Blog

테스트 주도 iOS 애플리케이션 개발 4장 정리

March 1, 2014

테스트 주도 iOS 애플리케이션 개발 4장 정리

테스트용 도구

지금까지 테스트 주도 개발이 할 수 있는 것테스트 우선 코드를 작성하는 방법을 알아봤기 때문에 이 장에서는 사용할 수 있는 도구를 살펴본다.

  • OCUnit 프레임워크와 다른 도구(구글 툴킷, GHUnit, 캐차)의 장단점
  • 모의 객체를 만드는 프레임워크 (OCMock)
  • 테스트를 자동으로 실행하는 데 도움을 주는 지속적인 통합 도구 (허드슨, 크루즈컨트롤)

엑스코드를 이용한 OCUnit

OCUnit은 켄트 벡의 SUnit 프레임워크의 오브젝티브C 버전으로 완벽히 이식된 버전이다.

OCUnit의 주요 장점은 애플이 2.1 버전 이후로 엑스코드에 통합했다는 것이다. 그래서 OCUnit은 작업을 시작하고 빠른 결과를 얻기 가장 쉬운 단위 테스트 프레임워크다.

OCUnit은 실행 시간에 SenTestCase를 상속받은 모든 클래스를 발견하고 하나씩 픽스처로 초기화한다. 해당 클래스가 픽스처의 환경을 설정하려고 -setUp 메소드를 구현한다면 OCUnit은 테스트 전에 알아서 실행한다. 이와 유사하게 -tearDown 메소드를 감지해서 있다면 테스트한 후 수행한다. 또한 OCUnit은 각 픽스처가 구현한 모든 단위 테스트를 스스로 감지해서 테스트를 모두 수행하고 보고하려고 성공과 실패의 수를 기록한다. OCUnit이 테스트 메소드를 발견하게 하려고 메소드를 반환값과 매개변수가 없고 소문자 test로 시작하는 이름으로 선언해야 한다.

단위 테스트를 실행해야 하는 가장 중요한 순간은 빌드를 준비해야 할 순간이다.

터미널 애플리케이션이나 셀 스크립트 중 일부로 커맨드라인으로부터 테스트를 수행하는 것도 유용하다. 사실 지속적인 통합 시스템을 사용하려면 스크립트로부터 테스트를 실행할 필요가 있을 것이다.

엑스코드는 스크립트나 터미널에서 사용하기에 적합한 커맨드라인 도구인 xcodebuild를 가지고 있다. xcodebuild 도구는 테스트 실패 알림을 포함해 테스트 대상을 빌드하고 실행시키는 데 사용한 모든 명령을 출력한다.

OCUnit의 대안

맥용 구글 툴킷

맥용 구글 툴킷은 맥과 iOS 개발자에게 흥미롭고 유용한 유틸리티다. GTM의 테스트 기능은 추가적인 매크로를 제공해 OCUnit의 기능을 확장했다. OCUnit 매크로와 비교해서 이 매크로는 테스트 메소드를 더 짧게 해주고 한결 더 표현력이 좋게 해준다. 또한 로그 메시지가 기대한 것과 일치하는지 검증하는 모의 객체도 제공한다. 그리고 그래픽과 이미지 코드에 사용하기 편리한 범주도 있다.

GHUnit

GHUnit 프레임워크는 OCUnit과 구글 툴킷과의 호환성을 염두하여 만들어졌다. 실제로 양쪽 프레임워크에서 작성한 테스트 픽스처를 가져와서 변경 없이 GHUnit에서 사용할 수 있다. GHUnit의 주요 기능은 맥과 iOS용 사용자 정의 프론트 엔드다. 이는 키워드에 기반해 테스트 결과를 걸러낼 수 있는 기능을 제공하고 엑스코드보다 결과에 대한 표현을 더 잘 다룰 수 있게 해준다.

테스트를 실행하려면 앱의 빌드 스킴에서 테스트 옵션을 선택하지 않고 테스트 앱을 빌드하고 실행해야 함을 말한다. (테스트가 아닌 빌드&실행을 통해 테스팅)

캐차

캐차는 이 장에서 설명한 테스트 프레임워크 중 가장 최신이다.

캐차는 OCUnit에 기반한 프레임워크와 다른 접근 방법을 가지고 있다.

