2012-05-18 2 views
1

면책 조항 :이 질문의 저자는 대부분 Erlang/OTP에 대한 이론적 지식이 있습니다.왜 EUnit은 .beam 파일을 .eunit/ebin으로 컴파일합니까?

을 통해 myapp/ebin 디렉토리 내에서 Erlang이 아닌 일부 실행 파일을 호출하는 작은 OTP 애플리케이션이 있습니다. 응용 프로그램 자체를 실행하면 모든 것이 잘되고 실행 파일의 포트가 성공적으로 열립니다.

그러나 응용 프로그램에 대한 단위 테스트를 실행하려고하면 에 의존하는 테스트가 실패합니다. EUnit으로 시작하면 응용 프로그램은 myapp/.eunit/ebin에서 실행 파일을 찾으려고하기 때문에 실패합니다.

응용 프로그램 코드를 변경하지 않고 어떻게 동작을 변경할 수 있습니까? 응용 프로그램 자체를 실행할 때와 동일한 현재 디렉토리에서 EUnit 테스트를 어떻게 수행 할 수 있습니까? (나는 EUnit을 실행할 수 있도록 실행 파일에 대한 경로를 제공하는 코드를 변경하는 것이 좋지 않다는 것을 의미한다).

편집 : Erlang mailing list의 조언을 따르지만 code:priv_dir(myapp_name){error, bad_name}을 반환합니다.

편집 : .eunit/modulename.beam 파일을 포함하고 ebin/modulename.beam 파일과 modulename_tests.beam 파일을 모두 포함되어 있음을 볼 수 있습니다. 이제 나는 완전히 잃어버린다. 내가 make test를 실행하면 .eunit/ 디렉토리에 해당 modulename.beam 파일을 (filename:absname("") 명확 modulename.beam 파일을 테스트하는 동안 .eunit/에서 실행되는 것을 보여줍니다) 호출 ebin/ 디렉토리의 각 modulename_tests.beam 파일을 호출 eunit 명령을 rebar 실행합니다. 왜 그래야만하지? ebin/ 대신 .eunit/ 디렉토리의 modulename.beam 파일을 실행해야하는 이유는 무엇입니까?

왜 우리는 실제로 동일한 .beam 파일을 myapp/ebinmyapp/.eunit/ebin에 넣어야합니까?

P. 나는 official documentation을 읽고 해결책을 찾지 못했습니다.

답변

0

erlang 시작 스크립트 ".erlang"을 사용하면 문제를 해결할 수 있습니다.

.erlang 파일에서 code:add_pathz/N을 사용하여 필요한 경로를 추가하십시오.

couchdb 소스 코드를 읽기 전에 priv 디렉토리를 사용하는 방법의 예가 있습니다. 어쩌면 해결책이 도움이 될지도 모릅니다. 그것은 을 start_port 함수로 감싸고 디렉토리를 start_port 함수로 설정합니다. 당신은 priv grep을 할 수

priv_dir() -> 
    case code:priv_dir(couch) of 
     {error, bad_name} -> 
      % small hack, in dev mode "app" is couchdb. Fixing requires 
      % renaming src/couch to src/couch. Not really worth the hassle. 
      % -Damien 
      code:priv_dir(couchdb); 
     Dir -> Dir 
    end. 

start_driver(LibDir) -> 
    case erl_ddll:load_driver(LibDir, "couch_icu_driver") of 
    ok -> 
     ok; 
    {error, already_loaded} -> 
     ok = erl_ddll:reload_driver(LibDir, "couch_icu_driver"); 
    {error, Error} -> 
     exit(erl_ddll:format_error(Error)) 
    end. 

파일 couch_util.erl에서 파일 couch_os_daemon.erl

start_port(Command) -> 
    PrivDir = couch_util:priv_dir(), 
    Spawnkiller = filename:join(PrivDir, "couchspawnkillable"), 
    Port = open_port({spawn, Spawnkiller ++ " " ++ Command}, ?PORT_OPTIONS), 
    {ok, Port}. 


stop_port(#daemon{port=Port, kill=undefined}=D) -> 
    ?LOG_ERROR("Stopping daemon without a kill command: ~p", [D#daemon.name]), 
    catch port_close(Port); 
stop_port(#daemon{port=Port}=D) -> 
    ?LOG_DEBUG("Stopping daemon: ~p", [D#daemon.name]), 
    os:cmd(D#daemon.kill), 
    catch port_close(Port). 

에서

는 많은 예를 찾을 수있다.

+0

친애하는 Chen,이 경로를 동적으로 추가 할 수있는 방법이 있습니까? 하드 코딩 된 값을 코드에 추가 : add_pathsz()는 다른 컴퓨터에서 코드로 작업 할 때 도움이되지 않습니다. – skanatek

+0

코드를 추가하여 답장을 업데이트했습니다. –

4

EUnit은이 작업을 자체적으로 수행하지 않으며, .eunit 디렉토리는 Rebar가 사용하는 규칙입니다.

+0

.eunit/대신에 어떻게하면 ebar /로 컴파일되도록 철근을 만들 수 있습니까? 그리고 앱 빌드에서 무언가를 깨뜨릴 것인가? – skanatek

+0

철근을 포크하고 패치 할 수 있습니다. https://github.com/basho/rebar/blob/master/src/rebar_eunit.erl#L74 – Tilman

관련 문제