1

免责声明:这个问题的作者主要有 Erlang/OTP 的理论知识。

我有一个小型 OTP 应用程序,它myapp/ebin通过open_port(). 当我运行应用程序本身时,一切顺利,可执行文件的端口已成功打开。

但是当我尝试为应用程序运行单元测试时,依赖于open_port()失败的单元测试,因为当开始时EUnit应用程序启动时,尝试在myapp/.eunit/ebin.

如何在不更改应用程序本身代码的情况下更改该行为?如何使用与运行应用程序本身相同的当前目录运行 EUnit 测试?(我的意思是更改提供可执行文件路径的代码只是为了能够运行 EUnit 并不是一个好主意)。

编辑:我遵循了 Erlang邮件列表中的建议,但是code:priv_dir(myapp_name)返回{error, bad_name}

编辑:我可以看到.eunit/包含modulename.beam文件并且ebin/包含modulename.beam文件和modulename_tests.beam文件。现在我完全迷失了。当我运行时make testrebar运行eunit命令,该命令调用目录中的每个modulename_tests.beam文件,该文件ebin/调用目录中的相应modulename.beam文件.eunit/filename:absname("")清楚地表明modulename.beam文件是.eunit/在测试期间执行的)。为什么会这样?为什么我们需要modulename.beam从目录运行文件.eunit/而不是ebin/?

为什么我们实际上需要在myapp/ebin和中有相同的 .beam 文件myapp/.eunit/ebin

PS我已经阅读了官方文档并没有找到解决方案。

4

2 回答 2

4

EUnit 本身不会这样做 - .eunit 目录是 Rebar 使用的约定。

于 2012-05-19T22:02:23.943 回答
0

使用erlang启动脚本“.erlang”,它可以解决你的问题。

在 .erlang 文件中,用于code:add_pathz/N添加必要的路径。

在阅读couchdb源代码之前,有一个如何使用priv目录的示例。也许解决方案对您有帮助。open_port它用函数包装start_port,并在函数中设置目录start_port

在文件中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).

在文件 couch_util.erl

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.

你可以 grep priv,可以找到很多例子。

于 2012-05-19T00:37:50.857 回答