原因:在 erl 控制台 [Erlang] 中运行常见测试时 undef

Posted

技术标签:

【中文标题】原因:在 erl 控制台 [Erlang] 中运行常见测试时 undef【英文标题】:Reason: undef while running common tests in erl console [Erlang] 【发布时间】:2021-05-15 17:24:11 【问题描述】:

我正在运行应用程序,并在交互式控制台中尝试运行位于 test/common 目录中的常用测试套件:

ct:run("test/common").

但是我得到了一堆错误:

Reason: undef

所有测试都失败了。 我试图从 linux shell 运行它们

ct_run -dir test/common

或者像这样:

ct_run -boot start_sasl -spec test/common/app_ct.spec -erl_args -config env/dev.config

结果相同。

但是当我使用 rebar(第二个版本,不是 rebar3)运行它们时

rebar ct

一切正常,测试通过。但是编译和启动应用程序需要太多时间。

在 rebar.config 我有:

ct_dir,"test/common".
ct_log_dir,"test/logs".
ct_extra_params,"-boot start_sasl -pa deps/*/ebin -pa ebin -spec test/common/app_ct.spec -erl_args -config env/dev.config".

在 test/common/app_ct.spec 我有:

verbosity, 100.
init, eval, [application, ensure_all_started, [app], timer, sleep, [30000]].
alias, common, "./test/common/".
suites, "", [app_srv_SUITE, app_client_SUITE].

如何使用 ct:run("test/common") 从 erl 控制台运行测试?

我的目标是能够单独重新编译单个测试文件并从工作应用程序控制台运行测试,而无需停止和重新编译所有应用程序。

我重新编译单个测试模块没有这样的问题:

c("test/common/new_mod_SUITE.erl", [i, "include", i, "deps", outdir, "test/common"]). 

但在那之后我仍然无法运行测试。

【问题讨论】:

【参考方案1】:

首先,需要确保所有测试都已编译,并且它们位于文件夹内,作为参数放入ct:run/1。如果只需要从特定文件夹运行一项测试,可以使用ct:run/2。如果需要从特定文件夹运行特定测试用例,可以使用特定文件夹ct:run/3。例子:

1> ct:run("test/common").
2> ct:run("test/common", "some_SUITE").

但是我建议使用rebar3,在rebar3 中添加了--dir 之类的选项,并且可以像这样运行来自特定文件夹的测试:

$ ./rebar3 ct --dir="test/common"

【讨论】:

谢谢,我检查了 .beam 文件在指定目录中,我可以将它们编译到该目录,没有问题:c("test/common/new_mod_SUITE.erl", [ i, "include", i, "deps", outdir, "test/common"])。但是当我尝试运行测试时 ct:run("test/common", "new_mod_SUITE")。我仍然收到错误原因:undef. 顺便说一句,我编译了SUITE模块后,我可以在erlang终端中手动调用所有的测试用例,但是太繁琐,太费时间了。 你看,必须编译 Erlang 模块,请参阅文档 - erlang.org/doc/reference_manual/code_loading.html。如果您尝试使用我上面写的rebar3,您将能够在特定文件夹中运行测试,例如:rebar3 ct --dir="test/common"。但无论您是想手动运行还是使用工具运行 - 所有模块都必须在调用或运行常用测试之前编译。 很抱歉造成误解,显然我不够清楚。我真正想说的是,我从 erlang 控制台编译和重新编译我的测试套件没有问题,在我启动应用程序后打开。在那个控制台中,我可以像 my_SUITE:first_test_case() 一样手动调用我的测试用例。我无法工作的是能够调用 ct:run("test/common", "my_SUITE")。从 erlang 控制台,因为当我运行此命令时,我得到原因: undef 错误,我不知道我错过了什么。但这与钢筋版本无关。 my_SUITE模块编译后出现错误。 .beam 文件就位,我检查了。如果没有编译模块,我将无法手动从模块运行测试用例。我的猜测是原因:undef 错误源于调用 ct:run() 命令之前需要完成的一些缺失步骤(可能是启动 ct 应用程序或在运行 ct:run() 之前调用某些函数)。只是错误本身对我来说信息量不是很大。【参考方案2】:

这可能无济于事,但这是我使用 rebar3 时会发生的事情:

~/erlang_programs/myrebar/myapp$ ls
LICENSE     _build      rebar.lock  test
README.md   rebar.config    src

