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.

472 lines
20 KiB

преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
  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", "basic_app_tests.beam", "basic_app_tests_helper.beam"]).
  96. %% check that the correct tests are exported from modules for project
  97. %% note that this implies `TEST` is set correctly
  98. basic_app_exports(_Config) ->
  99. Tests = fun(Mod) ->
  100. begin
  101. Path = code:which(Mod),
  102. {ok, {Mod, [{exports, Ex}]}} = beam_lib:chunks(Path, [exports]),
  103. true = lists:member({sanity_test, 0}, Ex)
  104. end
  105. end,
  106. Helpers = fun(Mod) ->
  107. begin
  108. Path = code:which(Mod),
  109. {ok, {Mod, [{exports, Ex}]}} = beam_lib:chunks(Path, [exports]),
  110. true = lists:member({help, 0}, Ex)
  111. end
  112. end,
  113. lists:foreach(Tests, [basic_app, basic_app_tests]),
  114. lists:foreach(Helpers, [basic_app_tests_helper]).
  115. %% check that the correct tests are schedule to run for project
  116. basic_app_testset(Config) ->
  117. Result = ?config(result, Config),
  118. {ok, [{application, basic_app}]} = rebar_prv_eunit:prepare_tests(Result).
  119. %% === tests for multiple applications in the `apps' directory of a project ===
  120. %% check that project compiles properly
  121. multi_app_compiles(Config) ->
  122. AppDir = ?config(apps, Config),
  123. State = ?config(result, Config),
  124. {ok, _} = rebar_prv_eunit:do(State),
  125. rebar_test_utils:check_results(AppDir, [{app, "multi_app_bar"}, {app, "multi_app_baz"}], "*").
  126. %% check that all files expected to be present are present
  127. multi_app_files(Config) ->
  128. AppDir = ?config(apps, Config),
  129. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", F])) end,
  130. ["multi_app_bar.app", "multi_app_bar.beam", "multi_app_bar_tests.beam", "multi_app_bar_tests_helper.beam"]),
  131. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", F])) end,
  132. ["multi_app_baz.app", "multi_app_baz.beam", "multi_app_baz_tests.beam", "multi_app_baz_tests_helper.beam"]),
  133. lists:foreach(fun(F) -> true = ec_file:exists(filename:join([AppDir, "_build", "test", "test", F])) end,
  134. ["multi_app_tests.beam", "multi_app_tests_helper.beam"]).
  135. %% check that the correct tests are exported from modules for project
  136. %% note that this implies `TEST` is set correctly
  137. multi_app_exports(_Config) ->
  138. Tests = fun(Mod) ->
  139. begin
  140. Ex = Mod:module_info(exports),
  141. true = lists:member({sanity_test, 0}, Ex)
  142. end
  143. end,
  144. Helpers = fun(Mod) ->
  145. begin
  146. Ex = Mod:module_info(exports),
  147. true = lists:member({help, 0}, Ex)
  148. end
  149. end,
  150. lists:foreach(Tests, [multi_app_bar, multi_app_bar_tests,
  151. multi_app_baz, multi_app_baz_tests,
  152. multi_app_tests]),
  153. lists:foreach(Helpers, [multi_app_bar_tests_helper, multi_app_baz_tests_helper, multi_app_tests_helper]).
  154. %% check that the correct tests are schedule to run for project
  155. multi_app_testset(Config) ->
  156. AppDir = ?config(apps, Config),
  157. Result = ?config(result, Config),
  158. Set = {ok, [{application, multi_app_bar}, {application, multi_app_baz}, {dir, filename:join([AppDir, "_build", "test", "test"])}]},
  159. Set = rebar_prv_eunit:prepare_tests(Result).
  160. %% === tests for command line arguments ===
  161. %% no explicit test for cmd line args taking precedence over the rebar.config since
  162. %% almost every single test implies it
  163. %% check tests in the rebar.config are run if no cmd line opts are specified
  164. eunit_tests(Config) ->
  165. State = ?config(result, Config),
  166. Expect = {ok, [{test, multi_app_bar, sanity_test}, {test, multi_app_baz, sanity_test}]},
  167. Expect = rebar_prv_eunit:prepare_tests(State).
  168. %% check eunit_opts from the rebar.config are respected
  169. eunit_opts(Config) ->
  170. State = ?config(result, Config),
  171. Apps = rebar_state:project_apps(State),
  172. lists:foreach(fun(App) -> [verbose] = rebar_app_info:get(App, eunit_opts) end,
  173. Apps).
  174. %% check eunit_first_files from the rebar.config are respected
  175. eunit_first_files(Config) ->
  176. State = ?config(result, Config),
  177. FirstFiles = [filename:join(["apps", "multi_app_bar", "test", "multi_app_bar_tests_helper.erl"]),
  178. filename:join(["apps", "multi_app_baz", "test", "multi_app_baz_tests_helper.erl"])],
  179. Apps = rebar_state:project_apps(State),
  180. lists:foreach(fun(App) -> FirstFiles = rebar_app_info:get(App, eunit_first_files) end,
  181. Apps).
  182. %% check that the --application cmd line opt generates the correct test set
  183. single_application_arg(Config) ->
  184. S = ?config(result, Config),
  185. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar"]),
  186. State = rebar_state:command_parsed_args(S, Args),
  187. {ok, [{application, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State).
  188. multi_application_arg(Config) ->
  189. S = ?config(result, Config),
  190. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar,multi_app_baz"]),
  191. State = rebar_state:command_parsed_args(S, Args),
  192. {ok, [{application, multi_app_bar}, {application, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State).
  193. %% check that an invalid --application cmd line opt generates an error
  194. missing_application_arg(Config) ->
  195. S = ?config(result, Config),
  196. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=missing_app"]),
  197. State = rebar_state:command_parsed_args(S, Args),
  198. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Application `missing_app' not found in project."]}}},
  199. Error = rebar_prv_eunit:prepare_tests(State).
  200. %% check that the --module cmd line opt generates the correct test set
  201. single_module_arg(Config) ->
  202. AppDir = ?config(apps, Config),
  203. S = ?config(result, Config),
  204. %% necessary to fix paths
  205. Path = code:get_path(),
  206. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  207. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=multi_app_bar"]),
  208. State = rebar_state:command_parsed_args(S, Args),
  209. {ok, [{module, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State),
  210. %% restore path
  211. code:set_path(Path).
  212. multi_module_arg(Config) ->
  213. AppDir = ?config(apps, Config),
  214. S = ?config(result, Config),
  215. %% necessary to fix paths
  216. Path = code:get_path(),
  217. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  218. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"])]),
  219. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=multi_app_bar,multi_app_baz"]),
  220. State = rebar_state:command_parsed_args(S, Args),
  221. {ok, [{module, multi_app_bar}, {module, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State),
  222. %% restore path
  223. code:set_path(Path).
  224. %% check that an invalid --module cmd line opt generates an error
  225. missing_module_arg(Config) ->
  226. S = ?config(result, Config),
  227. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=missing_app"]),
  228. State = rebar_state:command_parsed_args(S, Args),
  229. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}},
  230. Error = rebar_prv_eunit:prepare_tests(State).
  231. %% check that the --suite cmd line opt generates the correct test set
  232. single_suite_arg(Config) ->
  233. AppDir = ?config(apps, Config),
  234. S = ?config(result, Config),
  235. %% necessary to fix paths
  236. Path = code:get_path(),
  237. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  238. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar"]),
  239. State = rebar_state:command_parsed_args(S, Args),
  240. {ok, [{module, multi_app_bar}]} = rebar_prv_eunit:prepare_tests(State),
  241. %% restore path
  242. code:set_path(Path).
  243. multi_suite_arg(Config) ->
  244. AppDir = ?config(apps, Config),
  245. S = ?config(result, Config),
  246. %% necessary to fix paths
  247. Path = code:get_path(),
  248. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  249. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"])]),
  250. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=multi_app_bar,multi_app_baz"]),
  251. State = rebar_state:command_parsed_args(S, Args),
  252. {ok, [{module, multi_app_bar}, {module, multi_app_baz}]} = rebar_prv_eunit:prepare_tests(State),
  253. %% restore path
  254. code:set_path(Path).
  255. %% check that an invalid --suite cmd line opt generates an error
  256. missing_suite_arg(Config) ->
  257. S = ?config(result, Config),
  258. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--suite=missing_app"]),
  259. State = rebar_state:command_parsed_args(S, Args),
  260. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}},
  261. Error = rebar_prv_eunit:prepare_tests(State).
  262. %% check that the --file cmd line opt generates the correct test set
  263. single_file_arg(Config) ->
  264. S = ?config(result, Config),
  265. AppDir = ?config(apps, Config),
  266. Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  267. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]),
  268. State = rebar_state:command_parsed_args(S, Args),
  269. {ok, [{file, Path}]} = rebar_prv_eunit:prepare_tests(State).
  270. multi_file_arg(Config) ->
  271. S = ?config(result, Config),
  272. AppDir = ?config(apps, Config),
  273. BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  274. BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin", "multi_app_baz.beam"]),
  275. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ BarPath ++ "," ++ BazPath]),
  276. State = rebar_state:command_parsed_args(S, Args),
  277. {ok, [{file, BarPath}, {file, BazPath}]} = rebar_prv_eunit:prepare_tests(State).
  278. %% check that an invalid --file cmd line opt generates an error
  279. missing_file_arg(Config) ->
  280. S = ?config(result, Config),
  281. AppDir = ?config(apps, Config),
  282. Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]),
  283. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--file=" ++ Path]),
  284. State = rebar_state:command_parsed_args(S, Args),
  285. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["File `" ++ Path ++"' not found."]}}},
  286. Error = rebar_prv_eunit:prepare_tests(State).
  287. %% check that the --dir cmd line opt generates the correct test set
  288. single_dir_arg(Config) ->
  289. S = ?config(result, Config),
  290. AppDir = ?config(apps, Config),
  291. Path = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  292. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]),
  293. State = rebar_state:command_parsed_args(S, Args),
  294. {ok, [{dir, Path}]} = rebar_prv_eunit:prepare_tests(State).
  295. multi_dir_arg(Config) ->
  296. S = ?config(result, Config),
  297. AppDir = ?config(apps, Config),
  298. BarPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  299. BazPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_baz", "ebin"]),
  300. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ BarPath ++ "," ++ BazPath]),
  301. State = rebar_state:command_parsed_args(S, Args),
  302. {ok, [{dir, BarPath}, {dir, BazPath}]} = rebar_prv_eunit:prepare_tests(State).
  303. %% check that an invalid --dir cmd line opt generates an error
  304. missing_dir_arg(Config) ->
  305. S = ?config(result, Config),
  306. AppDir = ?config(apps, Config),
  307. Path = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]),
  308. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--dir=" ++ Path]),
  309. State = rebar_state:command_parsed_args(S, Args),
  310. Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Directory `" ++ Path ++"' not found."]}}},
  311. Error = rebar_prv_eunit:prepare_tests(State).
  312. %% check that multiple args are composed
  313. multiple_arg_composition(Config) ->
  314. S = ?config(result, Config),
  315. AppDir = ?config(apps, Config),
  316. %% necessary to fix paths
  317. Path = code:get_path(),
  318. code:add_paths([filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"])]),
  319. FilePath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin", "multi_app_bar.beam"]),
  320. DirPath = filename:join([AppDir, "_build", "test", "lib", "multi_app_bar", "ebin"]),
  321. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=multi_app_bar",
  322. "--module=multi_app_bar",
  323. "--suite=multi_app_bar",
  324. "--file=" ++ FilePath,
  325. "--dir=" ++ DirPath]),
  326. State = rebar_state:command_parsed_args(S, Args),
  327. Expect = [{application, multi_app_bar},
  328. {dir, DirPath},
  329. {file, FilePath},
  330. {module, multi_app_bar},
  331. {module, multi_app_bar}],
  332. {ok, Expect} = rebar_prv_eunit:prepare_tests(State),
  333. %% restore path
  334. code:set_path(Path).
  335. %% check that multiple errors are reported
  336. multiple_arg_errors(Config) ->
  337. S = ?config(result, Config),
  338. AppDir = ?config(apps, Config),
  339. FilePath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin", "missing_app.beam"]),
  340. DirPath = filename:join([AppDir, "_build", "test", "lib", "missing_app", "ebin"]),
  341. {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--application=missing_app",
  342. "--module=missing_app",
  343. "--suite=missing_app",
  344. "--file=" ++ FilePath,
  345. "--dir=" ++ DirPath]),
  346. State = rebar_state:command_parsed_args(S, Args),
  347. Expect = ["Application `missing_app' not found in project.",
  348. "Directory `" ++ DirPath ++ "' not found.",
  349. "File `" ++ FilePath ++ "' not found.",
  350. "Module `missing_app' not found in project.",
  351. "Module `missing_app' not found in project."],
  352. {error, {rebar_prv_eunit, {eunit_test_errors, Expect}}} = rebar_prv_eunit:prepare_tests(State).