manywaypark's Blog
개발, 검색, 함수

복잡할 것없고 그냥 환경 변수 설정한다.

rebar.config에서 설정하려고 많이 검색했네... Orz.

ERL_FLAGS="-name foo@127.0.0.1 -setcookie bar" rebar skip_deps=true eunit


ref: http://stackoverflow.com/questions/10307575/passing-runtime-arguments-to-erlang-when-running-rebar-eunit


happy hackin'

[BR] EUnit Bug Report

함수형 언어/Erlang 2008. 12. 24. 18:25 by manywaypark
맨 마지막 테스트 함수의 테스트 준비단계가 2번 실행되는 버그가 있는 것같다.
나의 test case가 성공할 때도 있고 실패할 때도 있는 이상한 상태가 되어서 내 잘못인 줄 알고 개발중인 모듈의 여기저기를 손댔다가 갑자기 느끼는 바가 있어 EUnit을 테스트하는 간단한 코드를 만들었다.

일단 공식적으로 버그 리포트는 했고,
참고를 위해 글을 남긴다.

last_test_() ->
do_some_prep(), % 요놈이 매번 두번씩 불린단 말씀.
... do some tests ...
do_some_prep()가 두번 불려지면 당혹스런(?) 테스트 실패가 나올 수 있다. disk i/o나 DB operation 처럼 side effect가 있는 경우에 특히 테스트가 통과될 때도 있고 안될때도 있는 불안정한 상태가 될 수 있다.

happy hackin'

ps. 글을 쓰고 좀더 만져 보니 조금 더 복잡하다. EUnit 사이트에 올린 케이스들 말고 테스트 케이스를 다음과 같이 하면...

twice_case1_test_() ->
    io:format("c1: prep one~n"),
    ?_assert(1 + 1 =:= 2).

twice_case2_test_() ->
    io:format("c2: prep one~n"),
    ?_assert(1 + 1 =:= 2).

twice_case3_test_() ->
    io:format("c3: prep one~n"),
    ?_assert(1 + 1 =:= 2).

결과:
(emacs@desktop)14> eunit_twice_case:test().
c3: prep one
c2: prep one
c3: prep one
c2: prep one
c1: prep one
  All 3 tests successful.
ok
마지막에 있는 두개가 두번씩 불린다.

2008-12-31 "by design" 이라는군요 Orz. side effect가 있는 함수는 준비단계에서 부르면 절대 안되겠습니다.
좀 복잡한 테스트 케이스를 하나 추가하고 컴파일후 mod:test()를 실행했더니,
다음과 같은 에러가 나면서 그 모듈에 대한 유닛 테스트가 아예 동작하지 않았다.
*** test module not found ***
::false

{error,{module_not_found,false}}

순간 당황했으나, 방금 추가한 테스트 케이스를 살펴보니 _assert macro에 들어가는 내용이 잘못되어 있었다. boolean expression이 들어가야하는 곳에 그냥 expression만 하나 들어있었고, _assert(very_complex_expression) =:= expected value의 형태로 되어 있었다(어제 급히 추가하고 안돌려보고 바로 퇴근한 것이 후회되는 순간이었다). 그래도 컴파일은 멀쩡히 평소처럼 잘 되고 runtime에 가서야 에러가 나는 것은 좀 불편해보인다.

간략히 축약해서 예를 들자면 다음과 같다.
%% causes runtime error (see above msg).
?_assert(1+1) =:= 2
%% runs well w/o runtime error (good)
?_assert(1+1 =:= 2)

실제 내 코드에서는 1+1부분이 많이 복잡해서 화면을 넘어가고 있었고, _assert macro가 여러 개의 리스트로 묶여져 있어서 찾는데 좀 고생했다. Orz.

happy hackin'
일단 eunit으로 테스트를 하는 것을 가정한다.

unit test - makefile에서...
make file에 다음과 같은 부분을 추가한 후에, make test 하면 간편하게 명령행에서 unit test를 수행할 수있다.
(makefile 뼈대는 Programming Erlang을 기초로 했다.)

......
MODS = doc str_util db i18n tiny_scan
......

test: compile test_subdirs
    rm -rf Mnesia.nonode@nohost # removes previous mneisa db (optional).
    @for m in ${MODS};\
    do \
        echo "testing $$m";\
        ${ERL} -noshell -pz "subdir1" -pz "subdir2" -s $$m test -s init stop;\
    done

test_subdirs:
    cd subdir1; make test
    cd subdir2; make test

unit test, coverage test - 개발중 REPL(distel 또는 erl prompt) 에서...
REPL을 사용해서 (멋지게) 코딩-테스트를 반복중이라면, 다음과 같은 모듈을 하나 디렉토리에 넣어서 test:unit() 또는 test:cover() 를 실행시켜서 unit test 및 coverage test를 시시때때로 수행해 볼 수 있다.


테스트는 아무리 강조해도 지나치지 않다.
경험상 대부분의 버그는 테스트되지 않거나, 적절하지 못한 테스트(셋)들을 통과한 코드에 기생한다.

happy hackin'



1 
분류 전체보기 (306)
잡담 (20)
함수형 언어 (65)
emacs (16)
java (18)
tips & tricks (154)
사랑 (1)
가사 (0)
독서 (4)
mobile (6)
비함수형 언어 (2)

공지사항

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

05-04 17:08