~/erlang_programs/myrebar/myapp$ cd src
~/erlang_programs/myrebar/myapp/src$ ls
a.erl       myapp_app.erl   rebar.lock
myapp.app.src   myapp_sup.erl

~/erlang_programs/myrebar/myapp/src$ cat a.erl
-module(a).
-compile(export_all).
%%-include("eunit.hrl").


hello() -> io:format("hello").

~/erlang_programs/myrebar/myapp/src$ cd ../test
~/erlang_programs/myrebar/myapp/test$ ls
a_SUITE.erl

~/erlang_programs/myrebar/myapp/test$ cat a_SUITE.erl 
-module(a_SUITE).
-compile(export_all).

all() -> [go].

go(_Config) ->
   1 = 1. 

~/erlang_programs/myrebar/myapp/test$ cd ..
~/erlang_programs/myrebar/myapp$ rebar3 compile
===> Verifying dependencies...
===> Compiling myapp
~/erlang_programs/myrebar/myapp$ rebar3 shell
===> Verifying dependencies...
===> Compiling myapp
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [kernel-poll:false]

Eshell V9.3  (abort with ^G)
1> ===> The rebar3 shell is a development tool; to deploy applications in production, consider using releases (http://www.rebar3.org/docs/releases)
===> Booted myapp
 
1> ct:run("test").

Common Test: Running make in test directories...
Recompile: a_SUITE
a_SUITE.erl:2: Warning: export_all flag enabled - all functions will be exported

CWD set to: "/Users/7stud/erlang_programs/myrebar/myapp/ct_run.nonode@nohost.2021-02-14_14.26.08"

TEST INFO: 1 test(s), 1 case(s) in 1 suite(s)

Testing myrebar.myapp: Starting test, 1 test cases
Testing myrebar.myapp: TEST COMPLETE, 1 ok, 0 failed of 1 test cases

Updating /Users/7stud/erlang_programs/myrebar/myapp/index.html ... done
Updating /Users/7stud/erlang_programs/myrebar/myapp/all_runs.html ... done
1,0,0,0
2> 

然后退出shell后:

~/erlang_programs/myrebar/myapp$ 

~/erlang_programs/myrebar/myapp$ rebar3 ct
===> Verifying dependencies...
===> Compiling myapp
test/a_SUITE.erl:2: Warning: export_all flag enabled - all functions will be exported

===> Running Common Test suites...
%%% a_SUITE: .
All 1 tests passed.

~/erlang_programs/myrebar/myapp$ 

我没碰rebar.config,是rebar3默认生成的:

erl_opts, [debug_info].
deps, [eleveldb, "2.2.20"]
.

shell, [
  % config, "config/sys.config",
    apps, [myapp]
].

当您在 shell 中时,我会尝试打印您当前的工作目录:

2> pwd().
/Users/7stud/erlang_programs/myrebar/myapp
ok

然后尝试使用该目录的完整路径或相对路径,例如:

"./test/common"
"Users/../../test/common"

然后,我会将除一个之外的所有 *_SUITE.erl 文件移动到应用程序外部的目录中,然后只使用一个测试文件。然后,我会删除所有配置文件并重试。

【讨论】:

我检查了 pwd()。它给了我项目 /home/andr/projects/my_proj 的根目录。尝试以 ct:run("./test/common") 和 ct:run("/home/andr/projects/my_proj/test/common") 两种方式运行测试。错误原因:undef 仍然存在,测试失败。 @AndreyKo,好的,现在尝试摆脱 rebar.config 的东西。 @AndreyKo,在那之后,我会尝试用一个测试文件创建一个全新的应用程序,看看你是否可以运行该测试。或者,只需使用您当前的应用程序并将所有 src 文件移出 src 目录,并将所有测试文件移出 test 目录,看看是否可以将一个测试放在“./test”目录中运行。 ct_dir 是否相对于测试目录,所以您应该指定“common”? @AndreyKo,这里有一些信息:github.com/erlang/rebar3/issues/415 @AndreyKo,更多:***.com/questions/20265672/…

以上是关于原因:在 erl 控制台 [Erlang] 中运行常见测试时 undef的主要内容,如果未能解决你的问题,请参考以下文章

erl模块翻译

Erlang模块与Erlang程序的运行方法

杀死进程并在erlang中运行程序

将命令传递给erl?

如何在 Erlang 中的多个 erl 之间共享记录?

Erl 中的记录(Erlang 问题)