Swift 프로젝트의 유닛테스트(Unit Test)
Xcode에서 새 프로젝트를 생성하면 기본적으로 (옵션을 해제하지 않으면) Test를 위한 타겟과 프레임워크를 자동으로 생성한다. 이 테스트 기능은 테스트 자동화나 TDD(Test Driven Development, 테스트 주도 개발)을 위해 사용되는 유용한 기능이다.
다만 스위프트(Swift) 기반의 프로젝트에서는 만들어 놓은 모듈을 테스트 할때 사소한 애로사항(?)이 있어서 이를 정리해 본다.
혹시나 Xcode 6 유닛테스트 가이드를 찾는다면 Xcode 6 유닛테스트 가이드 글을 참고하자.
스위프트 테스트 코드를 작성하기 위해서는 두 가지 종류의 준비가 필요하다.
Import Project
첫 째로, 테스트 코드에서 테스트 하려는 모듈이 포함된 프로젝트 자체를 프레임워크 형식으로 임포트(import) 시켜야 한다. 예를 들어 프로젝트 이름이 MySwiftProject 라면 아래와 같은 코드가 필요하다.
Access Control
다음으로는 테스트 하려는 코드의 엑세스 컨트롤을 살펴봐야 한다. 왜냐하면 테스트 코드는 타겟(target)이 다르기 때문이 엑세스컨트롤의 영향을 크게 받기 때문이다.
기본적으로 스위프트의 엑세스 컨트롤은 별 다른 지시어가 없는 이상 internal 이다. 이 키워드는 '동일 타겟 내에서의 자유로운 엑세스'를 의미하는데, 그래서 테스트에서는 internal로 명시된 모듈에 접근 할 수가 없다.
따라서 테스트 하려는 클래스나 메소드에는 아래와 같은 식으로 public 을 명시해서 테스트 타겟에서도 접근이 가능하게 해야한다.
Target Membership
위 두 가지 내용을 이용해도 되겠지만, 사실 더 쉬운 방법이 있다. 위의 방법은 타겟의 분리, 즉 프로젝트용 타겟과 테스트용 타겟이 분리되어 있기 때문에 해야 되는 것이다. 즉, 반대로 생각하면 테스트하려는 모듈을 테스트 타겟에 추가해주면 한방에 해결된다는 말이 된다.
이 방법은 굉장히 쉽다. 모듈을 생성 할 때 타겟을 지정해주거나, 혹은 해당 모듈을 선택하고 우측 파일 인스펙터(File Inspector)를 열어서 Target Membership 에서 테스트 타겟을 체크해 주면 된다.
위 스크린샷을 보면 쉽게 알 수 있다. 테스트하려는 파일을 테스트 쪽 타겟에도 추가해 준 상태다. 우측 인스펙터 창에서 Target Membership을 보자.
이 방법은 소스코드를 고치지 않아도 된다는 점에서 훨신 유용하다 -_-;
사실 앞의 내용은 좀 장황한 편이 있어서 이 방법을 추천해야 할 것 같다. 실컷 글 적어놓고 이런 방법이 있다는 것을 생각치 못 했기에 실컷 찍어놓은 스크린캐스트가 쓸 모 없게 된 기분이다. -_-;;;
[관련글] Xcode 6 유닛테스트(Unit Test) 기초가이드
[관련글] [Xcode] 비동기 루틴 유닛 테스트 (Asynchronous Unittest)
[관련글] Swift - 엑세스 컨트롤(Access Control)
[관련글] 스위프트(Swift) 가이드
다만 스위프트(Swift) 기반의 프로젝트에서는 만들어 놓은 모듈을 테스트 할때 사소한 애로사항(?)이 있어서 이를 정리해 본다.
혹시나 Xcode 6 유닛테스트 가이드를 찾는다면 Xcode 6 유닛테스트 가이드 글을 참고하자.
스위프트 테스트 코드를 작성하기 위해서는 두 가지 종류의 준비가 필요하다.
Import Project
첫 째로, 테스트 코드에서 테스트 하려는 모듈이 포함된 프로젝트 자체를 프레임워크 형식으로 임포트(import) 시켜야 한다. 예를 들어 프로젝트 이름이 MySwiftProject 라면 아래와 같은 코드가 필요하다.
import MySwiftProject
만약 프로젝트 이름에 일반적으로 사용해서는 안되는 공백(whitespace)이나 빼기기호(마이너스, dash, -)가 포함되어 있다면 이를 밑줄(_, underline 혹은 underscore)로 변환해서 정형화(normalize)해야 한다. 예를 들어 "My Swift-Project" 라는 프로젝트 명을 import 하려면 아래와 같이 코딩하면 된다.
import My_Swift_Project
만약 위 이름 규칙을 잘 모르겠으면 그냥 기본적으로 생성되는 테스트 파일의 이름을 보면 된다. 정형화된 프로젝트 이름 뒤에 Tests 라는 이름이 붙어있기 때문에 참고가 가능하다.Access Control
다음으로는 테스트 하려는 코드의 엑세스 컨트롤을 살펴봐야 한다. 왜냐하면 테스트 코드는 타겟(target)이 다르기 때문이 엑세스컨트롤의 영향을 크게 받기 때문이다.
기본적으로 스위프트의 엑세스 컨트롤은 별 다른 지시어가 없는 이상 internal 이다. 이 키워드는 '동일 타겟 내에서의 자유로운 엑세스'를 의미하는데, 그래서 테스트에서는 internal로 명시된 모듈에 접근 할 수가 없다.
따라서 테스트 하려는 클래스나 메소드에는 아래와 같은 식으로 public 을 명시해서 테스트 타겟에서도 접근이 가능하게 해야한다.
public class MyModule {
// ...
public func mySomeMethod() {
// ...
}
func anotherMethod() {
// this method cannot test from unittest code
}
// ...
}
이렇게 해 두면 테스트코드 내에서 XCTAssert 등을 활용해 테스트 자동화가 가능해진다.Target Membership
위 두 가지 내용을 이용해도 되겠지만, 사실 더 쉬운 방법이 있다. 위의 방법은 타겟의 분리, 즉 프로젝트용 타겟과 테스트용 타겟이 분리되어 있기 때문에 해야 되는 것이다. 즉, 반대로 생각하면 테스트하려는 모듈을 테스트 타겟에 추가해주면 한방에 해결된다는 말이 된다.
이 방법은 굉장히 쉽다. 모듈을 생성 할 때 타겟을 지정해주거나, 혹은 해당 모듈을 선택하고 우측 파일 인스펙터(File Inspector)를 열어서 Target Membership 에서 테스트 타겟을 체크해 주면 된다.
위 스크린샷을 보면 쉽게 알 수 있다. 테스트하려는 파일을 테스트 쪽 타겟에도 추가해 준 상태다. 우측 인스펙터 창에서 Target Membership을 보자.
이 방법은 소스코드를 고치지 않아도 된다는 점에서 훨신 유용하다 -_-;
사실 앞의 내용은 좀 장황한 편이 있어서 이 방법을 추천해야 할 것 같다. 실컷 글 적어놓고 이런 방법이 있다는 것을 생각치 못 했기에 실컷 찍어놓은 스크린캐스트가 쓸 모 없게 된 기분이다. -_-;;;
[관련글] Xcode 6 유닛테스트(Unit Test) 기초가이드
[관련글] [Xcode] 비동기 루틴 유닛 테스트 (Asynchronous Unittest)
[관련글] Swift - 엑세스 컨트롤(Access Control)
[관련글] 스위프트(Swift) 가이드
댓글