서론
의존성 주입 등을 공부하면서 "테스트가 쉬워진다."라는 문장을 자주 접했습니다.
오늘은 UnitTest가 무엇인지 알아보고, Xcode의 UnitTest 기능을 간단히 사용해보겠습니다.
UnitTest
UnitTest는 프로젝트의 특정 모듈이 의도된대로 정확히 작동하는지 검증하는 절차로,
모든 함수와 메서드에 대한 테스트 케이스를 작성하는 절차를 의미합니다.
작성한 프로그램이 의도대로 잘 동작하는지 검증하는 가장 작은 단위의 테스트라고 할 수도 있습니다.
작은 단위의 테스트이므로 테스트에는 의존성을 최소화해야 합니다.
따라서 각 객체의 관심사를 분리해야 하고, 이때 의존성 분리와 주입이 필요합니다.
저도 최근에 의존성에 대한 포스팅을 작성했는데요.
의존성 주입 DI(Dependency Injection)와 IoC(Inversion Of Control)를 먼저 보시면 도움이 되실 것 같습니다.
UnitTest가 필요한 이유
UnitTest가 필요한 이유는 미래를 위해서 입니다.
당장은 테스트 코드 작성에 들이는 시간이 아까울 수 있습니다.
하지만 프로젝트가 커지고 기능이 추가될 때마다 앱 전체를 다시 테스트하는 것은 비효율적이고 시간도 오래 걸립니다.
필요한 모듈만 부분적으로 테스트하면 시간이 절약되고,
어떤 모듈에서 문제가 발생하는지 빠르게 확인이 가능하기 때문에 디버깅도 쉬워집니다.
저는 작은 토이 프로젝트만 진행한 쩌리 초보 개발자이기 때문에 테스트 코드의 유의미한 필요성을 크게 느끼진 못했습니다.
그래서 다른 분의 포스팅 링크를 남겨둘테니 참고 부탁드립니다.
테스트 코드가 불가능하다는 이유와 그 이유가 그저 핑계인 이유를 말하고 있습니다.
Xcode 프로젝트 생성
프로젝트 생성 시 UnitTest를 추가할 수 있습니다.
Include Tests 체크박스를 체크하면 UnitTest 폴더가 생성됩니다.
이미 생성된 프로젝트에 Unit Test 파일을 추가하고 싶다면 Command + N을 누르고 Unit Test Case Class를 선택하면 됩니다.
Tests 폴더와 UITests 폴더가 생겼습니다.
이번 포스팅에서는 UITests는 보지 않고 Tests 폴더의 Tests 파일만 살펴보려고 합니다.
Tests 파일에는 아래 코드가 들어 있습니다.
setUpWithError 메서드는 테스트가 시작될 때 수행됩니다.
tearDownWithError 메서드는 테스트가 종료될 때 수행됩니다.
주석으로 제공되는 가이드대로 setUpWithError( )에서는 테스트에 필요한 데이터를 설정하면 되고,
tearDownWithError( )에서는 테스트가 종료될 때 해체하는 동작을 수행하면 됩니다.
공식 문서 랑크는 각각 setUpWithError와 tearDownWithError이니 참고하세요.
testExample은 테스트 코드 예시이며, testPerformanceExample는 코드의 실행 속도를 테스트하는 역할입니다.
이 두 개의 메서드는 삭제 후 각자 테스트 메서드를 작성하면 됩니다.
테스트 코드 작성
테스트 메서드는 반드시 test 키워드로 시작해야 하고,
테스트 코드는 아래 세 가지로 이루어집니다.
- given : 필요한 데이터를 세팅함
- when : 테스트 코드를 실행함
- then : 결과 확인
위 구성에 맞춰 간단하게 입력한 숫자가 소수인지 아닌지 판단하는 테스트 코드를 작성하겠습니다.
func testNumberIsPrime() {
//given
let number = 3
//when
let isPrime = isPrime(number)
//then
XCTAssertTrue(isPrime)
}
func testNumberIsNotPrime() {
//given
let number = 4
//when
let isPrime = isPrime(number)
//then
XCTAssertFalse(isPrime)
}
given에는 필요한 데이터인 숫자 데이터를 세팅했습니다.
when에서는 테스트할 메서드인 isPrime 메서드를 수행합니다.
then에서는 결과 변수를 체크합니다.
결과 변수를 체크할 때는 XCTAssert 메서드들을 사용합니다.
XCTAssertTrue는 결과가 true여야 테스트 통과, XCTAssertFalse는 결과가 false여야 테스트 통과입니다.
이외에도 nil일 때, non-nil일 때, 결과가 OOO일 때 등 조건에 대한 다양한 메서드들이 존재합니다.
이 메서드들은 https://developer.apple.com/documentation/xctest 에서 확인 가능합니다.
테스트 코드 실행
테스트 코드 실행은 Xcode에서 가능합니다. (당연한 얘기?)
Xcode 라인 쪽에 있는 마름모를 눌러서 테스트 메서드를 수행할 수 있습니다.
모든 테스트 코드를 한 번에 수행하고 싶다면
상위 객체에서 테스트를 수행하면 됩니다.
Xcode의 왼쪽 창에서도 수행할 수 있습니다.
개별로 수행한 모습입니다.
testNumberIsPrime 메서드의 마름모가 통과 표시로 변경되었습니다.
모듈 개별로 테스트가 가능하다는 것을 볼 수 있습니다.
로그창에서는 테스트 수행 정보를 볼 수 있습니다.
수행 속도도 나오기 때문에 유용합니다.
테스트 성공
두 테스트 케이스를 모두 수행해봤습니다.
3은 소수이기 때문에 true여야 하고, 4는 소수가 아니기 때문에 false여야 합니다.
데이터가 3일 때는 XCTAssertTrue로 통과했고, 4일 때는 XCTAssertFalse로 통과했기 때문에 제대로 구현되었다는 걸 알 수 있습니다.
테스트 실패
테스트 실패하는 경우를 봅시다.
func testNumberIsPrime() {
//given
let number = 6
//when
let isPrime = isPrime(number)
//then
XCTAssertTrue(isPrime)
}
6은 소수가 아니기 때문에 위 테스트는 실패해야 합니다.
테스트에 실패하면 위 사진처럼 X 표시로 마름모가 바뀝니다.
XCTAssert 메서드의 파라미터로 테스트 실패 시 표시할 문구를 설정할 수도 있습니다.
마무리
이렇게 UnitTest에 대해 간단히 알아보았습니다.
UnitTest를 통과했다고 완벽한 앱은 아니지만 필요한 모듈만 테스트할 수 있다는 큰 장점이 있습니다.
다만, 본 코드를 작성하는 시간만큼 테스트 코드를 작성해야 한다는 번거로움이 있고 Unit Test를 통과했다고 완벽한 앱은 아니니 여러 방면으로 주의가 필요합니다.
감사합니다.
참고
https://silver-g-0114.tistory.com/142
https://zeddios.tistory.com/48
https://fomaios.tistory.com/entry/iOS-Unit-Test에-대해서-간단히-알아보기
https://ios-development.tistory.com/334
https://www.kodeco.com/21020457-ios-unit-testing-and-ui-testing-tutorial
아직은 초보 개발자입니다.
더 효율적인 코드 훈수 환영합니다!
공감과 댓글 부탁드립니다.