최근 업데이트: 2019년 12월, 6분 소요

Unity 테스트 프레임워크로 게임 코드 테스트

이 페이지의 내용: Unity 테스트 프레임워크(UTF)를 사용해 프로젝트의 QA를 진행하는 방법에 대한 팁을 소개합니다. UTF는 품질 보증을 위해 가장 중요한 툴 중 하나입니다. UTF는 에디터와 지원되는 플랫폼 모두에서 자동으로 테스트를 실행하는 데 사용됩니다. 그리고 Unity 사용자 누구나 사용할 수 있습니다.  

새 Test Runner API를 사용하면 UTF에 더 큰 유연성과 확장성을 제공하여 테스트 요구 사항의 대부분을 충족할 수 있습니다. 이 API는 Unity 패키지 관리자를 통해 사용 가능하며, 이를 통해 더 빠르게 버그를 수정하고 새로운 업데이트를 배포할 수 있습니다. 즉, UTF의 소스 코드에 로컬로 액세스할 수 있습니다. 디버깅 시 소스 코드를 차근차근 확인하여 수정할 수 있습니다.  

더 자세한 내용은 Unity의 툴 및 테스트 개발자 리처드 파인(Richard Fine)과 크리스천 워넥(Christian Warnecke)이 진행한 유나이트 코펜하겐의 UTF 세션을 확인하세요.

Unity 테스트 프레임워크로 게임 코드 테스트

Unity 테스트 프레임워크 시작하기

Unity 테스트 프레임워크(UTF)가 처음인 경우, 입문을 위한 기술 자료를 읽어보시기 바랍니다. 간략히 말해, Unity 사용자는 UTF를 사용해 편집 모드와 플레이 모드 모두에서 코드를 테스트할 수 있으며, 스탠드얼론, Android, iOS 등과 같은 타겟 플랫폼에서도 코드를 테스트할 수 있습니다.

UTF는 .NET 언어용 오픈 소스 유닛 테스트 라이브러리인 NUnit 라이브러리의 Unity 통합을 사용합니다. NUnit에 관한 자세한 정보는 공식 NUnit 웹사이트를 참조하거나 Github의 NUnit 기술 자료를 확인하시기 바랍니다. 

입문자에게는 아래 블로그 게시물이 유용합니다.

Unity로 성능 벤치마킹을 시작하는 방법

Unity 테스트 러너를 통한 테스트 중심의 개발 테스트

Test Runner API에 대한 개요

Test Runner API(아래 API 참조)를 통해 어떤 스크립트에서나 프로그래밍 방식으로 테스트를 진행할 수 있습니다. 이 API를 사용하면 모드를 실행하지 않고도 편집 모드와 플레이 모드 모두에서 실행할 수 있는 테스트의 목록을 검색해서 가져올 수 있습니다. 각 테스트의 시작과 완료 시점에 일부 등록/등록 해제 콜백에 연결할 수 있으며, 테스트 주기 내의 각 레벨, 즉 전체 테스트 어셈블리, 개별 테스트 픽스처, 각 테스트 클래스 및 테스트에서도 연결할 수 있습니다. 

각 테스트를 시작할 때 실행하려는 테스트 경로에 대한 정보를 받을 수 있습니다. 테스트가 완료되면 테스트 결과를 볼 수 있습니다. 

또한 Unity 에디터의 플레이 모드에서 UTF를 실행하는 것 외에도 새로운 커스터마이징 포인트로 타겟 디바이스에서 UTF를 실행할 수 있습니다. 이는 플레이어를 빌드하기 전에 호출되며, 테스트 실행 설정을 변경하고 빌드 위치를 지정하기 위해 플레이어 빌드 옵션을 수정할 수도 있습니다.

