Swift + iOS/iOS

[ios] Xcode에서 Unit Test를 해보다

군옥수수수 2018. 7. 21. 22:46

[ios] Xcode에서 Unit Test를 해보다


안녕하세요. 오늘은 프로그래밍 공부를 시작하면서 처음으로 테스팅이라는 것을 해본 경험을 기록해보고자 이렇게 글을 작성하게 되었습니다.


사실 TDD, 유닛 테스트 등 여러 테스팅에 관련된 이야기를 들어만 봤을 뿐 이것을 해볼 시도도 하지 않았고 그렇게 중요하게 생각도 하지 않았습니다.


하지만 Let us: Go! 2018 밋업에서도 주제로 언급이 되었었고 연사분께서 하신 말씀 중 새로운 것을 두려워하고, 낯선 것을 두려워하기 때문에 TDD를 팀에 도입하기 힘들다는 말씀에 저 스스로 너무나 부끄러웠습니다.


하지만 다행히 저또한 해볼 수 있는 기회가 생겨서 굉장히 초보적이고 거창한 테스팅 코드는 아니지만 이를 통해 나름 뿌듯한 경험을 하게 되어 이렇게 글까지 작성하게 되었습니다.


물론 어느정도 찾아보고 공부를 한 후 글을 작성하는 것이지만 이는 저의 단순한 경험기이고 명확하지 않은 의미 전달과 잘못된 정보가 내포되어 있을 수 있습니다. 이점 양해 부탁드리며 많은 피드백 역시 부탁드리겠습니다.


Testing with Xcode

먼저 저는 개발자 문서를 가장 먼저 찾아보았습니다. 그리고 이곳에서 설명하는 내용 중 제가 이해하게 된 부분을 먼저 간략하게 정리해보려 합니다.


이 부분에서는 테스팅의 방법론이나, 좋은 테스팅 코드를 작성하는 법 등이 아닌 단순히 테스팅의 목적, Xcode에서 테스트 코드를 작성하는 방법과 각 메뉴, 메소드들의 역할들에 대해서만 이해하였습니다.

테스팅 준비하기

먼저 유닛 테스트를 진행하기 위해서는 테스트 타겟을 생성해야 하고 현재 프로젝트와 연결시켜주어야 합니다. 이를 위해서는 두 가지 방법이 존재합니다.


1. 프로젝트 생성시 함께 만들기

프로젝트를 생성하실 때 Include Unit TestInclude UI Tests 항목을 선택하시게 되면 테스트 코드의 뼈대가 포함된 프로젝트를 함께 생성하실 수 있습니다.


2. 추후에 만들어 포함시키기

만일 항목을 선택하지 않고 프로젝트를 생성하였다면 다음과 같은 방법으로 테스트 코드를 만들어 포함시킬 수 있습니다.

먼저 Navigator의 왼쪽에서 여섯 번째 항목으로 들어간 후 하단의 + 버튼을 눌러 추가할 수 있습니다.


만일 유닛 테스트 타겟을 생성한다면 다음과 같이 Target to be Tested 항목에서 테스트할 프로젝트를 선택해주어야 합니다. 이것이 끝이 아니라 마지막으로 테스트의 대상이 되는 프로젝트의 파일들에서 테스트 타겟을 타겟 맴버쉽으로 포함시켜야 합니다. 그래야 테스트 타겟에서 테스트의 대상이 되는 모듈에 접근이 가능하기 때문입니다.



부끄러운 사실이지만 저는 이것조차 하지 못해 굉장히 해맸습니다....!!

간단한 테스트 코드 작성해보기

이렇게 테스트 타겟을 생성하게 되면 이와 함께 테스트 클래스가 생성됩니다.


먼저 setUp 메소드부터 살펴보면 이 메소드에서는 이 테스트 클래스에서 진행되는 모든 테스트 케이스에서 공통으로 필요로 하는 행위들을 정의해줍니다. 즉 클래스 안에 속하는 테스트 메소드들이 호출되기 전 항상 setUp 메소드가 호출되는 것입니다.


예를 들자면 각 테스트 케이스에서 필요한 객체를 이곳에서 생성해줄 수 있습니다.


