Search

Unit Test 란?

 들어가며

유닛 테스트와 관련한 이전글(Unit Test 도전해보기)을 작성하면서 스스로 Unit Test에 대한 정의 내리기가 필요했습니다. Unit Test에 대한 필요성은 느꼈는데, Unit Test에 대한 얄팍한 지식을 가지고 “테스트를 해야겠다” 라고 느꼈던 거 같아서 얄팍했던 지식의 두께를 조금이나마 두껍게 만들어보려고 합니다.
⓵ Unit Test라는 게 뭐고, ⓶ 어떤 장점이 있어서 Unit Test를 해야만 하고, ⓷ Unit Test를 하게 된다면 어떤 점을 고려해서 테스트를 진행해야 하는지에 관해서 정리해보려고 합니다.

 Unit Test 란?

유닛 테스트(unit test)는 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차다. 즉, 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차를 말한다. - 위키백과
유닛 테스트는 우리가 작성한 코드가 의도한대로 작동하는지 검증하는 절차입니다. 소프트웨어로부터 작성한 소스 코드가 잘 작동한다고 피드백을 받는 것이죠. 유닛 테스트를 통해서 우리는 작성한 코드, 프로그램에 대한 확신을 가질 수 있게 됩니다.
유닛 테스트는 작은 단위(함수, 메서드)의 기능에 대한 유효성을 검증하는 역할을 하기 때문에, UI Tests나 Integration Tests보다 쉽게 테스트 코드를 작성하고 테스트를 진행해볼 수 있습니다.
유닛 테스트에서는 작은 단위의 기능에 대해서 하나 이상의 테스트를 진행해볼 수 있고, 각각의 조건에 대해서 유효성을 검증해볼 수 있습니다. 그렇다보니 무수히 많은 유닛 테스트 코드가 작성될 수 있게 됩니다.
가장 작은 단위를 검증하는 유닛 테스트는 테스트의 시작점이 됩니다. 유닛 테스트를 통해서 각 부분을 검증하고 그 부분들을 합쳐서 다시 검증하는 통합 테스트를 진행하게 됩니다. 통합 테스트를 통해서 서로 다른 모듈, 클래스 간의 상호작용의 유효성을 검증하고 나면, 실제 화면을 테스트해보는 UI Test를 진행하게 됩니다.
즉, 유닛 테스트가 선행되어야만 그 뒤에 진행되는 통합 테스트, UI 테스트가 온전하게 진행될 수 있게 됩니다. 작은 함수, 메서드들도 어떻게 작동할 지 모르는 상태에서 통합 테스트, UI 테스트를 진행하는 것이 과연 옳은 방식일까요..
유닛 테스트가 작은 단위를 검증한다는 건 알겠는데, 어떤 장점이 있어서 우리는 유닛 테스트를 해야만 할까요?

 Unit Test를 해야만 한다.