TestRunnerAPI.cs (C#)
void Execute(ExecutionSettings executionSettings);
void RegisterCallbacks<T>(T testCallbacks, int priority = 0) where T : ICallbacks;
void UnregisterCallbacks<T>(T testCallbacks) where T : ICallbacks;
void RetrieveTestList(TestMode testMode, Action<ITestAdaptor> callback);

빌드 분할 및 실행

빌드를 분할하고 실행하는 프로세스는 로컬 기기에 연결되지 않은 타겟 디바이스에서 테스트를 실행할 때 유용합니다. 예를 들어 하나 혹은 여러 개의 타겟 디바이스가 클라우드에 있는 경우 유용합니다. 

이를 위해서는 테스트 플레이어 빌드 프로세스 자체를 먼저 커스터마이즈해야 합니다. 그 방법은 다음과 같습니다. 

  • 플레이어를 빌드한 후에는 테스트를 실행하지 않도록 AutoRun을 비활성화합니다. 
  • 기본으로 저장되는 위치인 시스템의 임시 폴더가 아닌 다른 위치에 저장합니다. 

그런 다음 콜백 인터페이스를 사용해 플레이어 측에 커스텀 결과 보고서를 추가하여 모든 결과를 캡처하고 이를 XML 파일 또는 프로젝트에 적합한 형식으로 저장합니다. 

빌드 분할 및 실행에 대해서는 다음 코드 예제를 참조하시기 바랍니다. 유나이트 세션(6분 28초)에서 리처드 파인은 이 애플리케이션의 빌드와 결과 보고서 부분에 대한 코드를 단계별로 소개합니다.

빌드 분할 및 실행: 빌드

빌드:

 

SplitBuildAndRun:build.cs (C#)
[assembly:TestPlayerBuildModifier(typeof(SetupPlaymodeTestPlayer))]
public class SetupPlaymodeTestPlayer : ITestPlayerBuildModifier {
   public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions) {
   	playerOptions.options &= ~(BuildOptions.AutoRunPlayer | BuildOptions.ConnectToHost);
   	var buildLocation = Path.GetFullPath("TestPlayers");
   	var fileName = Path.GetFileName(playerOptions.locationPathName);
   	if (!string.IsNullOrEmpty(fileName))
       	buildLocation = Path.Combine(buildLocation, fileName);
   	playerOptions.locationPathName = buildLocation;
   	return playerOptions;
   }
}

빌드 분할 및 실행: 실행 결과 저장

실행: 

SplitBuildAndRun:SaveResults.cs (C#)
[assembly:TestRunCallback(typeof(ResultSerializer))]
public class ResultSerializer : ITestRunCallback {
   public void RunStarted(ITest testsToRun) { }
   public void TestStarted(ITest test) { }
   public void TestFinished(ITestResult result) { }
   public void RunFinished(ITestResult testResults) {     
   	var path = Path.Combine(Application.persistentDataPath, "testresults.xml");
   	using (var xw = XmlWriter.Create(path, new XmlWriterSettings{Indent = true}))
       	testResults.ToXml(true).WriteTo(xw);
   	System.Console.WriteLine($"***\n\nTEST RESULTS WRITTEN TO\n\n\t{path}\n\n***");
   	Application.Quit(testResults.FailCount > 0 ? 1 : 0);
   }
}

메뉴 항목에서 특정 테스트 실행하기

개발자가 유효성 검사를 작성할 때 종종 콘솔 창에 결과가 표시되는데, 이로 인해 메시지가 쌓이면서 결과를 놓칠 수 있습니다. 에디터 내 특정 위치에 결과를 명확하게 표시해 주는 테스트 도구 모음을 통해 유효성 검사 결과를 얻을 수 있다면 어떨까요? 메뉴 항목에서 특정 테스트를 실행하면 가능합니다.  

다른 에디터 확장 메뉴 항목과 완전히 동일한 방식으로 MenuItem에 연결된 메서드를 사용하면 됩니다. 이 메서드는 스크립터블 오브젝트 콜백 오브젝트를 생성합니다. 일반적인 클래스 대신에 스크립터블 오브젝트를 사용해 콜백을 그대로 유지하면서 도메인 리로드를 발생시키는 등의 테스트를 진행할 수 있습니다. 스크립터블 오브젝트가 활성화되면 콜백에 등록되고, 비활성화되면 등록 해제됩니다. 

그런 다음 필터를 설정합니다. MenuItem에 대한 테스트를 실행할 때 특정 카테고리 또는 그룹에 대한 테스트를 실행하는 경우가 있습니다. 필터를 사용하면 테스트를 비동기식으로 실행할 수 있습니다. 여러 프레임에 걸쳐 테스트가 실행되기 때문에 테스트 중에 UnityTest, UnitySetUp, UnityTearDown이 엔진 루프를 검증할 수 있습니다. 테스트가 완료되고 RunFinished를 등록하면 워크플로에 적합하게 메시지를 표시하거나 결과 창을 열도록 설정할 수 있습니다.

아래 코드 예제를 참조하세요. 리처드는 유나이트 세션(11분 50초)에서 이 애플리케이션의 코드 설정에 대해 설명합니다.  

LaunchTestsFromMenuItem.cs (C#)
public class RunTestsFromMenu : ScriptableObject, ICallbacks {
   [MenuItem(“Tools/Run useful tests”)] public static void DoRunTests() {
   	CreateInstance<RunTestsFromMenu>().StartTestRun();
   }
   private void StartTestRun() {
   	hideFlags = HideFlags.HideAndDontSave;
   	CreateInstance<TestRunnerApi>().Execute(new ExecutionSettings {
       	filters = new [] { new Filter{ categoryNames = new[] { “UsefulTests” }}}
   	});
   }
   public void OnEnable() { CreateInstance<TestRunnerApi>().RegisterCallbacks(this); }
   public void OnDisable() { CreateInstance<TestRunnerApi>().UnregisterCallbacks(this); }
   /* ...RunStarted, TestStarted, TestFinished... */
   public void RunFinished(ITestResultAdaptor result) {       
   	…
   	DestroyImmediate(this);
   }

빌드 전에 테스트 실행하기

빌드 프로세스에서는 테스트를 콜백에서 실행해야 하고, 이로 인해 엔진 업데이트 루프를 만들 기회가 없으므로 빌드 전에 테스트를 실행하는 것은 까다로울 수 있습니다. 하지만 빌드 전에 테스트를 실행하면 일부 프로젝트의 경우 시간이 오래 걸리는 실제 제작에 시간을 소비하기 전에 기본 기능이 작동하는지 확인할 수 있다는 이점이 있습니다. 

다른 빌드 프리프로세싱 구현과 동일한 방식으로 IPreprocessBuildWithReport 인터페이스를 사용해 해당 애플리케이션을 구현할 수 있습니다. 결과를 얻으려면 평소처럼 콜백을 등록하면 됩니다.

빌드 도중에 플레이 모드에 진입할 수 없으므로 Test Runner API를 사용하여 편집 모드에서 특정 테스트를 실행할 수 있습니다. 사전 빌드 유효성 테스트 카테고리와 같이 카테고리별로 필터링하여 원하는 테스트를 선택할 수 있습니다. 이러한 테스트는 동기식으로 실행할 수 있습니다. 

테스트가 완료되면 결과를 확인하세요. 어떤 부분이 테스트를 통과하지 못한 경우 빌드 프로세스를 중단시키는 BuildFailed 예외가 발생할 수 있습니다. 

이 애플리케이션은 ResultCollector와 프리프로세서로 나눌 수 있으며 리처드의 강연(15분 20초)에서 자세히 확인할 수 있습니다. 

크리스천과 리처드의 Test Runner API 시연을 라이브로 시청할 수 있습니다. 전체 세션을 시청하고 더 많은 QA 팁을 얻으세요. 

RunTestsBeforeBuild.cs (C#)
   public ITestResultAdaptor Result { get; private set; }     
   public void RunStarted(ITestAdaptor testsToRun) { }
   public void TestStarted(ITestAdaptor test) { }
   public void TestFinished(ITestResultAdaptor result) { }
   public void RunFinished(ITestResultAdaptor result)
   {
   	Result = result;
   }
}

이 콘텐츠가 마음에 드셨나요?

Unity에서는 최적의 웹사이트 경험을 제공하기 위해 쿠키를 사용합니다. 자세한 내용은 쿠키 정책 페이지를 참조하세요.

확인