http://code.google.com/p/python-nose/
http://somethingaboutorange.com/mrl/projects/nose/0.11.1/index.html
아.. 파이썬 모듈 임포팅은 정말 어색하구먼.
패키지라는놈을 써볼라 했는데 이게 또 아주 요상해서 코드를 따로 뽑아돌리기가 쉽질 않네. 이전에는 그냥 __name__ 체크해서 테스트 함수 쭉 돌려보는 식으로 했었는데 모듈/패키지가 복잡해 지니 테스팅 라이브러리가 필요해졌다.
일단 doctest 는 제꼈고 unittest 를 써보려고 했는데 이게 좀 쓰기가 성가시더라. 병신같은 JUnit 을 그대로 따온건지(JUnit 은 잘 모르겠다만) 테스트 케이스를 만드려면 클래스를 매번 추가해야 하고 이 케이스들을 수작업으로 등록해주거나 또는 케이스 찾는 코드를 직접 작성해줘야 하더라.
뭐 결국 nose 를 쓰면서 대부분의 불편함이 해결됐다.
우왕ㅋ굳ㅋ
헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤헤
2009년 8월 13일 목요일
2009년 1월 22일 목요일
MinUnit: C 에서 유닛 테스트 간단하게.
cmake 의 테스트를 주로 쓰는 편이라 테스트를 위해서 작은 바이너리들을 여러개 만드는 편인데 이 바이너리 코드들은 대부분 정형화 되어있다.
테스트할 함수 불러보고 리턴이 맘에 들면 조용히 지나가고 리턴이 맘에 안들면 뭐라뭐라 찍어주고 main 이 실패값을 리턴하도록 되어있는데 너무 뻔한 작업이다 보니 매크로를 쓰게 되고.. 그런데 이걸 그냥 즉흥적으로 하다보니 나중에 보면 매번 조금씩 다른 매크로를 만들었더라.
그러던 참에 List of unit testing frameworks 에서 MinUnit 을 구경하게 됐고 매크로만으로 이루어진게 내가 평소 하던 짓이랑 똑같아서 앞으로 이놈을 쓰기로 했다.
아예 minunit.h 파일을 새로 만들때마다 위 코드(의 수정버전)을 채워버리도록 emacs 에서 세팅하고 사용중.
2008년 6월 2일 월요일
boost test 프레임웍 최소한의 사용법
아 씨바 좃스팟이 로그인이 안되길래 일단 여기 적어둔다.
사무실에서 테스트해본거라 리눅스 환경.
a.cpp 는 워낙 간단하니 적지 않는다.
몇가지 포인트만 적어보면
사무실에서 테스트해본거라 리눅스 환경.
Makefile 소스 보기
CC = gcc
CXX = g++
LDFLAGS += -lboost_unit_test_framework
all: a.out b.out
a.out: a.o
$(CXX) $^ $(LDFLAGS) -o $@
b.out: b.o
$(CXX) $^ $(LDFLAGS) -o $@
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) -o $@ $< -MMD
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $< -MMD
clean:
-rm -f *.o *.d
-rm -f core
-rm -f a.out b.out
-include $(wildcard *.d)
a.cpp 는 워낙 간단하니 적지 않는다.
b.cpp 소스 보기
#define BOOST_TEST_DYN_LINK // 소스를 보니 boost_unit_test_framework 를 동적으로 링크하려면 이걸 디파인을 해줘야 하는듯.
// 실사용시라면 이자리 보다 Makefile 등에서 해주는게 맞겠지.
#define BOOST_TEST_MODULE test module name blahblah // 테스트 모듈의 이름을 define 으로 지정해 주는 모냥이군.
#include <boost/test/unit_test.hpp> // included 버전의 헤더를 쓴다면 링크를 피할수 있어서 편해지지만 빌드가 느려질거다
// 함수하나를 만들어서 자동으로 register 까지.
// 앵간한 경우라면 요 방법 하나만 알고 써먹어도 충분할듯.
// BOOST_AUTO_TEST_CASE 매크로를 이용해서 test case 를 추가.
BOOST_AUTO_TEST_CASE(test_sucks)
{
BOOST_CHECK(1); // assert 와 같은놈 참이면 pass 거짓이면 fail
BOOST_CHECK_EQUAL(1,1); // 두 인자 동등비교. 이게 굳이 필요한가? BOOST_CHECK 하나로 충분한거 아닌가
// 어쨌건 요런놈들을 test tools 라고 하는데 boost/test/test_tools.hpp 를 읽어보자.
int i = 0;
BOOST_TEST_CHECKPOINT("before divzero"); // 신기하구나. 시그널이나 트랩등이 걸린 경우는 가장 마지막 CHECKPOINT 를 찍어준다. 의심나는 구간 앞에 박아두면 된다.
i = 100 / i;
BOOST_TEST_MESSAGE("you sucks"); // 찍혀야 하는거 아닌가 안찍히네
// 아.. 이놈을 빌드해서 나온 파일을 실행할때 --log_level=all 이란 옵션을 주면 된다.
// 또는 환경변수에 BOOST_TEST_LOG_LEVEL=all 를 줘도 같은 효과.
// boost test 의 문서중 parameters 라는 부분을 찾아 읽어보자.
}
// 테스트 스위트를 만드려면 BOOST_AUTO_TEST_CASE() 와 BOOST_AUTO_TEST_SUITE_END() 매크로 를 쓴다.
// 스위트까지 만들어서 테스트를 할일이 있을까? 흠 fixture 를 써야 할 경우라면 필요하겠군.
BOOST_AUTO_TEST_SUITE(suite)
BOOST_AUTO_TEST_CASE(hello_suite)
{
}
// 중첩도 가능
BOOST_AUTO_TEST_SUITE(suite)
BOOST_AUTO_TEST_CASE(hello_inner_suite)
{
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()
// 좀 복잡한 테스트 스위트
BOOST_AUTO_TEST_SUITE(suite2)
struct adder {
adder() { BOOST_TEST_MESSAGE("setup fixture"); }
~adder() { BOOST_TEST_MESSAGE("teardown fixture"); }
int add(int x, int y) { return x+y; }
};
BOOST_FIXTURE_TEST_CASE(test_adder_1, adder)
{
// adder 의 non-private 멤버에 바로 접근이 가능
BOOST_CHECK_EQUAL(add(1,1),1);
}
BOOST_AUTO_TEST_SUITE_END()
몇가지 포인트만 적어보면
- header 파일을 인클루드 할때 included 아래의 헤더를 가져오면 이놈이 main 을 가지고 있어서 boost_unit_test_framework 를 링크할 필요가 없다. 단 이런짓을 하면 안그래도 느린 빌드속도가 더 느려질테니 불편해도 링크를 해서 쓰자. 이내용은 boost test 문서중에 FAQ 에 들어있다.
- 리눅스 환경에서 처음 빌드했을때 링크에러가 자꾸 났었다. 적당히 소스를 뒤져보니 BOOST_TEST_DYN_LINK 를 디파인해주지 않아서 생긴 문제. 물론 so 버전 말고 .a 를 링크해줘도 해결됐었겠지. 어쨌거나 이부분은 좀 거슬리는데.. 윈도환경에서도 테스트를 해보고 그럴듯하게 빌드시스템(Make, Cmake) 로 뽑아내는 방법을 찾아야겠다.
- 위에서 적은 경우는 BOOST_AUTO_TEST_CASE 를 이용해서 함수를 정의하면서 register 까지 해버린 경우인데 사실 코딩하다 보면 함수 정의와 register 를 따로 해야 하는 경우도 생기겠지... 난 이런식으로 테스트 코드와 릴리즈 코드가 섞이는것을 좋아 하지 않으니 그런 경우는 아예 적지도 않았다. 릴리즈 빌드에 테스트코드 넣는것은 아직 거부감이 든다.
- BOOST_CHECK_BLAHBLAH 류의 매크로가 여러가지 준비되어있다. 이놈들을 test tools 라고 하는데 위 주석에도 적었지만 boost/test/test_tools.hpp 를 참고하자.
- 테스트 스위트 는 BOOST_AUTO_TEST_SUITE 와 BOOST_AUTO_TEST_SUITE_END 매크로로 정의되며 중첩도 가능하다.
- 테스트 스위트를 쓴다면 결국 픽스쳐를 쓴다는 소리. boost test 의 샘플을 가져다가 잘 도는것을 테스트해봤는데 프리프로세서 풀어보고 소스를 읽어보려고 하니 좀 복잡하네.
- 위 예제에서는 스위트 안에 adder 란 클래스와 test_adder_1 이란 픽스쳐를 만들었는데 만약 test_adder_2 라는 픽스쳐를 만들어서 테스트를 하게 되면 adder 가 두번 생성 ( 정확히는 boost test 시스템이 만든 adder 의 서브클래스겠지 ), 이 되서 각각의 fixture 마다 다른 인스턴스를 보게된다. fixture 마다 완전히 독립되었다는것 명심하자. 하나의 인스턴스를 순서대로 이어받는식으로 작성이 가능한지는 모르겠다.
- 위에 적은 내용을 확인하려면 BOOST_TEST_MESSAGE 등의 매크로를 쓰면 된다. 기본값으로는 이걸로 메시지를 뿌려도 안찍히니 boost test 에 parameter 란걸 조정해줘야 하는데 실행파일을 실행할때 --log_level=all 라는 인자를 주거나 BOOST_TEST_LOG_LEVEL=all 란 환경변수를 주거나 하는등의 방법이 있다. 이내용은 boost test 문서중 parameter 를 참고.
피드 구독하기:
글 (Atom)