Visual Studio 의 단위 테스트의 문제

최근 가장 트랜드한 개발 방법론 중의 XP 에서는 단위 테스트 코드를 작성하도록 권장하고 있습니다. 단위 테스트는 그 코드를 작성하기에 많은 노력이 필요하지만, 그 이상의 가치와 편리함, 그리고 중요성 등을 잘 알고 있기 때문에 프로젝트의 대부분의 코드 또는 테스트 등은 단위 테스트를 작성합니다.

하지만 Visual Studio 의 단위 테스트에 치명적인 문제가 있었네요. 바로 Visual Studio 의 단위 테스트는 x64 를 지원하지 않습니다. 단위 테스트를 수행할 대상 프로젝트나 어셈블리가 x64 라면 단위 테스트를 수행할 수 없습니다. 만약 프로젝트의 속성의 빌드가 Any Cpu 또는 x86 이 아닌 x64 라면 테스트는 오류가 나고 맙니다.

먼저 단위 테스트 코드를 작성하여 단위 테스트를 수행하였습니다. 테스트를 실시하는 어셈블리는 x64 로 빌드된 어셈블리이고, 이것을 단위 테스트에 참조하여 사용하였습니다. 그리고 제가 사용하는 OS 는 Windows 7 x64 버전입니다.

이미 언급했지만, 프로젝트의 빌드 타입이 Any CPU 또는 x86 에서는 잘 돌아갑니다. 하지만 Unit Test 는 64비트 어플리케이션에 대해 BadImageFormatException 을 내뱉습니다. 일반적으로 BadImageFormatException 이라고 하면 어셈블리의 헤더 정보 등이 잘못되었거나 말 그대로 잘못된 이미지의 어셈블리일 경우 발생합니다.

테스트 메서드 MseServiceCatalogTest.ServicesImportTest.ServicesImportUnitTest.ServicesImportTest에서 예외를 throw했습니다. System.BadImageFormatException: 파일이나 어셈블리 'Microsoft.MSE.Tools.MetadataLoader.Module, Version=7.1.33.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 또는 여기에 종속되어 있는 파일이나 어셈블리 중 하나를 로드할 수 없습니다. 프로그램을 잘못된 형식으로 로드하려고 했습니다.

   

Visual Studio 단위 테스트는 x86 만 지원한다~?   

이리저리 검색해보니 Visual Studio 의 Unit Test 에서는 x32 어셈블리만을 로드할 수 있다고 합니다. 아마도 Unit Test Framework 가 x86 으로 빌드가 된 모양새입니다. 테스트 대상 프로젝트를 Any Cpu 로 맞추고 테스트 프로젝트를 x64 로 빌드하고 테스트를 수행해도 마찬가지 결과입니다.    

MseServiceCatalogTest.ServicesImportTest.ServicesImportUnitTest, MseServiceCatalogTest 형식을 가져올 수 없습니다. 오류: System.BadImageFormatException: 파일이나 어셈블리 'MseServiceCatalogTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 또는 여기에 종속되어 있는 파일이나 어셈블리 중 하나를 로드할 수 없습니다. 프로그램을 잘못된 형식으로 로드하려고 했습니다.

파일 이름: 'MseServiceCatalogTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
위치: System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)
위치: System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
위치: System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
위치: System.Type.GetType(String typeName)
위치: Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.GetType(UnitTestElement unitTest, String type)
위치: Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.ResolveMethods()

   

테스트 대상 어셈블리의 소스 코드가 없으면 어떡해~?    

그렇습니다. 소스 코드가 없으면 빌드 플랫폼을 변경할 수 없어서 단위 테스트를 수행하기가 참 곤란해 지겠지요. 하지만 뭐 방법은 없겠습니까만은 일부 제한적인 방법으로 x64 어셈블리를 x86 어셈블리로 변경할 수 있습니다.    

닷넷 어셈블리는 헤더 정보에 빌드 플랫폼 정보가 포함이 되어 있는데, 이것을 변경하면 됩니다. 그리고 .NET Framework SDK 에는 이러한 헤더를 변경할 수 있는 도구가 제공이 됩니다. 이 도구는 CorFlags.exe 로 CLR 버전을 업그레이드 하거나 x64 어셈블리를 x86 어셈블리로 헤더를 변경할 수 있습니다. 반대로 x64 어셈블리를 x32 어셈블리로 되돌릴 수 있습니다.    

덧붙여, .NET 1.1 어셈블리를 .NET 2.0 어셈블리로 변경하고 싶다면 이 방법으로 가능합니다. 또는 64비트 운영체제에서 32비트로 어셈블리를 변경하여 테스트 용도 등으로 사용할 수 도 있습니다.    

x64 어셈블리를 아래와 같이 x86 어셈블리로 변경할 수 있습니다.

C:\>CorFlags ClassLibrary.DLL /32BIT+

   

강력한 이름으로 서명된 x64 어셈블리는 어떻게?    

강력한 이름으로 서명된 어셈블리는 유감스럽게 CorFlags 로 헤더를 변경한 후에 다시 한번 강력한 이름으로 서명하면 됩니다. 유감스럽게도 만약 키 파일이 없다면 어셈블리를 사용할 수 없게 됩니다. 위에서 얘기 했듯이 이러한 이유로 제한적인 방법이라고 언급을 했습니다. ^_^;    

아무튼 저 같은 경우는 이 키 파일이 없어서 그만 OTL
그나마 다행인 것은 Visual Studio 2010 버전에서는 x64 어셈블리도 단위 테스트를 할 수 있다고 하네요.  

참고 문헌
CorFlags 변환 도구(CorFlags.exe)
http://msdn.microsoft.com/ko-kr/library/ms164699.aspx

 

신고
Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 강영수 2011.04.28 17:11 신고 Address Modify/Delete Reply

    좋은글 잘 보구 갑니다.