...
본문 바로가기

Xcode

기존 프로젝트에 Unit Test 추가하기

 

늘 그렇듯 오랜만에 글을 쓰는듯 하네요 

 

Xcode에서 신규 프로젝트 만들면 자동으로 Unit test도 추가할건지 물어봐서 추가하기도 쉽고, 

추가하지 못했어도, 기존 프로젝트에 Unit test 추가하는것도 이전에 했었을때 쉬웠던 기억이 있다. ( 그냥 Target 하나더 추가하는거니까? )

 

새해 목표중 하나로.. 회사 프로젝트에 Unit Test 추가하여, 조금씩 테스트 코드 작성해보기로 다짐을 했었고, 추가하는 과정이 생각보다 쉽지 않았어가지고, 공유 하려고 글을 작성한다. ( 2-3일동안 붙잡은듯... ㅠ ) 

 

기존 프로젝트 상황

앱 말고도, extension으로 추가된 target이 있고, Build Phases에서 script를 사용하고있었음. 

프로젝트의 Configurations가 다양하고, Product module name이 Configuration마다 다름. 

Objective-c & Swift 혼재됨.

 

 

바쁜 분들을 위한 핵심 요약 

Xcode 인터페이스에서 Command + U (테스트빌드) 했는데, Test Succeedded는 뜨는데, 실제로 테스트코드는 실행이안된다 ? 

그렇다면 Command-Line으로 테스트빌드 해보길! 

 

Build Settings가 잘 맞게 되어있는지 확인. 

 

Add Target 

 

Add a Target해서 Unit Testing Bundle을 추가하면 된다. 매우 쉽다. 

 

 

Test Build 

command + U  를 누르면 테스트 빌드를 하는데, 여기서 부터 문제.. 

 

 

XCode 화면에 Test Succeeded 로 나타나나,  실제 테스트코드가 실행되지 않음. 😡

요렇게 테스트 빌드는 성공했다고 뜨나, 

 

좌측 Test 네비게이션바나, 테스트코드 작성화면에 초록색체크박스 또는 실패했다는 빨간색이 떠야하는데,  안뜸.  저 케이스 하나씩 클릭해도 테스트가 안됌.   ( 아래 캡처화면이 정상. ) 

 

이때부터 멘붕. 

 

다른 프로젝트 새로 생성해보고 하는데 이상한점이, Test Succeeded 알람뜬거보면 (null) 로 뜬다는점 확인.

빌드세팅도 크게 다를게 없어보였음. 

 

삽질을 하다가... 어쩌다보니 Command-Line도 보게됌. 

 

 

1. Command-Line 으로 테스트 빌드해보기. 

커맨드라인으로도 빌드해볼수가 있는데,  

아래 내용참고하여, 

https://medium.com/tauk-blog/running-xctests-from-the-command-line-f2e5ce0b4bfd

 

Running XCTests from the Command Line

Update: We’ve created a Discord server for discussing all things related to automation testing! Join our community today 👋:

medium.com

 

터미널열어서 아래처럼 실행해보았다. 

xcodebuild \
-workspace 프로젝트이름.xcworkspace \
-scheme 스킴이름 \
-destination 'platform=macos,arch=arm64' \
test

 

 

터미널에 로그가 쫘르르륵 찍히면서, 마지막에 빌드실패!! 라며 로그를 찍어주셨다. 😌

 

 

2. 로그 분석

 

첫번째 이슈로는, 프로젝트에 앱말고도 extension으로 추가된 target이 있는데,  해당 target을 찾을 수 없다라는 로그였다. 