캐차는 C++로 구현했지만 C와 C++, 오브젝티브C 코드에서도 사용할 수 있다. 이름에서 연상할 수 있듯이 헤더에 모든 구현이 들어 있다. 또한 OCUnit류 프레임워크의 어써트 매크로의 모음 대신 setup과 teardown 메소드를 포함하는 규약과 테스트 메소드를 표시하고 어써트 처리기 안의 표현식을 감싸는 매크로를 포함하는 규약을 정의한다.

단위 테스트에 캐차를 사용하려면 테스트 픽스처를 반드시 오브젝티브C++ 파일로 컴파일해야 한다.(.mm) 캐차는 테스트 메소드를 찾으려고 모든 클래스를 뒤지기 때문이다. 픽스처 클래스에 OcFixture 프로토콜을 사용하는 것은 해당 클래스가 테스트 픽스처임을 설명하는 데 유용하다. 하지만 반드시 필요하지는 않기에 모든 OxFixture 메소드는 선택적이다.

OCMock

모의 객체는 테스트 주도 개발에 중요하다. 모의 객체가 없다면 부가작용이 있는 메소드를 자동으로 테스트할 수 없다.

부가작용은 메소드가 반환하는 값 이외의 모든 결과이다. 앱과 앱을 실행하는 기기는 상태가 있고 객체는 이런 상태를 읽거나 변경할 필요가 있다. 이를 테스트하려고 영향을 받을 객체의 모의 구현을 제공해야 할 필요가 있다.

OCMock은 모의 객체를 간단하게 만들 때 쓰는 프레임워크다. 다른 오브젝티브C 클래스의 인스턴스를 대신하는 모의 객체를 알아서 만들어주려고 오브젝티브C 런타임 인트로스펙선 기능(프로퍼티에 대한 정보를 프로그램에서 동적으로 접근하는 기능)을 이용한다.

OCMock은 모의로 만든 클래스의 동작을 찾고 교체하려고 오브젝티브C 실시간 라이브러리를 사용한다. 그래서 어떤 클래스라도 OCMock을 사용할 수 있다.

OCMock은 테스트 메소드의 마지막에 -verify 호출을 사용해 부가작용의 결과를 테스트한다. 예상한 이벤트가 모두 발생했다는 것을 보장하려고 모든 모의 객체에 대해 -verify를 호출할 필요가 있다.

기대를 충족시키지 못했다면 OCMock은 해당 문제를 설명하는 예외를 발생시킨다. 불행히도 이 예외는 테스트 실행기를 중단시킨다. 그렇기에 이외의 실패를 알려주지 않는다. OCMock이 테스트를 중단시키는 것을 막지 못한다.

지속적인 통합

지속적인 통합은 코드를 변경할 때마다 테스트를 자동으로 실행시켜줘서 테스트 주도 개발을 지원하는 도구다. 지속적인 통합 서버는 소스 코드 저장소를 관찰하고 변경이 발생하면 해당 변경을 받아와서 테스트를 실행한다.

지속적인 통합 자체는 매우 넓은 주제다. [지속적인 통합]을 참고. iOS 개발에서는 OS X Server로 CI Server 만드는 부분도 참고.

허드슨

허드슨은 자바로 작성한 웹 애플리케이션이다. 빌드를 실행하고 결과를 수집하는 것과 더불어 모든 프로젝트의 건강과 관련한 요약 정보를 보여주는 상황판을 포함해 종합적인 브라우저 기반 사용자 인터페이스를 제공한다.

크루즈컨트롤

크루즈컨트롤은 하나의 지속적인 통합 도구가 아니다. CruiseControl.net은 마이크로소프트 플랫폼에서 일하는 개발자용이다. 4장에서는 루비로 작성된 교차플랫폼 제품인 CruiseControl.rb에 집중하기로 한다.

허드슨과 크루즈컨트롤 모두 xcodebuild 도구를 이용해서 프로젝트를 테스트하고 빌드하는 작업을 만들어서 지속적으로 실행하게 한다.

요약

애플의 개발자 도구는 테스트 주도 개발을 사용하게 강력하고 원숙한 지원을 제공한다. 다양한 서드파티 대체 도구와 확장이 있어서 프로젝트와 일하는 방식에 알맞은 환경을 설정할 수 있다. 나머지 부분에 있는 예는 모두 OCUnit이 제공하는 기능에 초점을 맞출 것이다.


덧. Xcode 5부터는 XCTest가 기본 유닛 테스트 도구로 프로젝트가 생성된다. 따라서 OCUnit을 테스트하기 힘들다. 그리고 허드슨과 크루즈컨트롤은 직접 설치해보고 써보기 전에는 정확히 어떻게 동작하는지 알기가 힘들다.