왜? 왜? 왜?
작은 단위의 함수가 잘 작동하는지 검증한다는 게 어떤 이점을 주는 걸까요? 테스트 코드를 작성한다고 해서 우리의 개발 환경이 조금이라도 개선이 되는걸까요? 네!!
문제점 발견이 쉬워지고,
코드 변경이 쉬워지고,
더 깔끔하고 재사용성이 좋은 코드를 작성하게 됩니다.
1.
문제점 발견
작은 유닛으로 쪼개진 프로그램은 각 부분이 다른 부분들로 고립되어 있기 때문에, 각 부분이 정확하게 동작하는지 검사하기 쉽습니다. 이 말은 곧, 어느 부분에서 문제가 발생하는지 정확하고 재빠르게 확인 가능하다는 뜻이 됩니다.
문제가 어디서 발생하는지 쉽게 알 수 있기 때문에 디버깅 시간이 단축됩니다.
2.
코드 변경 쉬움
서비스 요구사항, 리팩토링으로 인한 코드 수정이 필요한 상황에서 우리는 코드 변경에 두려움을 느끼게 됩니다. 해당 코드가 의도대로 작동할 지에 대한 확신이 없기 때문입니다.
하지만 유닛 테스트를 진행한다면 우리는 코드 수정이 필요한 상황에서 더 유연하고 안정적으로 대응할 수 있게 됩니다. 왜냐하면 해당 모듈이 의도대로 작동하고 있음을 유닛 테스트를 통해서 확신할 수 있기 때문이죠.
어떻게 고치더라도 문제점을 금방 파악할 수 있고, 수정한 코드가 잘 동작한다는 걸 확인할 수 있기 때문에 두려움없이 의욕적으로 코드를 수정할 수 있게 됩니다.
3.
더 깔끔하고 재사용성이 좋은 코드 작성
In the process of making our architecture more testable, we’ve made it better on all other axis. Testable design is very often good software design. - Marin Benčević 우리 아키텍쳐를 보다 더 테스트하기 쉽게 만드는 과정은, 코드를 다른 방면으로도 더 낫게 만들어 줄 것이다. 보통 테스트 가능한 설계는 좋은 소프트웨어와 직결된다.
유닛 테스트를 통해서 코드 품질은 향상될 수 밖에 없습니다. Testable한 설계에 초점을 맞춰서 코드를 작성해야 때문이죠. 모든 아키텍쳐가 유닛 테스트를 진행할 수 있는건 아닙니다. 유닛 테스트를 진행하는 단위는 독립적이어야 하기에 유닛 테스트를 진행하고 싶다면 앱 아키텍쳐를 주의깊게 만들어야 합니다.
⓵ 외부 프레임워크로부터의 분리
테스트 가능한(Testable) 아키텍쳐는 앱 컴포넌트를 독립적으로 만듭니다. 독립적이라는 건 외부 프레임워크로부터의 분리가 되어 있다는 의미입니다.
우리는 앱 개발 시에 UIKit를 자연스럽게 임포트하게 됩니다. UIKit도 외부 프레임워크입니다. 따라서 ViewController(Controller)를 Model과 View의 매개 역할로 사용하는 MVC 패턴은 Controller에서 UIKit이라는 외부 프레임워크를 임포트하기 때문에 외부 프레임워크로부터 영향을 받을 수 밖에 없습니다. 이는 컴포넌트를 독립적으로 만들지 못한다는 의미이기에 테스트가 불가능한 설계라고 볼 수 있습니다.
따라서, 뷰(UIKit)와 로직을 분리함으로써 ViewController 바깥에 로직을 둘 수 있는 MVP, MVVM 패턴은 테스트 가능성을 얻게 됩니다. 분리된 컴포넌트를 쉽게 테스트할 수 상태라는거죠.
만약, 여러분들의 코드 구조가 UI 없이 비즈니스 로직으로만 테스트할 수 없는 상태라면 코드 구조를 다시 고민할 필요가 있습니다.
⓶ Dependency Injection(의존성 주입)
유닛은 완전히 분리되어 있기에 앱의 각 컴포넌트를 독립시킬 필요가 있습니다. 그렇기 때문에 우리는 테스트하고 있는 각 클래스에 ‘약한’ 의존성을 제공하는 방법을 생각할 필요가 있습니다.
의존성 주입을 통해서 클래스에 외부적인 의존성을 제공하는 겁니다. 모든 의존성은 프로토콜 객체로 선언되며, 클래스가 필요로 하는 오브젝트를 메소드에 담아 우리가 원하는 클래스/구조체 객체를 초기화할 때 쉽게 전달할 수 있습니다.
클래스에 자체적으로 제어되는 종속성을 제공하여 나머지 부분으로부터 완전히 독립적일 수 있게 됩니다. 또한 클래스가 구현을 변경해도 다른 클래스가 구체적인 구현에 의존하지 않기 때문에 해당 클래스를 건드릴 필요가 없습니다.
4.
(+⍺) Active한 문서
유닛 테스트는 Active한 문서입니다. 최신 버전이 어떤건지 알 수 없는 주석, 외부 문서(Passive)보다 가시적인 방법으로 문서를 보여줍니다. 또한, 메서드에 올바르게 접근하는지 컨트롤할 수 있게 해줍니다. deprecated된 메서드를 deprecated 되었다고 표시할 수 있기 때문이죠.
많은 사람과의 복잡한 코드 베이스 작업에서 특히 유용하게 사용할 수 있습니다.

 고려 사항

지속적인 유닛 테스트 환경을 구축하는 것은 중요합니다. 어떤 변화가 있더라도 의도대로 되는지 검증이 가능하다는 의미이기 때문입니다. CI로 정기적인 빌드를 통해 테스트 코드 유효성을 확인하며, 테스트가 항상 실패없이 실행되도록 유지해야 합니다.
유닛 테스트는 Known, Fixed된 입력이 Known, Fixed된 출력을 내는지 확인하는 과정입니다. 따라서 잘못된 가정을 통한 유닛 테스트는 실패한 유닛 테스트가 됩니다. 우리가 유닛 테스트를 진행한다고 해서 좋은 성과를 거두는 것이 아니고 좋은 유닛 테스트를 작성해야만 좋은 성과, 의미있는 결과를 거둘 수 있습니다.
좋은 유닛 테스트 작성법, 작성 원칙들이 있는데 워낙 많고 양이 방대하다보니 후에 유닛 테스트를 직접 작성하면서 함께 정리하도록 하겠습니다.

 마치며

안정성 증가, 기능 개발 효율 증가, 코드 품질 증가.
유닛 테스트는 테스트에 소요되는 노력만큼 많은 성과를 거둘 수 있는 방법인 거 같습니다.
처음 테스트를 프로젝트에 적용하는 입장이라서 두려움이 크고 어떻게 해야할 지 모르겠지만 적용한 후에 프로젝트를 생각하면 뿌듯하네요.
일단 아키텍쳐부터 Testable하게 개선해야겠습니다. ٩(。•◡•。)۶
이렇게 하나씩 하다보면 어느새 테스트를 진행하고 있겠죠.. ٩(。•◡•。)۶

 참고자료