Test target 테스트타겟이름 encountered an error 
(The bundle identifier for extension앱.app couldn’t be read. No such file or directory:

프로젝트의 Build phases에서 커스텀 Script를 실행하고있는데, 이 코드내용을 보면, 빌드를 할때, extension target도 빌드하여 바이너리로 생성되면서, 이 바이너리의 위치를 옮기도록 하는 내용이다. 

그러므로, 빌드할때 저 스크립트가 실행되면서 바이너리 위치가 변경되니, 테스트빌드할때 필요한 바이너리가 안보이니, 실패라고 뜨는것.

( 도대체 테스트빌드할때 extension target이 왜필요한지는 아직까지 모르겠음. )

솔직히 이런 이슈들을 Xcode 인터페이스에서는 에러처리를 안해줄법하다고도 생각이 들었다. 완전 엣지케이스같으니까? ( 하지만 너무하다. )

암튼, 코드내용을 보나, 최근 os를 보나,  이 스크립트는 인스톨할때만 필요해보여,  For install builds only 체크함.  

그럼 빌드 행위자체에서는 저 스크립트가 실행이 안되므로, extension target 바이너리의 위치가 옮겨지지 않으니, 이슈가 사라짐. 

 

 

이제다시 커맨드라인으로 다시 테스트 빌드해봤는데, 또 실패. 

 

 

두번째 이슈. 이번엔 빌드 돌리는 환경의 아키텍쳐가 없다함. 

보아하니, test target - Build settings - Architectures 가보니 excluded Architectures에 arm64가 있음. ( 나는 arm64 아키텍쳐인데 ) 그래서 요걸 없애줌. 

 

 

세번째 이슈.   test target - Build settings - Testing - Test Host 도 중요하다.

Host Application으로 설정한 앱의 바이너리를 사용해야하는데, 

 

이 위치의 이름이 잘맞는지 체크해야한다.  

 

해당 프로젝트는 Configurations가 많다. Alpha, beta, cbt, 등등..... 

그래서 해당 Configuration마다 빌드하게끔 해야할테고, 

빌드하고 생성된 바이너리의 이름도 다다르게 되어있었음. 

 

 

이렇게 하나하나 해결해주니, 테스트 빌드 드디어성공!!! 😭

 

 

테스트 빌드 성공했으나,  테스트코드에서 프로젝트 import가 안됨. ㅎ 🤪

( 테스트코드를 왜 작성하나 ? 내 프로젝트에서 사용되는 모듈, 로직 등을 테스트하기위함인데, 그러려면 내 프로젝트내의 코드를 사용해야하는데, 그러려면 import를 해줘야하는데.....! )

@testable import 내프로젝트이름

암튼 이게 안된다. 

 

테스트하는 Target ( 내프로젝트 앱)  - Builds Settings - enable testability 에 YES로 수정한다. 

 

추가적으로...

위의 Test Host와 비슷한 맥락으로, 해당 프로젝트는 Configurations가 많은데, 그에 따라 Product Module Name이 달랐다. 

 

다르므로, import할때도 다르게 작성해야한다. ( 같으면 상관없었을텐데 ㅠㅠ ) 

 

즉 Configration마다 다르게  import해야하는데, 그건 전처리구문으로 가능하다. 

아래처럼 전처리구문으로 작성하면된다.  ( 프로젝트 코드에서도 동일한 전처리구문을 사용해서 동일하게 작성했다. ) 

 

import 성공! 

 

import는 성공했으나... 외부 라이브러리를 찾을수없어서 테스트빌드 실패.😡

프로젝트에서 다양한 외부라이브러리를 사용하고 있다.

테스트코드에서 프로젝트에서 만든 클래스를 사용하려하니, 컴파일에러가 뜨는데, 보아하니, 해당 클래스에서 외부라이브러리를 쓰고있나보다. 

하지만 test target에는 외부라이브러리 접근이 없으니, Podfile을 열어서 아래를 수정하여, Pod install 해주었다.  ( Cocoapods으로 관리중 ) 

즉, 프로젝트가 가지는 모든 라이브러리들을 test target도 동일하게 상속받도록 하겠다는 뭐 그런뜻.. 

target 'TestTarget이름' do 
    inherit! :complete
end

 

 

이제 빌드 성공!!

 

테스트빌드 성공.. 했으나..  전처리구문이 실행이안됌 🤬

요건 내가 바보같았다.  전처리구문은 해당 target에만 사용이 되어지는거므로..  새로 만든 test target에도 Swift 전처리구문을 추가해줘야한다.  ( 아니면 상위 PROJECT에 추가해서 앱 target, test target 둘다 동일하게 사용가능하게끔 해도됌 ) 

 

앱 target에 전처리구문 에러나는곳이 몇군대있어서, 모든 Configuration 케이스에 맞게 추가해줬다.

 

 

이제 테스트 빌드해보니! 정상적으로 됐다!!

 

아래 코드는 테스트목적으로, 빨간색X가 떠야하는 상황이고, 전처리구문에 맞게 잘 실행됐다. 👍