You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

486 rivejä
21 KiB

10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
10 vuotta sitten
  1. -module(rebar_eunit_SUITE).
  2. -export([all/0, groups/0]).
  3. -export([init_per_suite/1, init_per_group/2, end_per_group/2]).
  4. -export([basic_app_compiles/1, basic_app_files/1, basic_app_exports/1, basic_app_testset/1]).
  5. -export([multi_app_compiles/1, multi_app_files/1, multi_app_exports/1, multi_app_testset/1]).
  6. -export([eunit_tests/1, eunit_opts/1, eunit_first_files/1]).
  7. -export([single_application_arg/1, multi_application_arg/1, missing_application_arg/1]).
  8. -export([single_module_arg/1, multi_module_arg/1, missing_module_arg/1]).
  9. -export([single_suite_arg/1, multi_suite_arg/1, missing_suite_arg/1]).
  10. -export([single_file_arg/1, multi_file_arg/1, missing_file_arg/1]).
  11. -export([single_dir_arg/1, multi_dir_arg/1, missing_dir_arg/1]).
  12. -export([multiple_arg_composition/1, multiple_arg_errors/1]).
  13. -include_lib("common_test/include/ct.hrl").
  14. -include_lib("eunit/include/eunit.hrl").
  15. -include_lib("kernel/include/file.hrl").
  16. all() ->
  17. [{group, basic_app}, {group, multi_app}, {group, cmd_line_args}].
  18. groups() ->
  19. [{basic_app, [sequence], [basic_app_compiles, {group, basic_app_results}]},
  20. {basic_app_results, [], [basic_app_files, basic_app_exports, basic_app_testset]},
  21. {multi_app, [sequence], [multi_app_compiles, {group, multi_app_results}]},
  22. {multi_app_results, [], [multi_app_files, multi_app_exports, multi_app_testset]},
  23. {cmd_line_args, [], [eunit_tests, eunit_opts, eunit_first_files,
  24. single_application_arg, multi_application_arg, missing_application_arg,
  25. single_module_arg, multi_module_arg, missing_module_arg,
  26. single_suite_arg, multi_suite_arg, missing_suite_arg,
  27. single_file_arg, multi_file_arg, missing_file_arg,
  28. single_dir_arg, multi_dir_arg, missing_dir_arg,
  29. multiple_arg_composition, multiple_arg_errors]}].
  30. %% this just unzips the example apps used by tests to the priv dir for later use
  31. init_per_suite(Config) ->
  32. PrivDir = ?config(priv_dir, Config),
  33. DataDir = ?config(data_dir, Config),
  34. {ok, Cwd} = file:get_cwd(),
  35. file:set_cwd(PrivDir),
  36. ok = ec_file:copy(filename:join([DataDir, "basic_app.zip"]), filename:join([PrivDir, "basic_app.zip"])),
  37. {ok, _} = zip:extract(filename:join([PrivDir, "basic_app.zip"])),
  38. ok = ec_file:copy(filename:join([DataDir, "multi_app.zip"]), filename:join([PrivDir, "multi_app.zip"])),
  39. {ok, _} = zip:extract(filename:join([PrivDir, "multi_app.zip"])),
  40. file:set_cwd(Cwd),
  41. Config.
  42. init_per_group(basic_app, Config) ->
  43. GroupState = rebar_test_utils:init_rebar_state(Config, "basic_app_"),
  44. AppDir = ?config(apps, GroupState),
  45. PrivDir = ?config(priv_dir, GroupState),
  46. AppDirs = ["src", "include", "test"],
  47. lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "basic_app", F]),
  48. filename:join([AppDir, F]),
  49. [recursive]) end, AppDirs),
  50. RebarConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}],
  51. {ok, State} = rebar_test_utils:run_and_check(GroupState, RebarConfig, ["as", "test", "lock"], return),
  52. [{result, State}|GroupState];
  53. init_per_group(multi_app, Config) ->
  54. GroupState = rebar_test_utils:init_rebar_state(Config, "multi_app_"),
  55. AppDir = ?config(apps, GroupState),
  56. PrivDir = ?config(priv_dir, GroupState),
  57. AppDirs = ["apps", "test"],
  58. lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "multi_app", F]),
  59. filename:join([AppDir, F]),
  60. [recursive]) end, AppDirs),
  61. RebarConfig = [{erl_opts, [{d, config_define}]}, {eunit_compile_opts, [{d, eunit_compile_define}]}],
  62. {ok, State} = rebar_test_utils:run_and_check(GroupState, RebarConfig, ["as", "test", "lock"], return),
  63. [{result, State}|GroupState];
  64. init_per_group(cmd_line_args, Config) ->
  65. GroupState = rebar_test_utils:init_rebar_state(Config, "cmd_line_args_"),
  66. AppDir = ?config(apps, GroupState),
  67. PrivDir = ?config(priv_dir, GroupState),
  68. AppDirs = ["apps", "test"],
  69. lists:foreach(fun(F) -> ec_file:copy(filename:join([PrivDir, "multi_app", F]),
  70. filename:join([AppDir, F]),
  71. [recursive]) end, AppDirs),
  72. RebarConfig = [{erl_opts, [{d, config_define}]},
  73. {eunit_compile_opts, [{d, eunit_compile_define}]},
  74. %% test set not supported by cmd line args
  75. {eunit_tests, [{test, multi_app_bar, sanity_test},
  76. {test, multi_app_baz, sanity_test}]},
  77. {eunit_opts, [verbose]},
  78. {eunit_first_files, [filename:join(["apps", "multi_app_bar", "test", "multi_app_bar_tests_helper.erl"]),
  79. filename:join(["apps", "multi_app_baz", "test", "multi_app_baz_tests_helper.erl"])]}],
  80. {ok, State} = rebar_test_utils:run_and_check(GroupState, RebarConfig, ["eunit"], return),
  81. [{result, State}|GroupState];
  82. init_per_group(_, Config) -> Config.
  83. end_per_group(_, Config) -> Config.
  84. %% === tests for a single application at the root of a project ===
  85. %% check that project compiles properly
  86. basic_app_compiles(Config) ->
  87. AppDir = ?config(apps, Config),
  88. State = ?config(result, Config),
  89. {ok, _} = rebar_prv_eunit:do(State),
  90. rebar_test_utils:check_results(AppDir, [{app, "basic_app"}], "*").
  91. %% check that all files expected to be present are present
  92. basic_app_files(Config) ->
  93. AppDir = ?config(apps, Config),
  94. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "ebin", F])) end,
  95. ["basic_app.app", "basic_app.beam"]),
  96. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "basic_app", "test", F])) end,
  97. ["basic_app_tests.beam", "basic_app_tests_helper.beam"]).
  98. %% check that the correct tests are exported from modules for project
  99. %% note that this implies `TEST` is set correctly
  100. basic_app_exports(_Config) ->
  101. Tests = fun(Mod) ->
  102. begin
  103. Path = code:which(Mod),
  104. {ok, {Mod, [{exports, Ex}]}} = beam_lib:chunks(Path, [exports]),
  105. true = lists:member({sanity_test, 0}, Ex)
  106. end
  107. end,
  108. Helpers = fun(Mod) ->
  109. begin
  110. Path = code:which(Mod),
  111. {ok, {Mod, [{exports, Ex}]}} = beam_lib:chunks(Path, [exports]),
  112. true = lists:member({help, 0}, Ex)
  113. end
  114. end,
  115. lists:foreach(Tests, [basic_app, basic_app_tests]),
  116. lists:foreach(Helpers, [basic_app_tests_helper]).
  117. %% check that the correct tests are schedule to run for project
  118. basic_app_testset(Config) ->
  119. Result = ?config(result, Config),
  120. {ok, [{application, basic_app}]} = rebar_prv_eunit:prepare_tests(Result).
  121. %% === tests for multiple applications in the `apps' directory of a project ===
  122. %% check that project compiles properly
  123. multi_app_compiles(Config) ->
  124. AppDir = ?config(apps, Config),
  125. State = ?config(result, Config),
  126. {ok, _} = rebar_prv_eunit:do(State),
  127. rebar_test_utils:check_results(AppDir, [{app, "multi_app_bar"}, {app, "multi_app_baz"}], "*").
  128. %% check that all files expected to be present are present
  129. multi_app_files(Config) ->
  130. AppDir = ?config(apps, Config),
  131. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", F])) end,
  132. ["multi_app_bar.app", "multi_app_bar.beam"]),
  133. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", F])) end,
  134. ["multi_app_baz.app", "multi_app_baz.beam"]),
  135. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "test", F])) end,
  136. ["multi_app_bar_tests.beam", "multi_app_bar_tests_helper.beam"]),
  137. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "test", F])) end,
  138. ["multi_app_baz_tests.beam", "multi_app_baz_tests_helper.beam"]),
  139. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "extras", "test", F])) end,
  140. ["multi_app_tests.beam", "multi_app_tests_helper.beam"]).
  141. %% check that the correct tests are exported from modules for project
  142. %% note that this implies `TEST` is set correctly
  143. multi_app_exports(_Config) ->
  144. Tests = fun(Mod) ->
  145. begin
  146. Ex = Mod:module_info(exports),
  147. true = lists:member({sanity_test, 0}, Ex)
  148. end
  149. end,
  150. Helpers = fun(Mod) ->
  151. begin
  152. Ex = Mod:module_info(exports),
  153. true = lists:member({help, 0}, Ex)
  154. end
  155. end,
  156. lists:foreach(Tests, [multi_app_bar, multi_app_bar_tests,
  157. multi_app_baz, multi_app_baz_tests,
  158. multi_app_tests]),
  159. lists:foreach(Helpers, [multi_app_bar_tests_helper, multi_app_baz_tests_helper, multi_app_tests_helper]).
  160. %% check that the correct tests are schedule to run for project
  161. multi_app_testset(Config) ->
  162. AppDir = ?config(apps, Config),
  163. Result = ?config(result, Config),
  164. Set = {ok, [{application, multi_app_bar},
  165. {application, multi_app_baz},
  166. {dir, filename:join([AppDir, "test"])}]},
  167. Set = rebar_prv_eunit:prepare_tests(Result).
  168. %% === tests for command line arguments ===
  169. %% no explicit test for cmd line args taking precedence over the rebar.config since
  170. %% almost every single test implies it
  171. %% check tests in the rebar.config are run if no cmd line opts are specified
  172. eunit_tests(Config) ->
  173. State = ?config(result, Config),
  174. Expect = {ok, [{test, multi_app_bar, sanity_test}, {test, multi_app_baz, sanity_test}]},
  175. Expect = rebar_prv_eunit:prepare_tests(State).
  176. %% check eunit_opts from the rebar.config are respected
  177. eunit_opts(Config) ->
  178. State = ?config(result, Config),
  179. Apps = rebar_state:project_apps(State),
  180. lists:foreach(fun(App) -> [verbose] = rebar_app_info:get(App, eunit_opts) end,
  181. Apps).
  182. %% check eunit_first_files from the rebar.config are respected
  183. eunit_first_files(Config) ->
  184. State = ?config(result, Config),
  185. FirstFiles = [filename:join(["apps", "multi_app_bar", "test", "multi_app_bar_tests_helper.erl"]),
  186. filename:join(["apps", "multi_app_baz", "test", "multi_app_baz_tests_helper.erl"])],
  187. Apps = rebar_state:project_apps(State),
  188. lists:foreach(fun(App) -> FirstFiles = rebar_app_info:get(App, eunit_first_files) end,
  189. Apps).
  190. %% check that the --application cmd line opt generates the correct test set
  191. single_application_arg(Config) ->
  192. S = ?config(result, Config),
  193. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar"]),
  194. State = rebar_state:command_parsed_args(S, Args),
  195. {ok, [{application, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State).
  196. multi_application_arg(Config) ->
  197. S = ?config(result, Config),
  198. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar,multi_app_baz"]),
  199. State = rebar_state:command_parsed_args(S, Args),
  200. {ok, [{application, multi_app_bar}, {application, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State).
  201. %% check that an invalid --application cmd line opt generates an error
  202. missing_application_arg(Config) ->
  203. S = ?config(result, Config),
  204. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=missing_app"]),
  205. State = rebar_state:command_parsed_args(S, Args),
  206. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Application `missing_app' not found in project."]}}},
  207. Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).
  208. %% check that the --module cmd line opt generates the correct test set
  209. single_module_arg(Config) ->
  210. AppDir = ?config(apps, Config),
  211. S = ?config(result, Config),
  212. %% necessary to fix paths
  213. Path = code:get_path(),
  214. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  215. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=multi_app_bar"]),
  216. State = rebar_state:command_parsed_args(S, Args),
  217. {ok, [{module, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State),
  218. %% restore path
  219. code:set_path(Path).
  220. multi_module_arg(Config) ->
  221. AppDir = ?config(apps, Config),
  222. S = ?config(result, Config),
  223. %% necessary to fix paths
  224. Path = code:get_path(),
  225. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  226. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"])]),
  227. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=multi_app_bar,multi_app_baz"]),
  228. State = rebar_state:command_parsed_args(S, Args),
  229. {ok, [{module, multi_app_bar}, {module, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State),
  230. %% restore path
  231. code:set_path(Path).
  232. %% check that an invalid --module cmd line opt generates an error
  233. missing_module_arg(Config) ->
  234. S = ?config(result, Config),
  235. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=missing_app"]),
  236. State = rebar_state:command_parsed_args(S, Args),
  237. T = rebar_prv_eunit:prepare_tests(State),
  238. Tests = rebar_prv_eunit:validate_tests(S, T),
  239. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}},
  240. Error = Tests.
  241. %% check that the --suite cmd line opt generates the correct test set
  242. single_suite_arg(Config) ->
  243. AppDir = ?config(apps, Config),
  244. S = ?config(result, Config),
  245. %% necessary to fix paths
  246. Path = code:get_path(),
  247. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  248. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar"]),
  249. State = rebar_state:command_parsed_args(S, Args),
  250. {ok, [{module, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State),
  251. %% restore path
  252. code:set_path(Path).
  253. multi_suite_arg(Config) ->
  254. AppDir = ?config(apps, Config),
  255. S = ?config(result, Config),
  256. %% necessary to fix paths
  257. Path = code:get_path(),
  258. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  259. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"])]),
  260. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar,multi_app_baz"]),
  261. State = rebar_state:command_parsed_args(S, Args),
  262. {ok, [{module, multi_app_bar}, {module, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State),
  263. %% restore path
  264. code:set_path(Path).
  265. %% check that an invalid --suite cmd line opt generates an error
  266. missing_suite_arg(Config) ->
  267. S = ?config(result, Config),
  268. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=missing_app"]),
  269. State = rebar_state:command_parsed_args(S, Args),
  270. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}},
  271. Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).
  272. %% check that the --file cmd line opt generates the correct test set
  273. single_file_arg(Config) ->
  274. S = ?config(result, Config),
  275. AppDir = ?config(apps, Config),
  276. Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  277. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]),
  278. State = rebar_state:command_parsed_args(S, Args),
  279. {ok, [{file, Path}]} = rebar_prv_eunit:prepare_tests(State).
  280. multi_file_arg(Config) ->
  281. S = ?config(result, Config),
  282. AppDir = ?config(apps, Config),
  283. BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  284. BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", "multi_app_baz.beam"]),
  285. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ BarPath ++ "," ++ BazPath]),
  286. State = rebar_state:command_parsed_args(S, Args),
  287. {ok, [{file, BarPath}, {file, BazPath}]} = rebar_prv_eunit:prepare_tests(State).
  288. %% check that an invalid --file cmd line opt generates an error
  289. missing_file_arg(Config) ->
  290. S = ?config(result, Config),
  291. AppDir = ?config(apps, Config),
  292. Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]),
  293. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]),
  294. State = rebar_state:command_parsed_args(S, Args),
  295. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["File `" ++ Path ++"' not found."]}}},
  296. Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).
  297. %% check that the --dir cmd line opt generates the correct test set
  298. single_dir_arg(Config) ->
  299. S = ?config(result, Config),
  300. AppDir = ?config(apps, Config),
  301. Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  302. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]),
  303. State = rebar_state:command_parsed_args(S, Args),
  304. {ok, [{dir, Path}]} = rebar_prv_eunit:prepare_tests(State).
  305. multi_dir_arg(Config) ->
  306. S = ?config(result, Config),
  307. AppDir = ?config(apps, Config),
  308. BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  309. BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"]),
  310. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ BarPath ++ "," ++ BazPath]),
  311. State = rebar_state:command_parsed_args(S, Args),
  312. {ok, [{dir, BarPath}, {dir, BazPath}]} = rebar_prv_eunit:prepare_tests(State).
  313. %% check that an invalid --dir cmd line opt generates an error
  314. missing_dir_arg(Config) ->
  315. S = ?config(result, Config),
  316. AppDir = ?config(apps, Config),
  317. Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]),
  318. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]),
  319. State = rebar_state:command_parsed_args(S, Args),
  320. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Directory `" ++ Path ++"' not found."]}}},
  321. Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).
  322. %% check that multiple args are composed
  323. multiple_arg_composition(Config) ->
  324. S = ?config(result, Config),
  325. AppDir = ?config(apps, Config),
  326. %% necessary to fix paths
  327. Path = code:get_path(),
  328. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  329. FilePath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  330. DirPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  331. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar",
  332. "--module=multi_app_bar",
  333. "--suite=multi_app_bar",
  334. "--file=" ++ FilePath,
  335. "--dir=" ++ DirPath]),
  336. State = rebar_state:command_parsed_args(S, Args),
  337. Expect = [{application, multi_app_bar},
  338. {dir, DirPath},
  339. {file, FilePath},
  340. {module, multi_app_bar},
  341. {module, multi_app_bar}],
  342. {ok, Expect} = rebar_prv_eunit:prepare_tests(State),
  343. %% restore path
  344. code:set_path(Path).
  345. %% check that multiple errors are reported
  346. multiple_arg_errors(Config) ->
  347. S = ?config(result, Config),
  348. AppDir = ?config(apps, Config),
  349. FilePath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]),
  350. DirPath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]),
  351. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=missing_app",
  352. "--module=missing_app",
  353. "--suite=missing_app",
  354. "--file=" ++ FilePath,
  355. "--dir=" ++ DirPath]),
  356. State = rebar_state:command_parsed_args(S, Args),
  357. T = rebar_prv_eunit:prepare_tests(State),
  358. Tests = rebar_prv_eunit:validate_tests(S, T),
  359. Expect = ["Application `missing_app' not found in project.",
  360. "Directory `" ++ DirPath ++ "' not found.",
  361. "File `" ++ FilePath ++ "' not found.",
  362. "Module `missing_app' not found in project.",
  363. "Module `missing_app' not found in project."],
  364. {error, {rebar_prv_eunit, {eunit_test_errors, Expect}}} = Tests.