No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

480 líneas
20 KiB

  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: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. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}},
  238. Error = rebar_prv_eunit:prepare_tests(State).
  239. %% check that the --suite cmd line opt generates the correct test set
  240. single_suite_arg(Config) ->
  241. AppDir = ?config(apps, Config),
  242. S = ?config(result, Config),
  243. %% necessary to fix paths
  244. Path = code:get_path(),
  245. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  246. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar"]),
  247. State = rebar_state:command_parsed_args(S, Args),
  248. {ok, [{module, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State),
  249. %% restore path
  250. code:set_path(Path).
  251. multi_suite_arg(Config) ->
  252. AppDir = ?config(apps, Config),
  253. S = ?config(result, Config),
  254. %% necessary to fix paths
  255. Path = code:get_path(),
  256. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  257. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"])]),
  258. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar,multi_app_baz"]),
  259. State = rebar_state:command_parsed_args(S, Args),
  260. {ok, [{module, multi_app_bar}, {module, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State),
  261. %% restore path
  262. code:set_path(Path).
  263. %% check that an invalid --suite cmd line opt generates an error
  264. missing_suite_arg(Config) ->
  265. S = ?config(result, Config),
  266. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=missing_app"]),
  267. State = rebar_state:command_parsed_args(S, Args),
  268. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}},
  269. Error = rebar_prv_eunit:prepare_tests(State).
  270. %% check that the --file cmd line opt generates the correct test set
  271. single_file_arg(Config) ->
  272. S = ?config(result, Config),
  273. AppDir = ?config(apps, Config),
  274. Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  275. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]),
  276. State = rebar_state:command_parsed_args(S, Args),
  277. {ok, [{file, Path}]} = rebar_prv_eunit:prepare_tests(State).
  278. multi_file_arg(Config) ->
  279. S = ?config(result, Config),
  280. AppDir = ?config(apps, Config),
  281. BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  282. BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", "multi_app_baz.beam"]),
  283. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ BarPath ++ "," ++ BazPath]),
  284. State = rebar_state:command_parsed_args(S, Args),
  285. {ok, [{file, BarPath}, {file, BazPath}]} = rebar_prv_eunit:prepare_tests(State).
  286. %% check that an invalid --file cmd line opt generates an error
  287. missing_file_arg(Config) ->
  288. S = ?config(result, Config),
  289. AppDir = ?config(apps, Config),
  290. Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]),
  291. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]),
  292. State = rebar_state:command_parsed_args(S, Args),
  293. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["File `" ++ Path ++"' not found."]}}},
  294. Error = rebar_prv_eunit:prepare_tests(State).
  295. %% check that the --dir cmd line opt generates the correct test set
  296. single_dir_arg(Config) ->
  297. S = ?config(result, Config),
  298. AppDir = ?config(apps, Config),
  299. Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  300. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]),
  301. State = rebar_state:command_parsed_args(S, Args),
  302. {ok, [{dir, Path}]} = rebar_prv_eunit:prepare_tests(State).
  303. multi_dir_arg(Config) ->
  304. S = ?config(result, Config),
  305. AppDir = ?config(apps, Config),
  306. BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  307. BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"]),
  308. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ BarPath ++ "," ++ BazPath]),
  309. State = rebar_state:command_parsed_args(S, Args),
  310. {ok, [{dir, BarPath}, {dir, BazPath}]} = rebar_prv_eunit:prepare_tests(State).
  311. %% check that an invalid --dir cmd line opt generates an error
  312. missing_dir_arg(Config) ->
  313. S = ?config(result, Config),
  314. AppDir = ?config(apps, Config),
  315. Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]),
  316. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]),
  317. State = rebar_state:command_parsed_args(S, Args),
  318. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Directory `" ++ Path ++"' not found."]}}},
  319. Error = rebar_prv_eunit:prepare_tests(State).
  320. %% check that multiple args are composed
  321. multiple_arg_composition(Config) ->
  322. S = ?config(result, Config),
  323. AppDir = ?config(apps, Config),
  324. %% necessary to fix paths
  325. Path = code:get_path(),
  326. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  327. FilePath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  328. DirPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  329. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar",
  330. "--module=multi_app_bar",
  331. "--suite=multi_app_bar",
  332. "--file=" ++ FilePath,
  333. "--dir=" ++ DirPath]),
  334. State = rebar_state:command_parsed_args(S, Args),
  335. Expect = [{application, multi_app_bar},
  336. {dir, DirPath},
  337. {file, FilePath},
  338. {module, multi_app_bar},
  339. {module, multi_app_bar}],
  340. {ok, Expect} = rebar_prv_eunit:prepare_tests(State),
  341. %% restore path
  342. code:set_path(Path).
  343. %% check that multiple errors are reported
  344. multiple_arg_errors(Config) ->
  345. S = ?config(result, Config),
  346. AppDir = ?config(apps, Config),
  347. FilePath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]),
  348. DirPath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]),
  349. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=missing_app",
  350. "--module=missing_app",
  351. "--suite=missing_app",
  352. "--file=" ++ FilePath,
  353. "--dir=" ++ DirPath]),
  354. State = rebar_state:command_parsed_args(S, Args),
  355. Expect = ["Application `missing_app' not found in project.",
  356. "Directory `" ++ DirPath ++ "' not found.",
  357. "File `" ++ FilePath ++ "' not found.",
  358. "Module `missing_app' not found in project.",
  359. "Module `missing_app' not found in project."],
  360. {error, {rebar_prv_eunit, {eunit_test_errors, Expect}}} = rebar_prv_eunit:prepare_tests(State).