그 다음으로는 tearDown 메소드입니다. setUp 메소드와 유사하지만 그 반대로 모든 테스트 케이스 메소드들이 종료된 후 호출되는 메소드로 setUp에서 생성되고 테스트 메소드에서 사용된 것들을 정리해주고 해제할 필요가 있을 때 해당 내용들을 tearDown에 작성해주면 됩니다.


그럼 테스트 메소드를 작성해볼까요?


테스트 메소드는 test 접두어를 붙인 메소드로 이런 접두어가 붙은 메소드 옆에는 다이아몬드 모양이 생기고 우리는 그 버튼을 눌러 테스팅을 진행할 수 있습니다. 그리고 각 케이스는 하나의 메소드로 분리하여 작성해야 합니다. 테스트 메소드도 메소드로 하나의 기능만을 수행해야하기 때문에 하나의 테스트 메소드 안에 여러 케이스를 넣는 것은 올바른 방법이 아닙니다.


그리고 우리는 XCTAssert... 계열 메소드를 사용하여 기대 값과 실제 결과 값을 비교하여 테스트 수행 결과를 확인할 수 있습니다.


XCTAsset 계열 메소드는 공식 문서에서 확인해보실 수 있습니다.


만일 pow(3) 의 결과가 9가 아니라면, 즉 기대 값과 테스트의 대상이 되는 메소드의 결과 값이 같다면 XCTAssertEqual 메소드를 무사히 통과하겠지만 그렇지 않다면 테스트에 fail 했다는 안내와 함께 결과 값이 올바르지 않습니다.라는 문구가 함께 출력될 것입니다.


저는 이러한 테스팅을 하는 방법도 방법이지만 좋은 테스팅, 올바른 테스팅에 대해 궁금하였습니다. 여러 글들을 보아도 테스팅에 대한 경험이 전무하기 때문에 와닿지는 않았지만 "이런거구나~" 정도의 감만 익히는 수준으로 글들을 빠르게 읽어갔습니다.


그리고 제가 이해한 것들을 바탕으로 좋은 테스팅과 올바른 테스팅에 대해 간략하게 정리해보았습니다.


FIRST


  • Fast - 테스팅은 빠르게 동작해야 한다.
  • Independent / Isolated - 독립적이어야 한다.
  • Repeatable - 동일한 인풋의 테스팅의 결과는 항상 동일해야 한다.
  • Self-Validating - 테스트는 완벽히 자동화되어야 한다. 그 결과 자체로 성공과 실패를 알 수 있어야 한다.
  • Timely - 이상적인 테스트 코드는 테스트할 코드를 작성하기 전 작성되어야 한다.

Given, When, Then

Given, When, Then으로 섹션을 나누어 작성하는 습관을 기르자


  1. Given - 입력 값을 제공
  2. When - 입력 값을 사용해 테스트의 대상이 되는 메소드를 실행
  3. Then - 결과 값을 증명 (기대값과 비교)

위의 예시에 이를 적용한다면 다음과 같습니다.


Asynchronous Test

비동기 코드에 대한 테스팅은 대체로 느리기 때문에 보다 빠른 테스트 코드와 분리시켜야 한다.


Fail Faster

테스트를 진행하다보면 당연히 실패하는 케이스도 있습니다. 하지만 그 실패하는 케이스는 되도록 빠르게 결과를 내뱉어야 합니다. 이게 무슨 뜻인지는 코드를 통해 살펴보도록 하겠습니다.


여기서 요청(request)에 대한 기대 응답을 5초동안 기다리는 것이 아닌 그 결과가 나오는 즉시 실패에 대한 결과를 보여주는 것입니다.


마무리

테스팅에 대한 많은 얘기들이 오고가는 글들이 존재합니다. 하지만 이제 막 테스트를 처음 해본 저에게는 아직 와닿지 않는다거나 하는 글들이 많았습니다. 하지만 확실히 왜 테스트 코드를 작성하고 이를 적극 도입하려는 움직임이 생기는지는 조금씩 이해가 가기 시작하였습니다.


미래에 이 글을 보게 된다면 웃음이 날 정도로 기초적이고 당연하며 올바르지 않은 내용이 담겨있을 수 있는 글이지만 이 글을 시작으로 테스트에 보다 더 적극적이고 열린 마음으로 임해야겠습니다. 감사합니다.


굉장히 두서 없는 글이지만 혹여나 틀린 정보가 있다면 많은 피드백 부탁드리겠습니다.