PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/duckduckhack/testing/test_files.md

https://gitlab.com/Guy1394/duckduckgo-documentation
Markdown | 161 lines | 127 code | 34 blank | 0 comment | 0 complexity | e2f2d53347e11b73635dd83e143ce0c6 MD5 | raw file
  1. ## Test Files
  2. Good test files can help you quickly test code iterations. They also serve as a functional specification for your code. This specification helps everyone quickly understand and verify the expected behavior of the tested code, improving the quality of the feedback you receive and accelerating the review process.
  3. <!-- /summary -->
  4. Every Instant Answer must include a test file in the `t` directory. The test files are run automatically before each release to ensure that all Instant Answers are functioning properly. Properly functioning Instant Answers:
  5. - ignore any unsuitable queries,
  6. - trigger on the expected queries, and
  7. - provide appropriate answers for the queries handled.
  8. At a minimum, your tests should cover all of your primary and secondary example queries. If possible, you should also include examples of similar queries on which your code does **not** trigger. If your answer depends on the user's location, please review the [Location API testing guide](https://github.com/duckduckgo/duckduckgo-documentation/blob/master/duckduckhack/testing/testing_language_location_apis.md) for help in developing your tests. If your answer depends on the time of day or year, please be sure that your tests will continue to pass no matter when they are run.
  9. ## Creating Test Files
  10. If you used `duckpan new` to start your project, a simple test file was automatically created for you. Otherwise, copying the test file from a similar Instant Answer is an easy way to get started. Either way, you are only a few well-placed edits away from a test file suitable for your Instant Answer.
  11. Your test file should have **the same name** as the package it is testing. For example, the code in `lib/DDG/Goodie/Fortune.pm` is tested by `t/Fortune.t`.
  12. The standard DuckPAN installation includes Goodie and Spice testing libraries (`DDG::Test::Goodie` and `DDG::Test::Spice`, respectively.) These libraries make it quick and easy to develop tests for your Instant Answer.
  13. ## Running Test Files
  14. Tests are run from the root of the repository using the `prove` command included in your Perl distribution. During development, you can quickly run a single test file to verify your changes:
  15. ```shell
  16. prove -Ilib t/TestName.t
  17. ```
  18. <!-- /summary -->
  19. Or all of the tests in the repository's `t` directory:
  20. ```shell
  21. prove -Ilib t/
  22. ```
  23. To ensure that you have not inadvertently changed the behavior of other code, you should run the full test suite before submitting your Instant Answer. This is easily accomplished via `duckpan`:
  24. ```shell
  25. duckpan test
  26. ```
  27. ## Example Goodie Test File
  28. Below is the test file of the **RouterPasswords** Goodie, found at [`t/RouterPasswords.t`](https://github.com/duckduckgo/zeroclickinfo-goodies/blob/master/t/RouterPasswords.t).
  29. <!-- /summary -->
  30. ```perl
  31. #!/usr/bin/env perl
  32. use strict;
  33. use warnings;
  34. # These modules are necessary for the functions we'll be running.
  35. use Test::More;
  36. use DDG::Test::Goodie;
  37. # These zci attributes aren't necessary, but if you specify them inside your
  38. # goodie, you'll need to add matching values here to check against.
  39. zci answer_type => 'password';
  40. zci is_cached => 1;
  41. ddg_goodie_test(
  42. [
  43. # This is the name of the goodie that will be loaded to test.
  44. 'DDG::Goodie::RouterPasswords'
  45. ],
  46. # This is a sample query, just like the user will enter into the DuckDuckGo
  47. # search box.
  48. 'Belkin f5d6130' =>
  49. test_zci(
  50. # The first argument to test_zci is the plain text (default)
  51. # returned from a goodie. If your goodie also returns an HTML
  52. # version, you can pass that along explicitly as the second
  53. # argument. If your goodie is random, you can use regexps instead of
  54. # strings to match against.
  55. 'Default login for the BELKIN F5D6130: Username: (none) Password: password',
  56. html => 'Default login for the BELKIN F5D6130:<br><i>Username</i>: (none)<br><i>Password</i>: password'
  57. ),
  58. # You should include more test cases here. Try to think of ways that your
  59. # Instant Answer might break, and add them here to ensure they won't. Here are a
  60. # few others that were thought of for this goodie.
  61. 'Belkin f5d6130 password default' =>
  62. test_zci('Default login for the BELKIN F5D6130: Username: (none) Password: password',
  63. html => 'Default login for the BELKIN F5D6130:<br><i>Username</i>: (none)<br><i>Password</i>: password'),
  64. 'default password Belkin f5d6130' =>
  65. test_zci('Default login for the BELKIN F5D6130: Username: (none) Password: password',
  66. html => 'Default login for the BELKIN F5D6130:<br><i>Username</i>: (none)<br><i>Password</i>: password'),
  67. 'Belkin f5d6130 password' =>
  68. test_zci('Default login for the BELKIN F5D6130: Username: (none) Password: password',
  69. html => 'Default login for the BELKIN F5D6130:<br><i>Username</i>: (none)<br><i>Password</i>: password'),
  70. 'default BELKIN password f5d6130' =>
  71. test_zci('Default login for the BELKIN F5D6130: Username: (none) Password: password',
  72. html => 'Default login for the BELKIN F5D6130:<br><i>Username</i>: (none)<br><i>Password</i>: password'),
  73. 'password bELKIN default f5d6130' =>
  74. test_zci('Default login for the BELKIN F5D6130: Username: (none) Password: password',
  75. html => 'Default login for the BELKIN F5D6130:<br><i>Username</i>: (none)<br><i>Password</i>: password'),
  76. );
  77. # This function call is expected by Test::More. It makes sure the program
  78. # doesn't exit before all the tests have been run.
  79. done_testing;
  80. ```
  81. ## Example Spice Test File
  82. Below is the test file of the **Xkcd** Spice, found at [`t/Xkcd.t`](https://github.com/duckduckgo/zeroclickinfo-spice/blob/master/t/Xkcd.t).
  83. <!-- /summary -->
  84. ```perl
  85. #!/usr/bin/env perl
  86. use strict;
  87. use warnings;
  88. # These modules are necessary for the functions we'll be running.
  89. use Test::More;
  90. use DDG::Test::Spice;
  91. ddg_spice_test(
  92. [
  93. # This is the name of the Spice will be loaded to test.
  94. 'DDG::Spice::Xkcd'
  95. ],
  96. # This is a sample query, just like the user will enter into the DuckDuckGo
  97. # search box.
  98. '619 xkcd' => test_spice(
  99. # The first argument is the Spice callback. It includes the javascript
  100. # endpoint and the argument list constructed by the Perl code. In this
  101. # case, the endpoint is '/js/spice/xkcd/', and the argument returned by
  102. # the Perl code is 619.
  103. '/js/spice/xkcd/619',
  104. # This is the Spice calltype. It's almost always set to 'include',
  105. # except for some special cases like FlashVersion which don't make a
  106. # normal API call.
  107. call_type => 'include',
  108. # This is the Spice that should be triggered by the query.
  109. caller => 'DDG::Spice::Xkcd',
  110. # This is the cache value to expect. It's only necessary if you specify
  111. # one in your Spice.
  112. is_cached => 0
  113. ),
  114. # You should include more test cases here. Try to think of ways that your
  115. # Instant Answer might break, and add them here to ensure they won't. Here are is
  116. # another that is tested for this Spice.
  117. 'xkcd' => test_spice(
  118. '/js/spice/xkcd/',
  119. call_type => 'include',
  120. caller => 'DDG::Spice::Xkcd',
  121. is_cached => 0
  122. ),
  123. );
  124. # This function call is expected by Test::More. It makes sure the program
  125. # doesn't exit before all the tests have been run.
  126. done_testing;
  127. ```