1. 예제 소스 실행법 (Using C++) ¶
- 먼저 프로젝트를 Managed C++ 클래스 라이브러리로 만든다.
- Test Fixture 될 클래스의 앞에는 TestFixture, 테스트 함수 앞에 Test 인 Attribute 를 붙인다.
- 속성 페이지 가서 C/C++로 간다음, #using 참조확인에다가 NUnit이 깔린 폴더의 bin 폴더를 넣어준다.
- 컴파일후 지정된 dll 파일이 생긴다.
- NUnit이 깔린 폴더의 bin안에 보면 NUnit-gui.exe을 실행한다. 컴파일해서 나온 dll을 로딩해주고 run하면 테스트들을 실행해준다.
- 예제는 아무 생각없이 만들었고, 테스트 할 필요도 없는 거지만.. 그냥 사용법을 보는 거니까 신경쓰지 마세요.
// NUnit6.h #pragma once #using <nunit.framework.dll> using namespace System; using namespace NUnit::Framework; namespace NUnitSamples { [TestFixture] public __gc class Calculator { int a, b; public: [SetUp] void Init(); [Test] void Add(); [Test] void Sub(); [Test] void Mul(); [Test] void Div(); }; }
// NUnit6.cpp #include "stdafx.h" #include "NUnit6.h" namespace NUnitSamples { void Calculator::Init() { a = 5; b = 7; } void Calculator::Add() { Assertion::AssertEquals(12, a+b); } void Calculator::Sub() { Assertion::AssertEquals(-2, a-b); } void Calculator::Mul() { Assertion::AssertEquals(35, a*b); } void Calculator::Div() { Assertion::AssertEquals(1.4, a/b); } }
2. 사족 ¶
- 헤더에다 다 구현해도 된다. 하지만 같은 이름의 cpp파일을 만들어줘야 하는것같다. 안그러면 Test없다고 안된다.
- namespace 귀찮으면 안만들어도 된다.
- 간결 버젼
// NUnit6.h #pragma once #using <nunit.framework.dll> using namespace System; using namespace NUnit::Framework; [TestFixture] public __gc class Calculator { int a, b; public: [SetUp] void Calculator::Init() { a = 5; b = 7; } [Test] void Calculator::Add() { Assertion::AssertEquals(12, a+b); } [Test] void Calculator::Sub() { Assertion::AssertEquals(-2, a-b); } [Test] void Calculator::Mul() { Assertion::AssertEquals(35, a*b); } [Test] void Calculator::Div() { Assertion::AssertEquals(1.4, a/b); } };
// NUnit6.cpp #include "stdafx.h" #include "NUnit6.h"
3. MFC에서 사용하기 ¶
VC++ 7.0의 MFC에서 NUnit을 써보자. 이것보다 좋은 방법이 있을듯한데... 인수군은 이방법밖에는 만들어내지 못했다.
- 일단 MFC 프로젝트를 만든다. 이것을 메인프로젝트라고 하자.
- 전체 솔루션에 Managed C++ Library 프로젝트를 새로 추가한다. 이것을 테스트프로젝트라고 하자.
- 테스트 프로젝트의 속성으로 들어가서 #using 참조에 nunit\bin폴더를 넣어준다.
- 테스트 프로젝트의 속성으로 들어가서 포함 디렉토리에 위의 메인프로젝트의 폴더를 넣어주자.
- 메인프로젝트의 속성탭에 가서 Managed C++ Extension을 체크해준다.
메인프로젝트에서 만든 새 클래스를 테스트 프로젝트에서 테스트하고 싶다. 어떻게 해야할까? 순진한 인수군은 #include <domain.h> 이렇게 하고, 테스트 클래스에 .h랑 .cpp 참조 넣어주면 될줄 알았다. 이것땜에 어제밤부터 삽질했다. 이렇게만 하면 안되고... 새로 만든 클래스를 일단 보자.
#pragma once class CDomain { public: CDomain(void); ~CDomain(void); int add(int a, int b); int mult(int a, int b); };평소대로 하자면 이렇게 하면 될것이다. 하지만 현재 프로젝트는 Managed C++ Extensions이다. 이것은 C++을 이용해서 .Net을 Platform위에서 프로그래밍을 하기 위하여 Microsoft에서 C++을 확장한 형태의 문법을 제안된 추가 문법을 정의해 놓았다. 이를 이용해야 NUnit이 C++ 코드에 접근할수 있다. 이경우 NUnit 에서 검증할 클래스에 접근하기 위해 다음과 같이 클래스 앞에 __gc 를 붙여서 선언해야 한다.
#pragma once public __gc class CDomain { public: CDomain(void); ~CDomain(void); int add(int a, int b); int mult(int a, int b); };__gc의 가 부여하는 능력과 제약 사항에 대해서는 __gc 을 참고하자. NUnit 상에서 테스트의 대상 클래스는 무조건 포인터형으로 접근할수 있다. 이제 테스트 클래스의 내용을 보자.
// TestCase.h #pragma once #using <nunit.framework.dll> using namespace System; using namespace NUnit::Framework; #include "Domain.h" // 포함 디렉토리에 메인프로젝트의 폴더를 넣어놨으므로 가능 namespace TestCase { [TestFixture] public __gc class Class1 { private: CDomain* m_pD; // Only Pointer public: [SetUp] void init() { m_pD = new CDomain; // delete 필요없다. } [Test] void testAdd() { Assertion::AssertEquals(7, m_pD->add(3,4)); } [Test] void testMult() { Assertion::AssertEquals(12, m_pD->mult(3,4)); } }; }이렇게 해주면 된다. 이거 알아내느라 엄청 삽질했다. 그런 의미로... NUnit 많이 애용해 달라. 혹시나 더 간단하고 좋은 방법 있으면 올려 주세요.
이 경우 Unmanaged C++ 코드에 대해서 적용할수 없다. 즉, MFC로 완성된 프로그램이라도, .Net Platform 이 없는 곳에서는 작동할 수 없다. (로직에 __gc 가 존재하므로)
류상민은 NUnit 과 Unmanged C++의 연결을 완전하게는 하지 못했다. Managed C++프로젝트와 Unmanged C++ 프로젝트 두개를 만들어 Managed C++ 코드에서 NUnit 을 이용해 Unmanaged C++ 에 접근해 테스트 코드를 작성했다. 하지만, .Net Platform에 미숙과, Managed C++ Extension의 몰이해, 프로젝트 관리와 의존성 문제에 봉착해 곧 벽에 부딪쳤다. 이 둘은 혼용할수 없음을 알았다.
Unmanaged C++에서 가장 좋왔던 방법은 Unmanaged C++ Project 두개를 만들어서, 한쪽으로 의존시킨후 assert 를 이용해 자체적인 Test Framework 을 작성해서 사용하는 방법이었다.
--NeoCoin
--NeoCoin
아.. gc를 쓰면 닷넷 플랫폼없는 곳에서는 쓸 수가 없겠네요. 그러면 이방법은 어떤가요? 일단 테스트할때는 테스트할 클래스에 __gc를 붙이잖아요? 나중에 배포할때는 __gc를 없애는 겁니다. 물론 Managed C++ Extensions의 문법을 쓰면 안되겠죠.(gc빼고) 매크로를 잘 쓰면 어떻게 될거 같기도 한데... --인수
현재는 Managed C++에 깊히 공부해 보지 않아서, 잘 모르겠다. 이것이 __gc를 붙였다 때었다 하는 문제인지 확신할수가 없다.
그것을 떠나서, MFC를 쓰면서 테스트를 하는 것이 의미 있어 지려면, MFC 로 작성한 프로그램이 정상 동작하면서, 테스트를 할수 있어야 하는데, MFC Frameworks 이 Managed C++ 모드로 컴파일이 잘되고, 잘 돌아가는지, 이것이 의문이다. 된다면, MS에서 모든 MFC class앞에 __gc가 붙이기라도 한걸까? 혹은 이미 해당 매크로가 존재하지 않을까?