Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

474 linhas
18 KiB

12 anos atrás
  1. %% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ts=4 sw=4 et
  3. %% -------------------------------------------------------------------
  4. %%
  5. %% rebar: Erlang Build Tools
  6. %%
  7. %% Copyright (c) 2009, 2010 Dave Smith (dizzyd@dizzyd.com)
  8. %%
  9. %% Permission is hereby granted, free of charge, to any person obtaining a copy
  10. %% of this software and associated documentation files (the "Software"), to deal
  11. %% in the Software without restriction, including without limitation the rights
  12. %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. %% copies of the Software, and to permit persons to whom the Software is
  14. %% furnished to do so, subject to the following conditions:
  15. %%
  16. %% The above copyright notice and this permission notice shall be included in
  17. %% all copies or substantial portions of the Software.
  18. %%
  19. %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. %% THE SOFTWARE.
  26. %% -------------------------------------------------------------------
  27. %% @author Chris Bernard <cebernard@gmail.com>
  28. %% @doc This tests functionality provided by the rebar command 'eunit'.
  29. %% @copyright 2009, 2010 Dave Smith
  30. %% -------------------------------------------------------------------
  31. -module(rebar_eunit_tests).
  32. -compile(export_all).
  33. -include_lib("eunit/include/eunit.hrl").
  34. %% Assuming this test is run inside the rebar 'eunit'
  35. %% command, the current working directory will be '.eunit'
  36. -define(REBAR_SCRIPT, "../rebar").
  37. -define(TMP_DIR, "tmp_eunit/").
  38. %% ====================================================================
  39. %% Rebar EUnit and Cover Tests
  40. %% ====================================================================
  41. eunit_test_() ->
  42. {"Ensure EUnit runs with tests in a 'test' dir and no defined suite",
  43. setup, fun() -> setup_basic_project(), rebar("-v eunit") end,
  44. fun teardown/1,
  45. fun(RebarOut) ->
  46. [{"Tests in 'test' directory are found and run",
  47. ?_assert(string:str(RebarOut, "myapp_mymod_tests:") =/= 0)},
  48. {"Tests in 'src' directory are found and run",
  49. ?_assert(string:str(RebarOut, "myapp_mymod:") =/= 0)},
  50. {"Tests are only run once",
  51. ?_assert(string:str(RebarOut, "All 2 tests passed") =/= 0)}]
  52. end}.
  53. eunit_with_suites_and_tests_test_() ->
  54. [{"Ensure EUnit runs selected suites",
  55. setup, fun() ->
  56. setup_project_with_multiple_modules(),
  57. rebar("-v eunit suites=myapp_mymod2")
  58. end,
  59. fun teardown/1,
  60. fun(RebarOut) ->
  61. [{"Selected suite tests in 'test' directory are found and run",
  62. ?_assert(string:str(RebarOut, "myapp_mymod2_tests:") =/= 0)},
  63. {"Selected suite tests in 'src' directory are found and run",
  64. ?_assert(string:str(RebarOut, "myapp_mymod2:") =/= 0)},
  65. {"Unselected suite tests in 'test' directory are not run",
  66. ?_assert(string:str(RebarOut, "myapp_mymod_tests:") =:= 0)},
  67. {"Unselected suite tests in 'src' directory are not run",
  68. ?_assert(string:str(RebarOut, "myapp_mymod:") =:= 0)},
  69. {"Selected suite tests are only run once",
  70. ?_assert(string:str(RebarOut, "All 4 tests passed") =/= 0)}]
  71. end},
  72. {"Ensure EUnit runs selected _tests suites",
  73. setup, fun() ->
  74. setup_project_with_multiple_modules(),
  75. rebar("-v eunit suites=myapp_mymod2_tests")
  76. end,
  77. fun teardown/1,
  78. fun(RebarOut) ->
  79. [{"Selected suite tests in 'test' directory are found and run",
  80. ?_assert(string:str(RebarOut, "myapp_mymod2_tests:") =/= 0)},
  81. {"Selected suite tests in 'src' directory are not run",
  82. ?_assert(string:str(RebarOut, "myapp_mymod2:") =:= 0)},
  83. {"Unselected suite tests in 'test' directory are not run",
  84. ?_assert(string:str(RebarOut, "myapp_mymod_tests:") =:= 0)},
  85. {"Unselected suite tests in 'src' directory are not run",
  86. ?_assert(string:str(RebarOut, "myapp_mymod:") =:= 0)},
  87. {"Selected suite tests are only run once",
  88. ?_assert(string:str(RebarOut, "All 2 tests passed") =/= 0)}]
  89. end},
  90. {"Ensure EUnit runs a specific test defined in a selected suite",
  91. setup, fun() ->
  92. setup_project_with_multiple_modules(),
  93. rebar("-v eunit suites=myapp_mymod2 tests=myprivate2")
  94. end,
  95. fun teardown/1,
  96. fun(RebarOut) ->
  97. [{"Selected suite tests are found and run",
  98. ?_assert(string:str(RebarOut,
  99. "myapp_mymod2:myprivate2_test/0") =/= 0)},
  100. {"Selected suite tests is run once",
  101. ?_assert(string:str(RebarOut, "Test passed") =/= 0)}]
  102. end},
  103. {"Ensure EUnit runs a specific generator test defined in a selected suite",
  104. setup, fun() ->
  105. setup_project_with_multiple_modules(),
  106. rebar("-v eunit suites=myapp_mymod3 tests=mygenerator")
  107. end,
  108. fun teardown/1,
  109. fun(RebarOut) ->
  110. [{"Selected suite's generator test is found and run",
  111. ?_assert(string:str(RebarOut,
  112. "myapp_mymod3:mygenerator_test_/0") =/= 0)},
  113. {"Selected suite's generator test raises an error",
  114. ?_assert(string:str(RebarOut,
  115. "assertEqual_failed") =/= 0)},
  116. {"Selected suite tests is run once",
  117. ?_assert(string:str(RebarOut, "Failed: 1.") =/= 0)}]
  118. end},
  119. {"Ensure EUnit runs specific tests defined in selected suites",
  120. setup, fun() ->
  121. setup_project_with_multiple_modules(),
  122. rebar("-v eunit suites=myapp_mymod,myapp_mymod2"
  123. " tests=myprivate,myfunc2")
  124. end,
  125. fun teardown/1,
  126. fun(RebarOut) ->
  127. [{"Selected suite tests are found and run",
  128. [?_assert(string:str(RebarOut,
  129. "myapp_mymod:myprivate_test/0") =/= 0),
  130. ?_assert(string:str(RebarOut,
  131. "myapp_mymod2:myprivate2_test/0") =/= 0),
  132. ?_assert(
  133. string:str(RebarOut,
  134. "myapp_mymod2_tests:myfunc2_test/0") =/= 0)]},
  135. {"Selected suite tests are run once",
  136. ?_assert(string:str(RebarOut, "All 3 tests passed") =/= 0)}]
  137. end},
  138. {"Ensure EUnit runs specific test in a _tests suite",
  139. setup,
  140. fun() ->
  141. setup_project_with_multiple_modules(),
  142. rebar("-v eunit suites=myapp_mymod2_tests tests=common_name_test")
  143. end,
  144. fun teardown/1,
  145. fun(RebarOut) ->
  146. [{"Only selected suite tests are found and run",
  147. [?_assert(string:str(RebarOut,
  148. "myapp_mymod2:common_name_test/0") =:= 0),
  149. ?_assert(string:str(RebarOut,
  150. "myapp_mymod2_tests:common_name_test/0")
  151. =/= 0)]},
  152. {"Selected suite tests is run once",
  153. ?_assert(string:str(RebarOut, "Test passed") =/= 0)}]
  154. end},
  155. {"Ensure EUnit runs a specific test without a specified suite",
  156. setup,
  157. fun() ->
  158. setup_project_with_multiple_modules(),
  159. rebar("-v eunit tests=myprivate")
  160. end,
  161. fun teardown/1,
  162. fun(RebarOut) ->
  163. [{"Only selected suite tests are found and run",
  164. [?_assert(string:str(RebarOut,
  165. "myapp_mymod:myprivate_test/0") =/= 0),
  166. ?_assert(string:str(RebarOut,
  167. "myapp_mymod2:myprivate2_test/0")
  168. =/= 0)]},
  169. {"Selected suite tests is run once",
  170. ?_assert(string:str(RebarOut, "All 2 tests passed") =/= 0)}]
  171. end},
  172. {"Ensure EUnit runs a specific test by qualified function name",
  173. setup,
  174. fun() ->
  175. setup_project_with_multiple_modules(),
  176. rebar("-v eunit tests=myapp_mymod:myprivate_test")
  177. end,
  178. fun teardown/1,
  179. fun(RebarOut) ->
  180. [{"Selected test is run",
  181. [?_assert(string:str(RebarOut,
  182. "myapp_mymod:myprivate_test/0")
  183. =/= 0)]},
  184. {"Only selected test is run",
  185. [?_assert(string:str(RebarOut,
  186. "Test passed.") =/= 0)]}]
  187. end},
  188. {"Ensure EUnit runs a specific test by qualified function "
  189. ++ "name and tests from other module",
  190. setup,
  191. fun() ->
  192. setup_project_with_multiple_modules(),
  193. rebar("-v eunit suites=myapp_mymod3 "
  194. ++ "tests=myapp_mymod:myprivate_test")
  195. end,
  196. fun teardown/1,
  197. fun(RebarOut) ->
  198. [{"Selected test is run",
  199. [?_assert(string:str(RebarOut,
  200. "myapp_mymod:myprivate_test/0") =/= 0)]},
  201. {"Tests from module are run",
  202. [?_assert(string:str(RebarOut,
  203. "myapp_mymod3:") =/= 0)]},
  204. {"Only selected tests are run",
  205. [?_assert(string:str(RebarOut,
  206. "Failed: 1. Skipped: 0. Passed: 1")
  207. =/= 0)]}]
  208. end}].
  209. cover_test_() ->
  210. {"Ensure Cover runs with tests in a test dir and no defined suite",
  211. setup, fun() -> setup_cover_project(), rebar("-v eunit") end,
  212. fun teardown/1,
  213. fun(RebarOut) ->
  214. [{"Error messages are not present",
  215. ?_assert(string:str(RebarOut, "Cover analyze failed for") =:= 0)},
  216. {"All cover reports are generated",
  217. assert_files_in("the temporary eunit directory",
  218. expected_cover_generated_files())},
  219. {"Only production modules get coverage reports",
  220. assert_files_not_in("the temporary eunit directory",
  221. [".eunit/myapp_mymod_tests.COVER.html"])}]
  222. end}.
  223. cover_with_suite_test_() ->
  224. {"Ensure Cover runs with Tests in a test dir and a test suite",
  225. setup,
  226. fun() ->
  227. setup_cover_project_with_suite(),
  228. rebar("-v eunit suites=mysuite")
  229. end,
  230. fun teardown/1,
  231. fun(RebarOut) ->
  232. [{"Error messages are not present",
  233. ?_assert(string:str(RebarOut, "Cover analyze failed for") =:= 0)},
  234. {"Cover reports are generated for module",
  235. assert_files_in("the temporary eunit directory",
  236. [".eunit/index.html",
  237. ".eunit/mysuite.COVER.html"])},
  238. {"Only production modules get coverage reports",
  239. assert_files_not_in("the temporary eunit directory",
  240. [".eunit/myapp_app.COVER.html",
  241. ".eunit/myapp_mymod.COVER.html",
  242. ".eunit/myapp_sup.COVER.html",
  243. ".eunit/myapp_mymod_tests.COVER.html"])}]
  244. end}.
  245. expected_cover_generated_files() ->
  246. [".eunit/index.html",
  247. ".eunit/myapp_app.COVER.html",
  248. ".eunit/myapp_mymod.COVER.html",
  249. ".eunit/myapp_sup.COVER.html"].
  250. cover_coverage_test_() ->
  251. {"Coverage is accurately calculated",
  252. setup, fun() -> setup_cover_project(), rebar("-v eunit") end,
  253. fun teardown/1,
  254. [{"Modules that include the EUnit header can still have 100% coverage",
  255. %% cover notices the implicit EUnit test/0 func that never gets
  256. %% called during eunit:test(TestRepresentation), so NotCounted
  257. %% needs to be decremented in this case.
  258. assert_full_coverage("myapp_mymod")}]}.
  259. %% ====================================================================
  260. %% Environment and Setup Tests
  261. %% ====================================================================
  262. environment_test_() ->
  263. {"Sanity check the testing environment",
  264. setup, fun make_tmp_dir/0, fun remove_tmp_dir/1,
  265. [{"Ensure a test project can be created",
  266. ?_assert(filelib:is_dir(?TMP_DIR))},
  267. {"Ensure the rebar script can be found, copied, and run",
  268. [?_assert(filelib:is_regular(?REBAR_SCRIPT)),
  269. fun assert_rebar_runs/0]}]}.
  270. assert_rebar_runs() ->
  271. prepare_rebar_script(),
  272. ?assert(string:str(os:cmd(filename:nativename("./" ++ ?TMP_DIR ++ "rebar")),
  273. "No command to run specified!") =/= 0).
  274. basic_setup_test_() ->
  275. {"Create a simple project with a 'test' directory, a test, and a module",
  276. setup, fun setup_basic_project/0, fun teardown/1,
  277. %% Test the setup function
  278. assert_dirs_in("Basic Project",
  279. ["src", "ebin", "test"]) ++
  280. assert_files_in("Basic Project",
  281. ["test/myapp_mymod_tests.erl",
  282. "src/myapp_mymod.erl"])}.
  283. %% ====================================================================
  284. %% Setup and Teardown
  285. %% ====================================================================
  286. -define(myapp_mymod,
  287. ["-module(myapp_mymod).\n",
  288. "-export([myfunc/0]).\n",
  289. "-include_lib(\"eunit/include/eunit.hrl\").\n",
  290. "myfunc() -> ok.\n",
  291. "myprivate_test() -> ?assert(true).\n"]).
  292. -define(myapp_mymod_tests,
  293. ["-module(myapp_mymod_tests).\n",
  294. "-compile([export_all]).\n",
  295. "-include_lib(\"eunit/include/eunit.hrl\").\n",
  296. "myfunc_test() -> ?assertMatch(ok, myapp_mymod:myfunc()).\n"]).
  297. -define(myapp_mymod2,
  298. ["-module(myapp_mymod2).\n",
  299. "-export([myfunc2/0]).\n",
  300. "-include_lib(\"eunit/include/eunit.hrl\").\n",
  301. "myfunc2() -> ok.\n",
  302. "myprivate2_test() -> ?assert(true).\n",
  303. "common_name_test() -> ?assert(true).\n"]).
  304. -define(myapp_mymod2_tests,
  305. ["-module(myapp_mymod2_tests).\n",
  306. "-compile([export_all]).\n",
  307. "-include_lib(\"eunit/include/eunit.hrl\").\n",
  308. "myfunc2_test() -> ?assertMatch(ok, myapp_mymod2:myfunc2()).\n",
  309. "common_name_test() -> ?assert(true).\n"]).
  310. -define(myapp_mymod3,
  311. ["-module(myapp_mymod3).\n",
  312. "-export([myfunc3/0]).\n",
  313. "-include_lib(\"eunit/include/eunit.hrl\").\n",
  314. "myfunc3() -> ok.\n",
  315. "mygenerator_test_() -> [?_assertEqual(true, false)].\n"]).
  316. -define(mysuite,
  317. ["-module(mysuite).\n",
  318. "-export([all_test_/0]).\n",
  319. "-include_lib(\"eunit/include/eunit.hrl\").\n",
  320. "all_test_() -> [myapp_mymod_defined_in_mysuite_tests].\n"]).
  321. -define(myapp_mymod_defined_in_mysuite_tests,
  322. ["-module(myapp_mymod_defined_in_mysuite_tests).\n",
  323. "-compile([export_all]).\n",
  324. "-include_lib(\"eunit/include/eunit.hrl\").\n",
  325. "myfunc_test() -> ?assertMatch(ok, myapp_mymod:myfunc()).\n"]).
  326. make_tmp_dir() ->
  327. case file:make_dir(?TMP_DIR) of
  328. ok ->
  329. ok;
  330. {error, eexist} ->
  331. remove_tmp_dir(),
  332. make_tmp_dir();
  333. Error ->
  334. throw(Error)
  335. end.
  336. setup_environment() ->
  337. ok = make_tmp_dir(),
  338. prepare_rebar_script(),
  339. ok = file:set_cwd(?TMP_DIR).
  340. setup_basic_project() ->
  341. setup_environment(),
  342. rebar("create-app appid=myapp"),
  343. ok = file:make_dir("ebin"),
  344. ok = file:make_dir("test"),
  345. ok = file:write_file("test/myapp_mymod_tests.erl", ?myapp_mymod_tests),
  346. ok = file:write_file("src/myapp_mymod.erl", ?myapp_mymod).
  347. setup_project_with_multiple_modules() ->
  348. setup_basic_project(),
  349. ok = file:write_file("test/myapp_mymod2_tests.erl", ?myapp_mymod2_tests),
  350. ok = file:write_file("src/myapp_mymod2.erl", ?myapp_mymod2),
  351. ok = file:write_file("src/myapp_mymod3.erl", ?myapp_mymod3).
  352. setup_cover_project() ->
  353. setup_basic_project(),
  354. ok = file:write_file("rebar.config", "{cover_enabled, true}.\n").
  355. setup_cover_project_with_suite() ->
  356. setup_cover_project(),
  357. ok = file:write_file("test/mysuite.erl", ?mysuite),
  358. ok = file:write_file("test/myapp_mymod_defined_in_mysuite_tests.erl",
  359. ?myapp_mymod_defined_in_mysuite_tests).
  360. teardown(_) ->
  361. ok = file:set_cwd(".."),
  362. ok = remove_tmp_dir().
  363. remove_tmp_dir() ->
  364. remove_tmp_dir(arg_for_eunit).
  365. remove_tmp_dir(_) ->
  366. ok = rebar_file_utils:rm_rf(?TMP_DIR).
  367. %% ====================================================================
  368. %% Helper Functions
  369. %% ====================================================================
  370. prepare_rebar_script() ->
  371. Rebar = ?TMP_DIR ++ "rebar",
  372. {ok, _} = file:copy(?REBAR_SCRIPT, Rebar),
  373. case os:type() of
  374. {unix, _} ->
  375. [] = os:cmd("chmod u+x " ++ Rebar);
  376. {win32, _} ->
  377. {ok, _} = file:copy(?REBAR_SCRIPT ++ ".cmd",
  378. ?TMP_DIR ++ "rebar.cmd")
  379. end.
  380. rebar() ->
  381. rebar([]).
  382. rebar(Args) when is_list(Args) ->
  383. Out = os:cmd(filename:nativename("./rebar") ++ " " ++ Args),
  384. %% ?debugMsg("**** Begin"), ?debugMsg(Out), ?debugMsg("**** End"),
  385. Out.
  386. assert_dirs_in(Name, [Dir|T]) ->
  387. [{Name ++ " has directory: " ++ Dir, ?_assert(filelib:is_dir(Dir))} |
  388. assert_dirs_in(Name, T)];
  389. assert_dirs_in(_, []) -> [].
  390. assert_files_in(Name, [File|T]) ->
  391. [{Name ++ " has file: " ++ File, ?_assert(filelib:is_regular(File))} |
  392. assert_files_in(Name, T)];
  393. assert_files_in(_, []) -> [].
  394. assert_files_not_in(Name, [File|T]) ->
  395. [{Name ++ " does not have file: " ++ File,
  396. ?_assertNot(filelib:is_regular(File))} | assert_files_not_in(Name, T)];
  397. assert_files_not_in(_, []) -> [].
  398. assert_full_coverage(Mod) ->
  399. fun() ->
  400. {ok, F} = file:read_file(".eunit/index.html"),
  401. Result = [X || X <- string:tokens(binary_to_list(F), "\n"),
  402. string:str(X, Mod) =/= 0,
  403. string:str(X, "100%") =/= 0],
  404. ?assert(length(Result) =:= 1)
  405. end.