erlang自带的common test框架用作测试比较方便,支持分布式测试等强大功能,个人感觉美中不足之处是把用例和测试库没有很好分离。当然可以自己封装测试库import使用,不过总觉得不够简洁。
下面记录一下基本使用方法,主要利用erlang强大的模式匹配
编写脚本basic/basic_SUITE.erl如下:
-module(basic_SUITE). %% %% highly recommended you add the line below which may %% provide some macro -include_lib("common_test/include/ct.hrl"). -export([all/0]). -export([test1/1, test2/1, test_http/1]). all() -> [test1,test2,test_http]. test1(_Config) -> 1 = 1. test2(_Config) -> A = 0, 1/A. test_http(_Config) -> inets:start(), {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = httpc:request(get, {"http://api.dbank.com/rest.php", []}, [], []), io:format("~p~n",[Version]), io:format("~p~n",[ReasonPhrase]), io:format("~p~n",[Headers]), Body == "{\"error\":\"param error\"}".
编写demo/demo_SUITE.erl如下:
用例1,测试用例添加预置条件及回收处理函数
用例2,发起http请求测试结果
-module(demo_SUITE). -include_lib("common_test/include/ct.hrl"). %% use export_all for test , or you must export functions by hand -compile(export_all). -export([all/0, init_per_testcase/2, end_per_testcase/2]). -export([test_http/1,ets_tests/1]). all() -> [test_http, ets_tests]. %% %% ETS is an interface to the Erlang built-in term storage BIFs which %% provide the ability to store very large quantities of data in an %% Erlang runtime system %% %% call init_per_testcase before test_case %% init only for ets_tests and ignore others init_per_testcase(ets_tests, _Config) -> TabId = ets:new(account, [ordered_set, public]), ets:insert(TabId, {ciaos,25}), ets:insert(TabId, {stone,24}), [{table,TabId} | _Config]; init_per_testcase(_, _Config) -> %% ignore for all other cases. _Config. %% call end_per_testcase after test_case %% end_per_testcase(ets_tests, _Config) -> ets:delete(?config(table, _Config)); end_per_testcase(_, _Config) -> ok. %% test cases ets_tests(_Config) -> TabId = ?config(table, _Config), [{ciaos,25}] = ets:lookup(TabId,ciaos), stone = ets:last(TabId), true = ets:insert(TabId, {tiger,50}), tiger = ets:last(TabId). test_http(_Config) -> inets:start(), {ok, {{Version, 200, ReasonPhrase}, Headers, Body}} = httpc:request(get, {"http://api.dbank.com/rest.php", []}, [], []), %% %% add some comment io:format("~p~n",[Version]), io:format("~p~n",[ReasonPhrase]), io:format("~p~n",[Headers]), Body == "{\"error\":\"param error\"}".
编写spec.spec配置文件如下(配置目录,输出结果以及跳过指定测试)
{alias, demo, "./demo/"}. {alias, basic, "./basic/"}. {logdir, "./logs/"}. {suites, basic, all}. {suites, demo, all}. {skip_cases, basic, basic_SUITE, test2, "this test fails on purpose"}.
运行测试用例(用浏览器打开index.html会有更多的测试细节):
ciaos:~ # ct_run -spec spec.spec -suite basic/basic_SUITE.erl demo/demo_SUITE.erl Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false] Common Test v1.7.1 starting (cwd is /root) Eshell V5.10.1 (abort with ^G) (ct@vm6245)1> Common Test: Running make in test directories... Recompile: demo_SUITE CWD set to: "/root/logs/[email protected]_18.32.58" TEST INFO: 2 test(s), 5 case(s) in 2 suite(s) Testing penjin.basic: Starting test, 3 test cases Testing penjin.basic: TEST COMPLETE, 2 ok, 0 failed, 1 skipped of 3 test cases Testing penjin.demo: Starting test, 2 test cases Testing penjin.demo: TEST COMPLETE, 2 ok, 0 failed of 2 test cases Updating /root/penjin/logs/index.html... done Updating /root/penjin/logs/all_runs.html... done
common test功能还很多,比如将测试用例分组搭配,指定顺序或者随机测试,指定某个测试用例失败后剩余用例是否继续测试等。
empty list / no option
shuffle
parallel
sequence
{repeat, Times}
测试结果截图如下: