lgrgic_palindrome_detector 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +8 -0
  5. data/Gemfile.lock +31 -0
  6. data/README.md +39 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/lgrgic_palindrome_detector.gemspec +37 -0
  11. data/lib/lgrgic_palindrome_detector.rb +16 -0
  12. data/lib/lgrgic_palindrome_detector/version.rb +3 -0
  13. data/vendor/cache/ansi-1.5.0.gem +0 -0
  14. data/vendor/cache/bin/rake +27 -0
  15. data/vendor/cache/builder-3.2.3.gem +0 -0
  16. data/vendor/cache/cache/ansi-1.5.0.gem +0 -0
  17. data/vendor/cache/cache/builder-3.2.3.gem +0 -0
  18. data/vendor/cache/cache/minitest-5.11.3.gem +0 -0
  19. data/vendor/cache/cache/minitest-reporters-1.2.0.gem +0 -0
  20. data/vendor/cache/cache/rake-10.5.0.gem +0 -0
  21. data/vendor/cache/cache/ruby-progressbar-1.10.0.gem +0 -0
  22. data/vendor/cache/gems/ansi-1.5.0/.index +77 -0
  23. data/vendor/cache/gems/ansi-1.5.0/.yardopts +8 -0
  24. data/vendor/cache/gems/ansi-1.5.0/DEMO.md +451 -0
  25. data/vendor/cache/gems/ansi-1.5.0/HISTORY.md +217 -0
  26. data/vendor/cache/gems/ansi-1.5.0/LICENSE.txt +23 -0
  27. data/vendor/cache/gems/ansi-1.5.0/NOTICE.md +170 -0
  28. data/vendor/cache/gems/ansi-1.5.0/README.md +91 -0
  29. data/vendor/cache/gems/ansi-1.5.0/demo/01_ansicode.md +65 -0
  30. data/vendor/cache/gems/ansi-1.5.0/demo/02_core.md +11 -0
  31. data/vendor/cache/gems/ansi-1.5.0/demo/03_logger.md +30 -0
  32. data/vendor/cache/gems/ansi-1.5.0/demo/04_progressbar.md +62 -0
  33. data/vendor/cache/gems/ansi-1.5.0/demo/05_mixin.md +37 -0
  34. data/vendor/cache/gems/ansi-1.5.0/demo/06_string.md +56 -0
  35. data/vendor/cache/gems/ansi-1.5.0/demo/07_columns.md +89 -0
  36. data/vendor/cache/gems/ansi-1.5.0/demo/08_table.md +28 -0
  37. data/vendor/cache/gems/ansi-1.5.0/demo/09_diff.md +47 -0
  38. data/vendor/cache/gems/ansi-1.5.0/demo/10_bbcode.md +24 -0
  39. data/vendor/cache/gems/ansi-1.5.0/demo/11_terminal.md +8 -0
  40. data/vendor/cache/gems/ansi-1.5.0/demo/applique/ae.rb +1 -0
  41. data/vendor/cache/gems/ansi-1.5.0/demo/applique/output.rb +5 -0
  42. data/vendor/cache/gems/ansi-1.5.0/lib/ansi.rb +22 -0
  43. data/vendor/cache/gems/ansi-1.5.0/lib/ansi.yml +77 -0
  44. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/bbcode.rb +334 -0
  45. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/chain.rb +50 -0
  46. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/chart.rb +100 -0
  47. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/code.rb +349 -0
  48. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/columns.rb +197 -0
  49. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/constants.rb +25 -0
  50. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/core.rb +30 -0
  51. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/diff.rb +215 -0
  52. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/hexdump.rb +122 -0
  53. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/logger.rb +211 -0
  54. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/mixin.rb +121 -0
  55. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/progressbar.rb +292 -0
  56. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/string.rb +254 -0
  57. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/table.rb +179 -0
  58. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/terminal.rb +44 -0
  59. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/terminal/curses.rb +26 -0
  60. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/terminal/stty.rb +62 -0
  61. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/terminal/termios.rb +68 -0
  62. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/terminal/win32.rb +107 -0
  63. data/vendor/cache/gems/ansi-1.5.0/lib/ansi/version.rb +15 -0
  64. data/vendor/cache/gems/ansi-1.5.0/test/case_ansicode.rb +43 -0
  65. data/vendor/cache/gems/ansi-1.5.0/test/case_bbcode.rb +35 -0
  66. data/vendor/cache/gems/ansi-1.5.0/test/case_mixin.rb +35 -0
  67. data/vendor/cache/gems/ansi-1.5.0/test/case_progressbar.rb +21 -0
  68. data/vendor/cache/gems/ansi-1.5.0/test/test_helper.rb +3 -0
  69. data/vendor/cache/gems/builder-3.2.3/CHANGES +107 -0
  70. data/vendor/cache/gems/builder-3.2.3/MIT-LICENSE +20 -0
  71. data/vendor/cache/gems/builder-3.2.3/README.md +258 -0
  72. data/vendor/cache/gems/builder-3.2.3/Rakefile +195 -0
  73. data/vendor/cache/gems/builder-3.2.3/doc/jamis.rb +591 -0
  74. data/vendor/cache/gems/builder-3.2.3/doc/releases/builder-1.2.4.rdoc +31 -0
  75. data/vendor/cache/gems/builder-3.2.3/doc/releases/builder-2.0.0.rdoc +46 -0
  76. data/vendor/cache/gems/builder-3.2.3/doc/releases/builder-2.1.1.rdoc +58 -0
  77. data/vendor/cache/gems/builder-3.2.3/lib/blankslate.rb +137 -0
  78. data/vendor/cache/gems/builder-3.2.3/lib/builder.rb +13 -0
  79. data/vendor/cache/gems/builder-3.2.3/lib/builder/blankslate.rb +23 -0
  80. data/vendor/cache/gems/builder-3.2.3/lib/builder/version.rb +8 -0
  81. data/vendor/cache/gems/builder-3.2.3/lib/builder/xchar.rb +197 -0
  82. data/vendor/cache/gems/builder-3.2.3/lib/builder/xmlbase.rb +199 -0
  83. data/vendor/cache/gems/builder-3.2.3/lib/builder/xmlevents.rb +63 -0
  84. data/vendor/cache/gems/builder-3.2.3/lib/builder/xmlmarkup.rb +339 -0
  85. data/vendor/cache/gems/builder-3.2.3/rakelib/publish.rake +20 -0
  86. data/vendor/cache/gems/builder-3.2.3/rakelib/tags.rake +62 -0
  87. data/vendor/cache/gems/builder-3.2.3/rakelib/testing.rake +7 -0
  88. data/vendor/cache/gems/builder-3.2.3/test/helper.rb +12 -0
  89. data/vendor/cache/gems/builder-3.2.3/test/performance.rb +41 -0
  90. data/vendor/cache/gems/builder-3.2.3/test/preload.rb +39 -0
  91. data/vendor/cache/gems/builder-3.2.3/test/test_blankslate.rb +213 -0
  92. data/vendor/cache/gems/builder-3.2.3/test/test_eventbuilder.rb +150 -0
  93. data/vendor/cache/gems/builder-3.2.3/test/test_markupbuilder.rb +611 -0
  94. data/vendor/cache/gems/builder-3.2.3/test/test_method_caching.rb +62 -0
  95. data/vendor/cache/gems/builder-3.2.3/test/test_namecollision.rb +39 -0
  96. data/vendor/cache/gems/builder-3.2.3/test/test_xchar.rb +78 -0
  97. data/vendor/cache/gems/minitest-5.11.3/.autotest +34 -0
  98. data/vendor/cache/gems/minitest-5.11.3/History.rdoc +1310 -0
  99. data/vendor/cache/gems/minitest-5.11.3/Manifest.txt +26 -0
  100. data/vendor/cache/gems/minitest-5.11.3/README.rdoc +746 -0
  101. data/vendor/cache/gems/minitest-5.11.3/Rakefile +86 -0
  102. data/vendor/cache/gems/minitest-5.11.3/design_rationale.rb +52 -0
  103. data/vendor/cache/gems/minitest-5.11.3/lib/hoe/minitest.rb +32 -0
  104. data/vendor/cache/gems/minitest-5.11.3/lib/minitest.rb +987 -0
  105. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/assertions.rb +693 -0
  106. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/autorun.rb +13 -0
  107. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/benchmark.rb +455 -0
  108. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/expectations.rb +284 -0
  109. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/hell.rb +11 -0
  110. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/mock.rb +240 -0
  111. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/parallel.rb +70 -0
  112. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/pride.rb +4 -0
  113. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/pride_plugin.rb +142 -0
  114. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/spec.rb +331 -0
  115. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/test.rb +220 -0
  116. data/vendor/cache/gems/minitest-5.11.3/lib/minitest/unit.rb +45 -0
  117. data/vendor/cache/gems/minitest-5.11.3/test/minitest/metametameta.rb +102 -0
  118. data/vendor/cache/gems/minitest-5.11.3/test/minitest/test_minitest_benchmark.rb +137 -0
  119. data/vendor/cache/gems/minitest-5.11.3/test/minitest/test_minitest_mock.rb +874 -0
  120. data/vendor/cache/gems/minitest-5.11.3/test/minitest/test_minitest_reporter.rb +299 -0
  121. data/vendor/cache/gems/minitest-5.11.3/test/minitest/test_minitest_spec.rb +987 -0
  122. data/vendor/cache/gems/minitest-5.11.3/test/minitest/test_minitest_test.rb +2142 -0
  123. data/vendor/cache/gems/minitest-reporters-1.2.0/.gitignore +27 -0
  124. data/vendor/cache/gems/minitest-reporters-1.2.0/.ruby-gemset +1 -0
  125. data/vendor/cache/gems/minitest-reporters-1.2.0/.travis.yml +10 -0
  126. data/vendor/cache/gems/minitest-reporters-1.2.0/.yardopts +6 -0
  127. data/vendor/cache/gems/minitest-reporters-1.2.0/CHANGELOG.md +40 -0
  128. data/vendor/cache/gems/minitest-reporters-1.2.0/Gemfile +2 -0
  129. data/vendor/cache/gems/minitest-reporters-1.2.0/LICENSE +20 -0
  130. data/vendor/cache/gems/minitest-reporters-1.2.0/README.md +115 -0
  131. data/vendor/cache/gems/minitest-reporters-1.2.0/Rakefile +60 -0
  132. data/vendor/cache/gems/minitest-reporters-1.2.0/assets/default-reporter.png +0 -0
  133. data/vendor/cache/gems/minitest-reporters-1.2.0/assets/mean_time_reporter.png +0 -0
  134. data/vendor/cache/gems/minitest-reporters-1.2.0/assets/progress-reporter.png +0 -0
  135. data/vendor/cache/gems/minitest-reporters-1.2.0/assets/spec-reporter.png +0 -0
  136. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/extensible_backtrace_filter.rb +67 -0
  137. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/minitest_reporter_plugin.rb +75 -0
  138. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/old_activesupport_fix.rb +24 -0
  139. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/relative_position.rb +26 -0
  140. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters.rb +89 -0
  141. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/ansi.rb +31 -0
  142. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/base_reporter.rb +117 -0
  143. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/default_reporter.rb +228 -0
  144. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/html_reporter.rb +221 -0
  145. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/junit_reporter.rb +157 -0
  146. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/mean_time_reporter.rb +392 -0
  147. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/progress_reporter.rb +96 -0
  148. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/ruby_mate_reporter.rb +54 -0
  149. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/rubymine_reporter.rb +117 -0
  150. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/spec_reporter.rb +61 -0
  151. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/reporters/version.rb +5 -0
  152. data/vendor/cache/gems/minitest-reporters-1.2.0/lib/minitest/templates/index.html.erb +83 -0
  153. data/vendor/cache/gems/minitest-reporters-1.2.0/minitest-reporters.gemspec +31 -0
  154. data/vendor/cache/gems/minitest-reporters-1.2.0/test/fixtures/junit_filename_bug_example_test.rb +21 -0
  155. data/vendor/cache/gems/minitest-reporters-1.2.0/test/fixtures/mean_time_test.rb +8 -0
  156. data/vendor/cache/gems/minitest-reporters-1.2.0/test/fixtures/progress_detailed_skip_test.rb +8 -0
  157. data/vendor/cache/gems/minitest-reporters-1.2.0/test/fixtures/progress_test.rb +8 -0
  158. data/vendor/cache/gems/minitest-reporters-1.2.0/test/fixtures/sample_test.rb +15 -0
  159. data/vendor/cache/gems/minitest-reporters-1.2.0/test/fixtures/spec_test.rb +13 -0
  160. data/vendor/cache/gems/minitest-reporters-1.2.0/test/gallery/bad_test.rb +25 -0
  161. data/vendor/cache/gems/minitest-reporters-1.2.0/test/gallery/good_test.rb +14 -0
  162. data/vendor/cache/gems/minitest-reporters-1.2.0/test/integration/reporters/junit_reporter_test.rb +12 -0
  163. data/vendor/cache/gems/minitest-reporters-1.2.0/test/integration/reporters/mean_time_reporter_test.rb +7 -0
  164. data/vendor/cache/gems/minitest-reporters-1.2.0/test/integration/reporters/progress_reporter_test.rb +34 -0
  165. data/vendor/cache/gems/minitest-reporters-1.2.0/test/test_helper.rb +22 -0
  166. data/vendor/cache/gems/minitest-reporters-1.2.0/test/unit/minitest/extensible_backtrace_filter_test.rb +42 -0
  167. data/vendor/cache/gems/minitest-reporters-1.2.0/test/unit/minitest/mean_time_reporter_unit_test.rb +152 -0
  168. data/vendor/cache/gems/minitest-reporters-1.2.0/test/unit/minitest/minitest_reporter_plugin_test.rb +14 -0
  169. data/vendor/cache/gems/minitest-reporters-1.2.0/test/unit/minitest/reporters_test.rb +52 -0
  170. data/vendor/cache/gems/minitest-reporters-1.2.0/test/unit/minitest/spec_reporter_test.rb +41 -0
  171. data/vendor/cache/gems/rake-10.5.0/.autotest +7 -0
  172. data/vendor/cache/gems/rake-10.5.0/.rubocop.yml +27 -0
  173. data/vendor/cache/gems/rake-10.5.0/.togglerc +7 -0
  174. data/vendor/cache/gems/rake-10.5.0/CONTRIBUTING.rdoc +38 -0
  175. data/vendor/cache/gems/rake-10.5.0/History.rdoc +659 -0
  176. data/vendor/cache/gems/rake-10.5.0/MIT-LICENSE +21 -0
  177. data/vendor/cache/gems/rake-10.5.0/Manifest.txt +166 -0
  178. data/vendor/cache/gems/rake-10.5.0/README.rdoc +139 -0
  179. data/vendor/cache/gems/rake-10.5.0/Rakefile +81 -0
  180. data/vendor/cache/gems/rake-10.5.0/bin/rake +33 -0
  181. data/vendor/cache/gems/rake-10.5.0/doc/command_line_usage.rdoc +158 -0
  182. data/vendor/cache/gems/rake-10.5.0/doc/example/Rakefile1 +38 -0
  183. data/vendor/cache/gems/rake-10.5.0/doc/example/Rakefile2 +35 -0
  184. data/vendor/cache/gems/rake-10.5.0/doc/example/a.c +6 -0
  185. data/vendor/cache/gems/rake-10.5.0/doc/example/b.c +6 -0
  186. data/vendor/cache/gems/rake-10.5.0/doc/example/main.c +11 -0
  187. data/vendor/cache/gems/rake-10.5.0/doc/glossary.rdoc +42 -0
  188. data/vendor/cache/gems/rake-10.5.0/doc/jamis.rb +591 -0
  189. data/vendor/cache/gems/rake-10.5.0/doc/proto_rake.rdoc +127 -0
  190. data/vendor/cache/gems/rake-10.5.0/doc/rake.1 +141 -0
  191. data/vendor/cache/gems/rake-10.5.0/doc/rakefile.rdoc +624 -0
  192. data/vendor/cache/gems/rake-10.5.0/doc/rational.rdoc +151 -0
  193. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.4.14.rdoc +23 -0
  194. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.4.15.rdoc +35 -0
  195. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.5.0.rdoc +53 -0
  196. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.5.3.rdoc +78 -0
  197. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.5.4.rdoc +46 -0
  198. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.6.0.rdoc +141 -0
  199. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.7.0.rdoc +119 -0
  200. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.7.1.rdoc +59 -0
  201. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.7.2.rdoc +121 -0
  202. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.7.3.rdoc +47 -0
  203. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.8.0.rdoc +114 -0
  204. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.8.2.rdoc +165 -0
  205. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.8.3.rdoc +112 -0
  206. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.8.4.rdoc +147 -0
  207. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.8.5.rdoc +53 -0
  208. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.8.6.rdoc +37 -0
  209. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.8.7.rdoc +55 -0
  210. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.0.rdoc +112 -0
  211. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.1.rdoc +52 -0
  212. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.2.2.rdoc +55 -0
  213. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.2.rdoc +49 -0
  214. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.3.rdoc +102 -0
  215. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.4.rdoc +60 -0
  216. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.5.rdoc +55 -0
  217. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-0.9.6.rdoc +64 -0
  218. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-10.0.0.rdoc +178 -0
  219. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-10.0.1.rdoc +58 -0
  220. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-10.0.2.rdoc +53 -0
  221. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-10.0.3.rdoc +191 -0
  222. data/vendor/cache/gems/rake-10.5.0/doc/release_notes/rake-10.1.0.rdoc +61 -0
  223. data/vendor/cache/gems/rake-10.5.0/lib/rake.rb +79 -0
  224. data/vendor/cache/gems/rake-10.5.0/lib/rake/alt_system.rb +110 -0
  225. data/vendor/cache/gems/rake-10.5.0/lib/rake/application.rb +790 -0
  226. data/vendor/cache/gems/rake-10.5.0/lib/rake/backtrace.rb +23 -0
  227. data/vendor/cache/gems/rake-10.5.0/lib/rake/clean.rb +76 -0
  228. data/vendor/cache/gems/rake-10.5.0/lib/rake/cloneable.rb +16 -0
  229. data/vendor/cache/gems/rake-10.5.0/lib/rake/contrib/.document +1 -0
  230. data/vendor/cache/gems/rake-10.5.0/lib/rake/contrib/compositepublisher.rb +21 -0
  231. data/vendor/cache/gems/rake-10.5.0/lib/rake/contrib/ftptools.rb +137 -0
  232. data/vendor/cache/gems/rake-10.5.0/lib/rake/contrib/publisher.rb +81 -0
  233. data/vendor/cache/gems/rake-10.5.0/lib/rake/contrib/rubyforgepublisher.rb +18 -0
  234. data/vendor/cache/gems/rake-10.5.0/lib/rake/contrib/sshpublisher.rb +61 -0
  235. data/vendor/cache/gems/rake-10.5.0/lib/rake/contrib/sys.rb +4 -0
  236. data/vendor/cache/gems/rake-10.5.0/lib/rake/cpu_counter.rb +125 -0
  237. data/vendor/cache/gems/rake-10.5.0/lib/rake/default_loader.rb +14 -0
  238. data/vendor/cache/gems/rake-10.5.0/lib/rake/dsl_definition.rb +201 -0
  239. data/vendor/cache/gems/rake-10.5.0/lib/rake/early_time.rb +21 -0
  240. data/vendor/cache/gems/rake-10.5.0/lib/rake/ext/core.rb +25 -0
  241. data/vendor/cache/gems/rake-10.5.0/lib/rake/ext/module.rb +2 -0
  242. data/vendor/cache/gems/rake-10.5.0/lib/rake/ext/pathname.rb +25 -0
  243. data/vendor/cache/gems/rake-10.5.0/lib/rake/ext/string.rb +175 -0
  244. data/vendor/cache/gems/rake-10.5.0/lib/rake/ext/time.rb +18 -0
  245. data/vendor/cache/gems/rake-10.5.0/lib/rake/file_creation_task.rb +24 -0
  246. data/vendor/cache/gems/rake-10.5.0/lib/rake/file_list.rb +428 -0
  247. data/vendor/cache/gems/rake-10.5.0/lib/rake/file_task.rb +46 -0
  248. data/vendor/cache/gems/rake-10.5.0/lib/rake/file_utils.rb +128 -0
  249. data/vendor/cache/gems/rake-10.5.0/lib/rake/file_utils_ext.rb +144 -0
  250. data/vendor/cache/gems/rake-10.5.0/lib/rake/gempackagetask.rb +4 -0
  251. data/vendor/cache/gems/rake-10.5.0/lib/rake/invocation_chain.rb +56 -0
  252. data/vendor/cache/gems/rake-10.5.0/lib/rake/invocation_exception_mixin.rb +16 -0
  253. data/vendor/cache/gems/rake-10.5.0/lib/rake/late_time.rb +17 -0
  254. data/vendor/cache/gems/rake-10.5.0/lib/rake/linked_list.rb +103 -0
  255. data/vendor/cache/gems/rake-10.5.0/lib/rake/loaders/makefile.rb +53 -0
  256. data/vendor/cache/gems/rake-10.5.0/lib/rake/multi_task.rb +13 -0
  257. data/vendor/cache/gems/rake-10.5.0/lib/rake/name_space.rb +38 -0
  258. data/vendor/cache/gems/rake-10.5.0/lib/rake/packagetask.rb +199 -0
  259. data/vendor/cache/gems/rake-10.5.0/lib/rake/pathmap.rb +3 -0
  260. data/vendor/cache/gems/rake-10.5.0/lib/rake/phony.rb +15 -0
  261. data/vendor/cache/gems/rake-10.5.0/lib/rake/private_reader.rb +20 -0
  262. data/vendor/cache/gems/rake-10.5.0/lib/rake/promise.rb +99 -0
  263. data/vendor/cache/gems/rake-10.5.0/lib/rake/pseudo_status.rb +29 -0
  264. data/vendor/cache/gems/rake-10.5.0/lib/rake/rake_module.rb +38 -0
  265. data/vendor/cache/gems/rake-10.5.0/lib/rake/rake_test_loader.rb +22 -0
  266. data/vendor/cache/gems/rake-10.5.0/lib/rake/rdoctask.rb +4 -0
  267. data/vendor/cache/gems/rake-10.5.0/lib/rake/ruby182_test_unit_fix.rb +29 -0
  268. data/vendor/cache/gems/rake-10.5.0/lib/rake/rule_recursion_overflow_error.rb +20 -0
  269. data/vendor/cache/gems/rake-10.5.0/lib/rake/runtest.rb +27 -0
  270. data/vendor/cache/gems/rake-10.5.0/lib/rake/scope.rb +42 -0
  271. data/vendor/cache/gems/rake-10.5.0/lib/rake/task.rb +383 -0
  272. data/vendor/cache/gems/rake-10.5.0/lib/rake/task_argument_error.rb +7 -0
  273. data/vendor/cache/gems/rake-10.5.0/lib/rake/task_arguments.rb +98 -0
  274. data/vendor/cache/gems/rake-10.5.0/lib/rake/task_manager.rb +307 -0
  275. data/vendor/cache/gems/rake-10.5.0/lib/rake/tasklib.rb +24 -0
  276. data/vendor/cache/gems/rake-10.5.0/lib/rake/testtask.rb +213 -0
  277. data/vendor/cache/gems/rake-10.5.0/lib/rake/thread_history_display.rb +48 -0
  278. data/vendor/cache/gems/rake-10.5.0/lib/rake/thread_pool.rb +164 -0
  279. data/vendor/cache/gems/rake-10.5.0/lib/rake/trace_output.rb +22 -0
  280. data/vendor/cache/gems/rake-10.5.0/lib/rake/version.rb +7 -0
  281. data/vendor/cache/gems/rake-10.5.0/lib/rake/win32.rb +56 -0
  282. data/vendor/cache/gems/rake-10.5.0/rakelib/publish.rake +20 -0
  283. data/vendor/cache/gems/rake-10.5.0/rakelib/test_times.rake +25 -0
  284. data/vendor/cache/gems/rake-10.5.0/test/file_creation.rb +34 -0
  285. data/vendor/cache/gems/rake-10.5.0/test/helper.rb +129 -0
  286. data/vendor/cache/gems/rake-10.5.0/test/support/rakefile_definitions.rb +478 -0
  287. data/vendor/cache/gems/rake-10.5.0/test/support/ruby_runner.rb +34 -0
  288. data/vendor/cache/gems/rake-10.5.0/test/test_private_reader.rb +42 -0
  289. data/vendor/cache/gems/rake-10.5.0/test/test_rake.rb +40 -0
  290. data/vendor/cache/gems/rake-10.5.0/test/test_rake_application.rb +643 -0
  291. data/vendor/cache/gems/rake-10.5.0/test/test_rake_application_options.rb +468 -0
  292. data/vendor/cache/gems/rake-10.5.0/test/test_rake_backtrace.rb +119 -0
  293. data/vendor/cache/gems/rake-10.5.0/test/test_rake_clean.rb +61 -0
  294. data/vendor/cache/gems/rake-10.5.0/test/test_rake_cpu_counter.rb +68 -0
  295. data/vendor/cache/gems/rake-10.5.0/test/test_rake_definitions.rb +84 -0
  296. data/vendor/cache/gems/rake-10.5.0/test/test_rake_directory_task.rb +76 -0
  297. data/vendor/cache/gems/rake-10.5.0/test/test_rake_dsl.rb +40 -0
  298. data/vendor/cache/gems/rake-10.5.0/test/test_rake_early_time.rb +31 -0
  299. data/vendor/cache/gems/rake-10.5.0/test/test_rake_extension.rb +59 -0
  300. data/vendor/cache/gems/rake-10.5.0/test/test_rake_file_creation_task.rb +56 -0
  301. data/vendor/cache/gems/rake-10.5.0/test/test_rake_file_list.rb +670 -0
  302. data/vendor/cache/gems/rake-10.5.0/test/test_rake_file_list_path_map.rb +8 -0
  303. data/vendor/cache/gems/rake-10.5.0/test/test_rake_file_task.rb +197 -0
  304. data/vendor/cache/gems/rake-10.5.0/test/test_rake_file_utils.rb +314 -0
  305. data/vendor/cache/gems/rake-10.5.0/test/test_rake_ftp_file.rb +74 -0
  306. data/vendor/cache/gems/rake-10.5.0/test/test_rake_functional.rb +482 -0
  307. data/vendor/cache/gems/rake-10.5.0/test/test_rake_invocation_chain.rb +64 -0
  308. data/vendor/cache/gems/rake-10.5.0/test/test_rake_late_time.rb +18 -0
  309. data/vendor/cache/gems/rake-10.5.0/test/test_rake_linked_list.rb +84 -0
  310. data/vendor/cache/gems/rake-10.5.0/test/test_rake_makefile_loader.rb +46 -0
  311. data/vendor/cache/gems/rake-10.5.0/test/test_rake_multi_task.rb +64 -0
  312. data/vendor/cache/gems/rake-10.5.0/test/test_rake_name_space.rb +57 -0
  313. data/vendor/cache/gems/rake-10.5.0/test/test_rake_package_task.rb +79 -0
  314. data/vendor/cache/gems/rake-10.5.0/test/test_rake_path_map.rb +168 -0
  315. data/vendor/cache/gems/rake-10.5.0/test/test_rake_path_map_explode.rb +34 -0
  316. data/vendor/cache/gems/rake-10.5.0/test/test_rake_path_map_partial.rb +18 -0
  317. data/vendor/cache/gems/rake-10.5.0/test/test_rake_pathname_extensions.rb +15 -0
  318. data/vendor/cache/gems/rake-10.5.0/test/test_rake_pseudo_status.rb +21 -0
  319. data/vendor/cache/gems/rake-10.5.0/test/test_rake_rake_test_loader.rb +20 -0
  320. data/vendor/cache/gems/rake-10.5.0/test/test_rake_reduce_compat.rb +26 -0
  321. data/vendor/cache/gems/rake-10.5.0/test/test_rake_require.rb +40 -0
  322. data/vendor/cache/gems/rake-10.5.0/test/test_rake_rules.rb +388 -0
  323. data/vendor/cache/gems/rake-10.5.0/test/test_rake_scope.rb +44 -0
  324. data/vendor/cache/gems/rake-10.5.0/test/test_rake_task.rb +393 -0
  325. data/vendor/cache/gems/rake-10.5.0/test/test_rake_task_argument_parsing.rb +119 -0
  326. data/vendor/cache/gems/rake-10.5.0/test/test_rake_task_arguments.rb +127 -0
  327. data/vendor/cache/gems/rake-10.5.0/test/test_rake_task_lib.rb +9 -0
  328. data/vendor/cache/gems/rake-10.5.0/test/test_rake_task_manager.rb +178 -0
  329. data/vendor/cache/gems/rake-10.5.0/test/test_rake_task_manager_argument_resolution.rb +19 -0
  330. data/vendor/cache/gems/rake-10.5.0/test/test_rake_task_with_arguments.rb +172 -0
  331. data/vendor/cache/gems/rake-10.5.0/test/test_rake_test_task.rb +146 -0
  332. data/vendor/cache/gems/rake-10.5.0/test/test_rake_thread_pool.rb +145 -0
  333. data/vendor/cache/gems/rake-10.5.0/test/test_rake_top_level_functions.rb +71 -0
  334. data/vendor/cache/gems/rake-10.5.0/test/test_rake_win32.rb +72 -0
  335. data/vendor/cache/gems/rake-10.5.0/test/test_thread_history_display.rb +101 -0
  336. data/vendor/cache/gems/rake-10.5.0/test/test_trace_output.rb +52 -0
  337. data/vendor/cache/gems/ruby-progressbar-1.10.0/LICENSE.txt +19 -0
  338. data/vendor/cache/gems/ruby-progressbar-1.10.0/README.md +38 -0
  339. data/vendor/cache/gems/ruby-progressbar-1.10.0/Rakefile +2 -0
  340. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar.rb +18 -0
  341. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/base.rb +183 -0
  342. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/calculators/length.rb +100 -0
  343. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/calculators/running_average.rb +9 -0
  344. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/components.rb +5 -0
  345. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/components/bar.rb +102 -0
  346. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/components/percentage.rb +29 -0
  347. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/components/rate.rb +43 -0
  348. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/components/time.rb +107 -0
  349. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/components/title.rb +13 -0
  350. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/errors/invalid_progress_error.rb +4 -0
  351. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/format.rb +3 -0
  352. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/format/formatter.rb +27 -0
  353. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/format/molecule.rb +60 -0
  354. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/format/string.rb +36 -0
  355. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/output.rb +68 -0
  356. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/outputs/non_tty.rb +47 -0
  357. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/outputs/null.rb +33 -0
  358. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/outputs/tty.rb +32 -0
  359. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/progress.rb +118 -0
  360. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/refinements.rb +1 -0
  361. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/refinements/enumerator.rb +23 -0
  362. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/throttle.rb +25 -0
  363. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/time.rb +32 -0
  364. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/timer.rb +72 -0
  365. data/vendor/cache/gems/ruby-progressbar-1.10.0/lib/ruby-progressbar/version.rb +3 -0
  366. data/vendor/cache/minitest-5.11.3.gem +0 -0
  367. data/vendor/cache/minitest-reporters-1.2.0.gem +0 -0
  368. data/vendor/cache/rake-10.5.0.gem +0 -0
  369. data/vendor/cache/ruby-progressbar-1.10.0.gem +0 -0
  370. data/vendor/cache/specifications/ansi-1.5.0.gemspec +49 -0
  371. data/vendor/cache/specifications/builder-3.2.3.gemspec +21 -0
  372. data/vendor/cache/specifications/minitest-5.11.3.gemspec +39 -0
  373. data/vendor/cache/specifications/minitest-reporters-1.2.0.gemspec +49 -0
  374. data/vendor/cache/specifications/rake-10.5.0.gemspec +43 -0
  375. data/vendor/cache/specifications/ruby-progressbar-1.10.0.gemspec +46 -0
  376. metadata +460 -0
@@ -0,0 +1,221 @@
1
+ require 'builder'
2
+ require 'fileutils'
3
+ require 'erb'
4
+
5
+ module Minitest
6
+ module Reporters
7
+ # A reporter for generating HTML test reports
8
+ # This is recommended to be used with a CI server, where the report is kept as an artifact and is accessible via a shared link
9
+ #
10
+ # The reporter sorts the results alphabetically and then by results so that failing and skipped tests are at the top.
11
+ #
12
+ # When using Minitest Specs, the number prefix is dropped from the name of the test so that it reads well
13
+ #
14
+ # On each test run all files in the reports directory are deleted, this prevents a build up of old reports
15
+ #
16
+ # The report is generated using ERB. A custom ERB template can be provided but it is not required
17
+ # The default ERB template uses JQuery and Bootstrap, both of these are included by referencing the CDN sites
18
+ class HtmlReporter < BaseReporter
19
+
20
+ # The title of the report
21
+ attr_reader :title
22
+
23
+ # The number of tests that passed
24
+ def passes
25
+ count - failures - errors - skips
26
+ end
27
+
28
+ # The percentage of tests that passed, calculated in a way that avoids rounding errors
29
+ def percent_passes
30
+ 100 - percent_skipps - percent_errors_failures
31
+ end
32
+
33
+ # The percentage of tests that were skipped
34
+ def percent_skipps
35
+ (skips/count.to_f * 100).to_i
36
+ end
37
+
38
+ # The percentage of tests that failed
39
+ def percent_errors_failures
40
+ ((errors+failures)/count.to_f * 100).to_i
41
+ end
42
+
43
+ # Trims off the number prefix on test names when using Minitest Specs
44
+ def friendly_name(test)
45
+ groups = test.name.scan(/(test_\d+_)(.*)/i)
46
+ return test.name if groups.empty?
47
+ "it #{groups[0][1]}"
48
+ end
49
+
50
+ # The constructor takes a hash, and uses the following keys:
51
+ # :title - the title that will be used in the report, defaults to 'Test Results'
52
+ # :reports_dir - the directory the reports should be written to, defaults to 'test/html_reports'
53
+ # :erb_template - the path to a custom ERB template, defaults to the supplied ERB template
54
+ # :mode - Useful for debugging, :terse suppresses errors and is the default, :verbose lets errors bubble up
55
+ # :output_filename - the report's filename, defaults to 'index.html'
56
+ def initialize(args = {})
57
+ super({})
58
+
59
+ defaults = {
60
+ :title => 'Test Results',
61
+ :erb_template => "#{File.dirname(__FILE__)}/../templates/index.html.erb",
62
+ :reports_dir => 'test/html_reports',
63
+ :mode => :safe,
64
+ :output_filename => 'index.html'
65
+ }
66
+
67
+ settings = defaults.merge(args)
68
+
69
+ @mode = settings[:mode]
70
+ @title = settings[:title]
71
+ @erb_template = settings[:erb_template]
72
+ @output_filename = settings[:output_filename]
73
+ reports_dir = settings[:reports_dir]
74
+
75
+ @reports_path = File.absolute_path(reports_dir)
76
+ end
77
+
78
+ def start
79
+ super
80
+
81
+ puts "Emptying #{@reports_path}"
82
+ FileUtils.mkdir_p(@reports_path)
83
+ File.delete(html_file) if File.exist?(html_file)
84
+ end
85
+
86
+ # Called by the framework to generate the report
87
+ def report
88
+ super
89
+
90
+ begin
91
+ puts "Writing HTML reports to #{@reports_path}"
92
+ erb_str = File.read(@erb_template)
93
+ renderer = ERB.new(erb_str)
94
+
95
+ tests_by_suites = tests.group_by { |test| test_class(test) } # taken from the JUnit reporter
96
+
97
+ suites = tests_by_suites.map do |suite, tests|
98
+ suite_summary = summarize_suite(suite, tests)
99
+ suite_summary[:tests] = tests.sort { |a, b| compare_tests(a, b) }
100
+ suite_summary
101
+ end
102
+
103
+ suites.sort! { |a, b| compare_suites(a, b) }
104
+
105
+ result = renderer.result(binding)
106
+ File.open(html_file, 'w') do |f|
107
+ f.write(result)
108
+ end
109
+
110
+ rescue Exception => e
111
+ puts 'There was an error writing the HTML report'
112
+ puts 'This may have been caused by cancelling the test run'
113
+ puts 'Use mode => :verbose in the HTML reporters constructor to see more detail' if @mode == :terse
114
+ puts 'Use mode => :terse in the HTML reporters constructor to see less detail' if @mode != :terse
115
+ raise e if @mode != :terse
116
+ end
117
+
118
+ end
119
+
120
+ private
121
+ def html_file
122
+ "#{@reports_path}/#{@output_filename}"
123
+ end
124
+
125
+ def compare_suites_by_name(suite_a, suite_b)
126
+ suite_a[:name] <=> suite_b[:name]
127
+ end
128
+
129
+ def compare_tests_by_name(test_a, test_b)
130
+ friendly_name(test_a) <=> friendly_name(test_b)
131
+ end
132
+
133
+ # Test suites are first ordered by evaluating the results of the tests, then by test suite name
134
+ # Test suites which have failing tests are given highest order
135
+ # Tests suites which have skipped tests are given second highest priority
136
+ def compare_suites(suite_a, suite_b)
137
+ return compare_suites_by_name(suite_a, suite_b) if suite_a[:has_errors_or_failures] && suite_b[:has_errors_or_failures]
138
+ return -1 if suite_a[:has_errors_or_failures] && !suite_b[:has_errors_or_failures]
139
+ return 1 if !suite_a[:has_errors_or_failures] && suite_b[:has_errors_or_failures]
140
+
141
+ return compare_suites_by_name(suite_a, suite_b) if suite_a[:has_skipps] && suite_b[:has_skipps]
142
+ return -1 if suite_a[:has_skipps] && !suite_b[:has_skipps]
143
+ return 1 if !suite_a[:has_skipps] && suite_b[:has_skipps]
144
+
145
+ compare_suites_by_name(suite_a, suite_b)
146
+ end
147
+
148
+ # Tests are first ordered by evaluating the results of the tests, then by tests names
149
+ # Tess which fail are given highest order
150
+ # Tests which are skipped are given second highest priority
151
+ def compare_tests(test_a, test_b)
152
+ return compare_tests_by_name(test_a, test_b) if test_fail_or_error?(test_a) && test_fail_or_error?(test_b)
153
+
154
+ return -1 if test_fail_or_error?(test_a) && !test_fail_or_error?(test_b)
155
+ return 1 if !test_fail_or_error?(test_a) && test_fail_or_error?(test_b)
156
+
157
+ return compare_tests_by_name(test_a, test_b) if test_a.skipped? && test_b.skipped?
158
+ return -1 if test_a.skipped? && !test_b.skipped?
159
+ return 1 if !test_a.skipped? && test_b.skipped?
160
+
161
+ compare_tests_by_name(test_a, test_b)
162
+ end
163
+
164
+ def test_fail_or_error?(test)
165
+ test.error? || test.failure
166
+ end
167
+
168
+ # based on analyze_suite from the JUnit reporter
169
+ def summarize_suite(suite, tests)
170
+ summary = Hash.new(0)
171
+ summary[:name] = suite.to_s
172
+ tests.each do |test|
173
+ summary[:"#{result(test)}_count"] += 1
174
+ summary[:assertion_count] += test.assertions
175
+ summary[:test_count] += 1
176
+ summary[:time] += test.time
177
+ end
178
+ summary[:has_errors_or_failures] = (summary[:fail_count] + summary[:error_count]) > 0
179
+ summary[:has_skipps] = summary[:skip_count] > 0
180
+ summary
181
+ end
182
+
183
+ # based on message_for(test) from the JUnit reporter
184
+ def message_for(test)
185
+ suite = test.class
186
+ name = test.name
187
+ e = test.failure
188
+
189
+ if test.passed?
190
+ nil
191
+ elsif test.skipped?
192
+ "Skipped:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
193
+ elsif test.failure
194
+ "Failure:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
195
+ elsif test.error?
196
+ "Error:\n#{name}(#{suite}):\n#{e.message}"
197
+ end
198
+ end
199
+
200
+ # taken from the JUnit reporter
201
+ def location(exception)
202
+ last_before_assertion = ''
203
+ exception.backtrace.reverse_each do |s|
204
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
205
+ last_before_assertion = s
206
+ end
207
+ last_before_assertion.sub(/:in .*$/, '')
208
+ end
209
+
210
+ def total_time_to_hms
211
+ return ('%.2fs' % total_time) if total_time < 1
212
+
213
+ hours = (total_time / (60 * 60)).round
214
+ minutes = ((total_time / 60) % 60).round.to_s.rjust(2,'0')
215
+ seconds = (total_time % 60).round.to_s.rjust(2,'0')
216
+
217
+ "#{ hours }h#{ minutes }m#{ seconds }s"
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,157 @@
1
+ require 'builder'
2
+ require 'fileutils'
3
+ module Minitest
4
+ module Reporters
5
+ # A reporter for writing JUnit test reports
6
+ # Intended for easy integration with CI servers - tested on JetBrains TeamCity
7
+ #
8
+ # Inspired by ci_reporter (see https://github.com/nicksieger/ci_reporter)
9
+ # Also inspired by Marc Seeger's attempt at producing a JUnitReporter (see https://github.com/rb2k/minitest-reporters/commit/e13d95b5f884453a9c77f62bc5cba3fa1df30ef5)
10
+ # Also inspired by minitest-ci (see https://github.com/bhenderson/minitest-ci)
11
+ class JUnitReporter < BaseReporter
12
+ def initialize(reports_dir = "test/reports", empty = true, options = {})
13
+ super({})
14
+ @reports_path = File.absolute_path(reports_dir)
15
+ @single_file = options[:single_file]
16
+ @base_path = options[:base_path] || Dir.pwd
17
+
18
+ if empty
19
+ puts "Emptying #{@reports_path}"
20
+ FileUtils.mkdir_p(@reports_path)
21
+ File.delete(*Dir.glob("#{@reports_path}/TEST-*.xml"))
22
+ end
23
+ end
24
+
25
+ def report
26
+ super
27
+
28
+ puts "Writing XML reports to #{@reports_path}"
29
+ suites = tests.group_by { |test|
30
+ test_class(test)
31
+ }
32
+
33
+ if @single_file
34
+ xml = Builder::XmlMarkup.new(:indent => 2)
35
+ xml.instruct!
36
+ xml.test_suites do
37
+ suites.each do |suite, tests|
38
+ parse_xml_for(xml, suite, tests)
39
+ end
40
+ end
41
+ File.open(filename_for('minitest'), "w") { |file| file << xml.target! }
42
+ else
43
+ suites.each do |suite, tests|
44
+ xml = Builder::XmlMarkup.new(:indent => 2)
45
+ xml.instruct!
46
+ xml.test_suites do
47
+ parse_xml_for(xml, suite, tests)
48
+ end
49
+ File.open(filename_for(suite), "w") { |file| file << xml.target! }
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def get_source_location(result)
57
+ if result.respond_to? :klass
58
+ result.source_location
59
+ else
60
+ result.method(result.name).source_location
61
+ end
62
+ end
63
+
64
+ def parse_xml_for(xml, suite, tests)
65
+ suite_result = analyze_suite(tests)
66
+ file_path = Pathname.new(get_source_location(tests.first).first)
67
+ base_path = Pathname.new(@base_path)
68
+ relative_path = file_path.relative_path_from(base_path)
69
+
70
+ xml.testsuite(:name => suite, :filepath => relative_path,
71
+ :skipped => suite_result[:skip_count], :failures => suite_result[:fail_count],
72
+ :errors => suite_result[:error_count], :tests => suite_result[:test_count],
73
+ :assertions => suite_result[:assertion_count], :time => suite_result[:time]) do
74
+ tests.each do |test|
75
+ lineno = get_source_location(test).last
76
+ xml.testcase(:name => test.name, :lineno => lineno, :classname => suite, :assertions => test.assertions,
77
+ :time => test.time) do
78
+ xml << xml_message_for(test) unless test.passed?
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def xml_message_for(test)
85
+ # This is a trick lifted from ci_reporter
86
+ xml = Builder::XmlMarkup.new(:indent => 2, :margin => 2)
87
+
88
+ def xml.trunc!(txt)
89
+ txt.sub(/\n.*/m, '...')
90
+ end
91
+
92
+ e = test.failure
93
+
94
+ if test.skipped?
95
+ xml.skipped(:type => test.name)
96
+ elsif test.error?
97
+ xml.error(:type => test.name, :message => xml.trunc!(e.message)) do
98
+ xml.text!(message_for(test))
99
+ end
100
+ elsif test.failure
101
+ xml.failure(:type => test.name, :message => xml.trunc!(e.message)) do
102
+ xml.text!(message_for(test))
103
+ end
104
+ end
105
+ end
106
+
107
+ def message_for(test)
108
+ suite = test.class
109
+ name = test.name
110
+ e = test.failure
111
+
112
+ if test.passed?
113
+ nil
114
+ elsif test.skipped?
115
+ "Skipped:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
116
+ elsif test.failure
117
+ "Failure:\n#{name}(#{suite}) [#{location(e)}]:\n#{e.message}\n"
118
+ elsif test.error?
119
+ "Error:\n#{name}(#{suite}):\n#{e.message}"
120
+ end
121
+ end
122
+
123
+ def location(exception)
124
+ last_before_assertion = ''
125
+ exception.backtrace.reverse_each do |s|
126
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
127
+ last_before_assertion = s
128
+ end
129
+ last_before_assertion.sub(/:in .*$/, '')
130
+ end
131
+
132
+ def analyze_suite(tests)
133
+ result = Hash.new(0)
134
+ result[:time] = 0
135
+ tests.each do |test|
136
+ result[:"#{result(test)}_count"] += 1
137
+ result[:assertion_count] += test.assertions
138
+ result[:test_count] += 1
139
+ result[:time] += test.time
140
+ end
141
+ result
142
+ end
143
+
144
+ def filename_for(suite)
145
+ file_counter = 0
146
+ suite_name = suite.to_s[0..240].gsub(/[^a-zA-Z0-9]+/, '-') # restrict max filename length, to be kind to filesystems
147
+ filename = "TEST-#{suite_name}.xml"
148
+ while File.exist?(File.join(@reports_path, filename)) # restrict number of tries, to avoid infinite loops
149
+ file_counter += 1
150
+ filename = "TEST-#{suite_name}-#{file_counter}.xml"
151
+ puts "Too many duplicate files, overwriting earlier report #{filename}" and break if file_counter >= 99
152
+ end
153
+ File.join(@reports_path, filename)
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,392 @@
1
+ require 'minitest/reporters'
2
+ require 'yaml'
3
+
4
+ module Minitest
5
+ module Reporters
6
+
7
+ # This reporter creates a report providing the average (mean), minimum and
8
+ # maximum times for a test to run. Running this for all your tests will
9
+ # allow you to:
10
+ #
11
+ # 1) Identify the slowest running tests over time as potential candidates
12
+ # for improvements or refactoring.
13
+ # 2) Identify (and fix) regressions in test run speed caused by changes to
14
+ # your tests or algorithms in your code.
15
+ # 3) Provide an abundance of statistics to enjoy.
16
+ #
17
+ # This is achieved by creating a (configurable) 'previous runs' statistics
18
+ # file which is parsed at the end of each run to provide a new
19
+ # (configurable) report. These statistics can be reset at any time by using
20
+ # a simple rake task:
21
+ #
22
+ # rake reset_statistics
23
+ #
24
+ class MeanTimeReporter < Minitest::Reporters::DefaultReporter
25
+
26
+ class InvalidOrder < StandardError; end
27
+ class InvalidSortColumn < StandardError; end
28
+
29
+ # Reset the statistics file for this reporter. Called via a rake task:
30
+ #
31
+ # rake reset_statistics
32
+ #
33
+ # @return [Boolean]
34
+ def self.reset_statistics!
35
+ new.reset_statistics!
36
+ end
37
+
38
+ # @param options [Hash]
39
+ # @option previous_runs_filename [String] Contains the times for each test
40
+ # by description. Defaults to '/tmp/minitest_reporters_previous_run'.
41
+ # @option report_filename [String] Contains the parsed results for the
42
+ # last test run. Defaults to '/tmp/minitest_reporters_report'.
43
+ # @option show_count [Fixnum] The number of tests to show in the report
44
+ # summary at the end of the test run. Default is 15.
45
+ # @option show_progress [Boolean] If true it prints pass/skip/fail marks.
46
+ # Default is true.
47
+ # @option show_all_runs [Boolean] If true it shows all recorded suit results.
48
+ # Default is true.
49
+ # @option sort_column [Symbol] One of :avg (default), :min, :max, :last.
50
+ # Determines the column by which the report summary is sorted.
51
+ # @option order [Symbol] One of :desc (default), or :asc. By default the
52
+ # report summary is listed slowest to fastest (:desc). :asc will order
53
+ # the report summary as fastest to slowest.
54
+ # @return [Minitest::Reporters::MeanTimeReporter]
55
+ def initialize(options = {})
56
+ super
57
+
58
+ @all_suite_times = []
59
+ end
60
+
61
+ # Copies the suite times from the
62
+ # {Minitest::Reporters::DefaultReporter#after_suite} method, making them
63
+ # available to this class.
64
+ #
65
+ # @return [Hash<String => Float>]
66
+ def after_suite(suite)
67
+ super
68
+
69
+ @all_suite_times = @suite_times
70
+ end
71
+
72
+ # Runs the {Minitest::Reporters::DefaultReporter#report} method and then
73
+ # enhances it by storing the results to the 'previous_runs_filename' and
74
+ # outputs the parsed results to both the 'report_filename' and the
75
+ # terminal.
76
+ #
77
+ def report
78
+ super
79
+
80
+ create_or_update_previous_runs!
81
+
82
+ create_new_report!
83
+
84
+ write_to_screen!
85
+ end
86
+
87
+ def on_start
88
+ super if options[:show_progress]
89
+ end
90
+
91
+ def on_record(test)
92
+ super if options[:show_progress]
93
+ end
94
+
95
+ def on_report
96
+ super if options[:show_progress]
97
+ end
98
+
99
+ # Resets the 'previous runs' file, essentially removing all previous
100
+ # statistics gathered.
101
+ #
102
+ # @return [void]
103
+ def reset_statistics!
104
+ File.open(previous_runs_filename, 'w+') { |f| f.write('') }
105
+ end
106
+
107
+ protected
108
+
109
+ attr_accessor :all_suite_times
110
+
111
+ private
112
+
113
+ # @return [Hash<String => Float>]
114
+ def current_run
115
+ Hash[all_suite_times]
116
+ end
117
+
118
+ # @return [Hash] Sets default values for the filenames used by this class,
119
+ # and the number of tests to output to output to the screen after each
120
+ # run.
121
+ def defaults
122
+ {
123
+ order: :desc,
124
+ show_count: 15,
125
+ show_progress: true,
126
+ show_all_runs: true,
127
+ sort_column: :avg,
128
+ previous_runs_filename: '/tmp/minitest_reporters_previous_run',
129
+ report_filename: '/tmp/minitest_reporters_report',
130
+ }
131
+ end
132
+
133
+ # Added to the top of the report file and to the screen output.
134
+ #
135
+ # @return [String]
136
+ def report_title
137
+ "\n\e[4mMinitest Reporters: Mean Time Report\e[24m " \
138
+ "(Samples: #{samples}, Order: #{sort_column.inspect} " \
139
+ "#{order.inspect})\n"
140
+ end
141
+
142
+ # The report itself. Displays statistics about all runs, ideal for use
143
+ # with the Unix 'head' command. Listed in slowest average descending
144
+ # order.
145
+ #
146
+ # @return [String]
147
+ def report_body
148
+ order_sorted_body.each_with_object([]) do |result, obj|
149
+ rating = rate(result[:last], result[:min], result[:max])
150
+
151
+ obj << "#{avg_label} #{result[:avg].to_s.ljust(12)} " \
152
+ "#{min_label} #{result[:min].to_s.ljust(12)} " \
153
+ "#{max_label} #{result[:max].to_s.ljust(12)} " \
154
+ "#{run_label(rating)} #{result[:last].to_s.ljust(12)} " \
155
+ "#{des_label} #{result[:desc]}\n"
156
+ end.join
157
+ end
158
+
159
+ # @return [String] All of the column-sorted results sorted by the :order
160
+ # option. (Defaults to :desc).
161
+ def order_sorted_body
162
+ if desc?
163
+ column_sorted_body.reverse
164
+
165
+ elsif asc?
166
+ column_sorted_body
167
+
168
+ end
169
+ end
170
+
171
+ # @return [Array<Hash<Symbol => String>>] All of the results sorted by
172
+ # the :sort_column option. (Defaults to :avg).
173
+ def column_sorted_body
174
+ runs = options[:show_all_runs] ? previous_run : current_run
175
+ runs.keys.each_with_object([]) do |description, obj|
176
+ timings = previous_run[description]
177
+ size = Array(timings).size
178
+ sum = Array(timings).inject { |total, x| total + x }
179
+ obj << {
180
+ avg: (sum / size).round(9),
181
+ min: Array(timings).min.round(9),
182
+ max: Array(timings).max.round(9),
183
+ last: Array(timings).last.round(9),
184
+ desc: description,
185
+ }
186
+ end.sort_by { |k| k[sort_column] }
187
+ end
188
+
189
+ # @return [Hash]
190
+ def options
191
+ defaults.merge!(@options)
192
+ end
193
+
194
+ # @return [Fixnum] The number of tests to output to output to the screen
195
+ # after each run.
196
+ def show_count
197
+ options[:show_count]
198
+ end
199
+
200
+ # @return [Hash<String => Array<Float>]
201
+ def previous_run
202
+ @previous_run ||= YAML.load_file(previous_runs_filename)
203
+ end
204
+
205
+ # @return [String] The path to the file which contains all the durations
206
+ # for each test run. The previous runs file is in YAML format, using the
207
+ # test name for the key and an array containing the time taken to run
208
+ # this test for values.
209
+ def previous_runs_filename
210
+ options[:previous_runs_filename]
211
+ end
212
+
213
+ # Returns a boolean indicating whether a previous runs file exists.
214
+ #
215
+ # @return [Boolean]
216
+ def previously_ran?
217
+ File.exist?(previous_runs_filename)
218
+ end
219
+
220
+ # @return [String] The path to the file which contains the parsed test
221
+ # results. The results file contains a line for each test with the
222
+ # average time of the test, the minimum time the test took to run,
223
+ # the maximum time the test took to run and a description of the test
224
+ # (which is the test name as emitted by Minitest).
225
+ def report_filename
226
+ options[:report_filename]
227
+ end
228
+
229
+ # A barbaric way to find out how many runs are in the previous runs file;
230
+ # this method takes the first test listed, and counts its samples
231
+ # trusting (naively) all runs to be the same number of samples. This will
232
+ # produce incorrect averages when new tests are added, so it is advised
233
+ # to restart the statistics by removing the 'previous runs' file. A rake
234
+ # task is provided to make this more convenient.
235
+ #
236
+ # rake reset_statistics
237
+ #
238
+ # @return [Fixnum]
239
+ def samples
240
+ return 1 unless previous_run.first[1].is_a?(Array)
241
+
242
+ previous_run.first[1].size
243
+ end
244
+
245
+ # Creates a new 'previous runs' file, or updates the existing one with
246
+ # the latest timings.
247
+ #
248
+ # @return [void]
249
+ def create_or_update_previous_runs!
250
+ if previously_ran?
251
+ current_run.each do |description, elapsed|
252
+ new_times = if previous_run["#{description}"]
253
+ Array(previous_run["#{description}"]) << elapsed
254
+
255
+ else
256
+ Array(elapsed)
257
+
258
+ end
259
+
260
+ previous_run.store("#{description}", new_times)
261
+ end
262
+
263
+ File.write(previous_runs_filename, previous_run.to_yaml)
264
+
265
+ else
266
+
267
+ File.write(previous_runs_filename, current_run.to_yaml)
268
+
269
+ end
270
+ end
271
+
272
+ # Creates a new report file in the 'report_filename'. This file contains
273
+ # a line for each test of the following example format: (this is a single
274
+ # line despite explicit wrapping)
275
+ #
276
+ # Avg: 0.0555555 Min: 0.0498765 Max: 0.0612345 Last: 0.0499421
277
+ # Description: The test name
278
+ #
279
+ # Note however the timings are to 9 decimal places, and padded to 12
280
+ # characters and each label is coloured, Avg (yellow), Min (green),
281
+ # Max (red), Last (multi), and Description (blue). It looks pretty!
282
+ #
283
+ # The 'Last' label is special in that it will be colour coded depending
284
+ # on whether the last run was faster (bright green) or slower (bright red)
285
+ # or inconclusive (purple). This helps to identify changes on a per run
286
+ # basis.
287
+ #
288
+ # @return [void]
289
+ def create_new_report!
290
+ File.write(report_filename, report_title + report_body)
291
+ end
292
+
293
+ # Writes a number of tests (configured via the 'show_count' option) to the
294
+ # screen after creating the report. See '#create_new_report!' for example
295
+ # output information.
296
+ #
297
+ # @return [void]
298
+ def write_to_screen!
299
+ puts report_title
300
+ puts report_body.lines.take(show_count)
301
+ end
302
+
303
+ # @return [String] A yellow 'Avg:' label.
304
+ def avg_label
305
+ ANSI::Code.yellow('Avg:')
306
+ end
307
+
308
+ # @return [String] A blue 'Description:' label.
309
+ def des_label
310
+ ANSI::Code.blue('Description:')
311
+ end
312
+
313
+ # @return [String] A red 'Max:' label.
314
+ def max_label
315
+ ANSI::Code.red('Max:')
316
+ end
317
+
318
+ # @return [String] A green 'Min:' label.
319
+ def min_label
320
+ ANSI::Code.green('Min:')
321
+ end
322
+
323
+ # @param rating [Symbol] One of :faster, :slower or :inconclusive.
324
+ # @return [String] A purple 'Last:' label.
325
+ def run_label(rating)
326
+ case rating
327
+ when :faster then ANSI::Code.green('Last:')
328
+ when :slower then ANSI::Code.red('Last:')
329
+ else
330
+ ANSI::Code.magenta('Last:')
331
+ end
332
+ end
333
+
334
+ # @param run [Float] The last run time.
335
+ # @param min [Float] The minimum run time.
336
+ # @param max [Float] The maximum run time.
337
+ # @return [Symbol] One of :faster, :slower or :inconclusive.
338
+ def rate(run, min, max)
339
+ if run == min
340
+ :faster
341
+ elsif run == max
342
+ :slower
343
+ else
344
+ :inconclusive
345
+ end
346
+ end
347
+
348
+ # @return [Boolean] Whether the given :order option is :asc.
349
+ def asc?
350
+ order == :asc
351
+ end
352
+
353
+ # @return [Boolean] Whether the given :order option is :desc (default).
354
+ def desc?
355
+ order == :desc
356
+ end
357
+
358
+ # @raise [Minitest::Reporters::MeanTimeReporter::InvalidOrder]
359
+ # When the given :order option is invalid.
360
+ # @return [Symbol] The :order option, or by default; :desc.
361
+ def order
362
+ orders = [:desc, :asc]
363
+
364
+ if orders.include?(options[:order])
365
+ options[:order]
366
+
367
+ else
368
+ fail Minitest::Reporters::MeanTimeReporter::InvalidOrder,
369
+ "`:order` option must be one of #{orders.inspect}."
370
+
371
+ end
372
+ end
373
+
374
+ # @raise [Minitest::Reporters::MeanTimeReporter::InvalidSortColumn]
375
+ # When the given :sort_column option is invalid.
376
+ # @return [Symbol] The :sort_column option, or by default; :avg.
377
+ def sort_column
378
+ sort_columns = [:avg, :min, :max, :last]
379
+
380
+ if sort_columns.include?(options[:sort_column])
381
+ options[:sort_column]
382
+
383
+ else
384
+ fail Minitest::Reporters::MeanTimeReporter::InvalidSortColumn,
385
+ "`:sort_column` option must be one of #{sort_columns.inspect}."
386
+
387
+ end
388
+ end
389
+
390
+ end
391
+ end
392
+ end