code_metric_fu 4.14.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 (296) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +28 -0
  3. data/.metrics +3 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +15 -0
  6. data/.rubocop_todo.yml +69 -0
  7. data/.simplecov +74 -0
  8. data/.travis.yml +22 -0
  9. data/.yardopts +4 -0
  10. data/AUTHORS +12 -0
  11. data/CONTRIBUTING.md +47 -0
  12. data/CONTRIBUTORS +76 -0
  13. data/DEV.md +76 -0
  14. data/Gemfile +74 -0
  15. data/Guardfile +30 -0
  16. data/HISTORY.md +705 -0
  17. data/MIT-LICENSE +22 -0
  18. data/README.md +299 -0
  19. data/Rakefile +27 -0
  20. data/TODO.md +118 -0
  21. data/appveyor.yml +31 -0
  22. data/bin/metric_fu +9 -0
  23. data/bin/mf-cane +10 -0
  24. data/bin/mf-churn +10 -0
  25. data/bin/mf-flay +10 -0
  26. data/bin/mf-reek +10 -0
  27. data/bin/mf-roodi +10 -0
  28. data/bin/mf-saikuro +10 -0
  29. data/certs/bf4.pem +22 -0
  30. data/checksum/.gitkeep +0 -0
  31. data/checksum/metric_fu-4.10.0.gem.sha512 +1 -0
  32. data/checksum/metric_fu-4.11.0.gem.sha512 +1 -0
  33. data/checksum/metric_fu-4.11.1.gem.sha512 +1 -0
  34. data/checksum/metric_fu-4.11.2.gem.sha512 +1 -0
  35. data/checksum/metric_fu-4.11.3.gem.sha512 +1 -0
  36. data/checksum/metric_fu-4.11.4.gem.sha512 +1 -0
  37. data/checksum/metric_fu-4.12.0.gem.sha512 +1 -0
  38. data/checksum/metric_fu-4.2.0.gem.sha512 +1 -0
  39. data/checksum/metric_fu-4.2.1.gem.sha512 +1 -0
  40. data/checksum/metric_fu-4.3.0.gem.sha512 +1 -0
  41. data/checksum/metric_fu-4.3.1.gem.sha512 +1 -0
  42. data/checksum/metric_fu-4.4.0.gem.sha512 +1 -0
  43. data/checksum/metric_fu-4.4.1.gem.sha512 +1 -0
  44. data/checksum/metric_fu-4.4.2.gem.sha512 +1 -0
  45. data/checksum/metric_fu-4.4.3.gem.sha512 +1 -0
  46. data/checksum/metric_fu-4.4.4.gem.sha512 +1 -0
  47. data/checksum/metric_fu-4.5.0.gem.sha512 +1 -0
  48. data/checksum/metric_fu-4.5.1.gem.sha512 +1 -0
  49. data/checksum/metric_fu-4.5.2.gem.sha512 +1 -0
  50. data/checksum/metric_fu-4.6.0.gem.sha512 +1 -0
  51. data/checksum/metric_fu-4.7.0.gem.sha512 +1 -0
  52. data/checksum/metric_fu-4.7.1.gem.sha512 +1 -0
  53. data/checksum/metric_fu-4.7.2.gem.sha512 +1 -0
  54. data/checksum/metric_fu-4.7.3.gem.sha512 +1 -0
  55. data/checksum/metric_fu-4.7.4.gem.sha512 +1 -0
  56. data/checksum/metric_fu-4.8.0.gem.sha512 +1 -0
  57. data/checksum/metric_fu-4.9.0.gem.sha512 +1 -0
  58. data/config/roodi_config.yml +22 -0
  59. data/config/rubocop.yml +269 -0
  60. data/gem_tasks/build.rake +197 -0
  61. data/gem_tasks/rubocop.rake +10 -0
  62. data/gem_tasks/usage_test.rake +19 -0
  63. data/gem_tasks/yard.rake +24 -0
  64. data/lib/metric_fu/calculate.rb +10 -0
  65. data/lib/metric_fu/cli/client.rb +26 -0
  66. data/lib/metric_fu/cli/helper.rb +80 -0
  67. data/lib/metric_fu/cli/parser.rb +138 -0
  68. data/lib/metric_fu/configuration.rb +150 -0
  69. data/lib/metric_fu/constantize.rb +57 -0
  70. data/lib/metric_fu/data_structures/line_numbers.rb +112 -0
  71. data/lib/metric_fu/data_structures/location.rb +110 -0
  72. data/lib/metric_fu/data_structures/sexp_node.rb +107 -0
  73. data/lib/metric_fu/environment.rb +129 -0
  74. data/lib/metric_fu/errors/analysis_error.rb +4 -0
  75. data/lib/metric_fu/formatter/html.rb +96 -0
  76. data/lib/metric_fu/formatter/syntax.rb +45 -0
  77. data/lib/metric_fu/formatter/yaml.rb +18 -0
  78. data/lib/metric_fu/formatter.rb +40 -0
  79. data/lib/metric_fu/gem_run.rb +70 -0
  80. data/lib/metric_fu/gem_version.rb +92 -0
  81. data/lib/metric_fu/generator.rb +135 -0
  82. data/lib/metric_fu/io.rb +132 -0
  83. data/lib/metric_fu/loader.rb +105 -0
  84. data/lib/metric_fu/logger.rb +62 -0
  85. data/lib/metric_fu/logging/mf_debugger.rb +23 -0
  86. data/lib/metric_fu/metric.rb +143 -0
  87. data/lib/metric_fu/metrics/cane/generator.rb +95 -0
  88. data/lib/metric_fu/metrics/cane/grapher.rb +37 -0
  89. data/lib/metric_fu/metrics/cane/metric.rb +34 -0
  90. data/lib/metric_fu/metrics/cane/report.html.erb +87 -0
  91. data/lib/metric_fu/metrics/cane/violations.rb +46 -0
  92. data/lib/metric_fu/metrics/churn/generator.rb +37 -0
  93. data/lib/metric_fu/metrics/churn/hotspot.rb +43 -0
  94. data/lib/metric_fu/metrics/churn/metric.rb +29 -0
  95. data/lib/metric_fu/metrics/churn/report.html.erb +58 -0
  96. data/lib/metric_fu/metrics/flay/generator.rb +51 -0
  97. data/lib/metric_fu/metrics/flay/grapher.rb +37 -0
  98. data/lib/metric_fu/metrics/flay/hotspot.rb +52 -0
  99. data/lib/metric_fu/metrics/flay/metric.rb +28 -0
  100. data/lib/metric_fu/metrics/flay/report.html.erb +29 -0
  101. data/lib/metric_fu/metrics/flog/generator.rb +113 -0
  102. data/lib/metric_fu/metrics/flog/grapher.rb +77 -0
  103. data/lib/metric_fu/metrics/flog/hotspot.rb +46 -0
  104. data/lib/metric_fu/metrics/flog/metric.rb +29 -0
  105. data/lib/metric_fu/metrics/flog/report.html.erb +50 -0
  106. data/lib/metric_fu/metrics/hotspots/analysis/analyzed_problems.rb +34 -0
  107. data/lib/metric_fu/metrics/hotspots/analysis/analyzer_tables.rb +114 -0
  108. data/lib/metric_fu/metrics/hotspots/analysis/grouping.rb +23 -0
  109. data/lib/metric_fu/metrics/hotspots/analysis/groupings.rb +12 -0
  110. data/lib/metric_fu/metrics/hotspots/analysis/problems.rb +20 -0
  111. data/lib/metric_fu/metrics/hotspots/analysis/ranked_problem_location.rb +70 -0
  112. data/lib/metric_fu/metrics/hotspots/analysis/ranking.rb +29 -0
  113. data/lib/metric_fu/metrics/hotspots/analysis/rankings.rb +91 -0
  114. data/lib/metric_fu/metrics/hotspots/analysis/record.rb +32 -0
  115. data/lib/metric_fu/metrics/hotspots/analysis/scoring_strategies.rb +24 -0
  116. data/lib/metric_fu/metrics/hotspots/analysis/table.rb +67 -0
  117. data/lib/metric_fu/metrics/hotspots/generator.rb +40 -0
  118. data/lib/metric_fu/metrics/hotspots/hotspot.rb +87 -0
  119. data/lib/metric_fu/metrics/hotspots/hotspot_analyzer.rb +61 -0
  120. data/lib/metric_fu/metrics/hotspots/metric.rb +20 -0
  121. data/lib/metric_fu/metrics/hotspots/report.html.erb +60 -0
  122. data/lib/metric_fu/metrics/rails_best_practices/generator.rb +47 -0
  123. data/lib/metric_fu/metrics/rails_best_practices/grapher.rb +38 -0
  124. data/lib/metric_fu/metrics/rails_best_practices/metric.rb +31 -0
  125. data/lib/metric_fu/metrics/rails_best_practices/report.html.erb +22 -0
  126. data/lib/metric_fu/metrics/rcov/external_client.rb +22 -0
  127. data/lib/metric_fu/metrics/rcov/generator.rb +75 -0
  128. data/lib/metric_fu/metrics/rcov/grapher.rb +37 -0
  129. data/lib/metric_fu/metrics/rcov/hotspot.rb +46 -0
  130. data/lib/metric_fu/metrics/rcov/metric.rb +61 -0
  131. data/lib/metric_fu/metrics/rcov/rcov_format_coverage.rb +149 -0
  132. data/lib/metric_fu/metrics/rcov/rcov_line.rb +48 -0
  133. data/lib/metric_fu/metrics/rcov/report.html.erb +40 -0
  134. data/lib/metric_fu/metrics/rcov/simplecov_formatter.rb +74 -0
  135. data/lib/metric_fu/metrics/reek/generator.rb +97 -0
  136. data/lib/metric_fu/metrics/reek/grapher.rb +55 -0
  137. data/lib/metric_fu/metrics/reek/hotspot.rb +95 -0
  138. data/lib/metric_fu/metrics/reek/metric.rb +26 -0
  139. data/lib/metric_fu/metrics/reek/report.html.erb +35 -0
  140. data/lib/metric_fu/metrics/roodi/generator.rb +41 -0
  141. data/lib/metric_fu/metrics/roodi/grapher.rb +37 -0
  142. data/lib/metric_fu/metrics/roodi/hotspot.rb +39 -0
  143. data/lib/metric_fu/metrics/roodi/metric.rb +24 -0
  144. data/lib/metric_fu/metrics/roodi/report.html.erb +22 -0
  145. data/lib/metric_fu/metrics/saikuro/generator.rb +145 -0
  146. data/lib/metric_fu/metrics/saikuro/hotspot.rb +51 -0
  147. data/lib/metric_fu/metrics/saikuro/metric.rb +31 -0
  148. data/lib/metric_fu/metrics/saikuro/parsing_element.rb +37 -0
  149. data/lib/metric_fu/metrics/saikuro/report.html.erb +71 -0
  150. data/lib/metric_fu/metrics/saikuro/scratch_file.rb +108 -0
  151. data/lib/metric_fu/metrics/stats/generator.rb +82 -0
  152. data/lib/metric_fu/metrics/stats/grapher.rb +40 -0
  153. data/lib/metric_fu/metrics/stats/hotspot.rb +35 -0
  154. data/lib/metric_fu/metrics/stats/metric.rb +28 -0
  155. data/lib/metric_fu/metrics/stats/report.html.erb +44 -0
  156. data/lib/metric_fu/reporter.rb +37 -0
  157. data/lib/metric_fu/reporting/graphs/graph.rb +69 -0
  158. data/lib/metric_fu/reporting/graphs/grapher.rb +66 -0
  159. data/lib/metric_fu/reporting/result.rb +59 -0
  160. data/lib/metric_fu/run.rb +82 -0
  161. data/lib/metric_fu/tasks/metric_fu.rake +54 -0
  162. data/lib/metric_fu/templates/_gem_info.html.erb +8 -0
  163. data/lib/metric_fu/templates/_graph.html.erb +2 -0
  164. data/lib/metric_fu/templates/_report_footer.html.erb +1 -0
  165. data/lib/metric_fu/templates/configuration.rb +25 -0
  166. data/lib/metric_fu/templates/css/bluff.css +15 -0
  167. data/lib/metric_fu/templates/css/buttons.css +82 -0
  168. data/lib/metric_fu/templates/css/default.css +43 -0
  169. data/lib/metric_fu/templates/css/integrity.css +337 -0
  170. data/lib/metric_fu/templates/css/rcov.css +32 -0
  171. data/lib/metric_fu/templates/css/reset.css +7 -0
  172. data/lib/metric_fu/templates/css/syntax.css +19 -0
  173. data/lib/metric_fu/templates/index.html.erb +13 -0
  174. data/lib/metric_fu/templates/javascripts/bluff-min.js +1 -0
  175. data/lib/metric_fu/templates/javascripts/bluff_graph.js +15 -0
  176. data/lib/metric_fu/templates/javascripts/excanvas.js +35 -0
  177. data/lib/metric_fu/templates/javascripts/highcharts.js +294 -0
  178. data/lib/metric_fu/templates/javascripts/highcharts_graph.js +38 -0
  179. data/lib/metric_fu/templates/javascripts/js-class.js +1 -0
  180. data/lib/metric_fu/templates/javascripts/standalone-framework.js +17 -0
  181. data/lib/metric_fu/templates/javascripts/utils.js +9 -0
  182. data/lib/metric_fu/templates/layout.html.erb +41 -0
  183. data/lib/metric_fu/templates/metrics_template.rb +86 -0
  184. data/lib/metric_fu/templates/report.html.erb +31 -0
  185. data/lib/metric_fu/templates/report.rb +41 -0
  186. data/lib/metric_fu/templates/template.rb +247 -0
  187. data/lib/metric_fu/utility.rb +79 -0
  188. data/lib/metric_fu/version.rb +9 -0
  189. data/lib/metric_fu.rb +143 -0
  190. data/metric_fu.gemspec +72 -0
  191. data/spec/capture_warnings.rb +55 -0
  192. data/spec/cli/helper_spec.rb +165 -0
  193. data/spec/dummy/.gitignore +1 -0
  194. data/spec/dummy/.gitkeep +0 -0
  195. data/spec/dummy/.metrics +4 -0
  196. data/spec/dummy/lib/.gitkeep +0 -0
  197. data/spec/dummy/lib/bad_encoding.rb +6 -0
  198. data/spec/dummy/spec/.gitkeep +0 -0
  199. data/spec/fixtures/20090630.yml +7922 -0
  200. data/spec/fixtures/coverage-153.rb +11 -0
  201. data/spec/fixtures/coverage.rb +13 -0
  202. data/spec/fixtures/exit0.sh +3 -0
  203. data/spec/fixtures/exit1.sh +3 -0
  204. data/spec/fixtures/hotspots/flog.yml +86 -0
  205. data/spec/fixtures/hotspots/generator.yml +47 -0
  206. data/spec/fixtures/hotspots/generator_analysis.yml +53 -0
  207. data/spec/fixtures/hotspots/reek.yml +14 -0
  208. data/spec/fixtures/hotspots/roodi.yml +13 -0
  209. data/spec/fixtures/hotspots/saikuro.yml +27 -0
  210. data/spec/fixtures/hotspots/several_metrics.yml +47 -0
  211. data/spec/fixtures/hotspots/stats.yml +4 -0
  212. data/spec/fixtures/hotspots/three_metrics_on_same_file.yml +36 -0
  213. data/spec/fixtures/line_numbers/foo.rb +33 -0
  214. data/spec/fixtures/line_numbers/module.rb +11 -0
  215. data/spec/fixtures/line_numbers/module_surrounds_class.rb +15 -0
  216. data/spec/fixtures/line_numbers/two_classes.rb +11 -0
  217. data/spec/fixtures/metric_missing.yml +1 -0
  218. data/spec/fixtures/rcov_output.txt +135 -0
  219. data/spec/fixtures/saikuro/app/controllers/sessions_controller.rb_cyclo.html +10 -0
  220. data/spec/fixtures/saikuro/app/controllers/users_controller.rb_cyclo.html +16 -0
  221. data/spec/fixtures/saikuro/index_cyclo.html +155 -0
  222. data/spec/fixtures/saikuro_sfiles/thing.rb_cyclo.html +11 -0
  223. data/spec/metric_fu/calculate_spec.rb +21 -0
  224. data/spec/metric_fu/configuration_spec.rb +90 -0
  225. data/spec/metric_fu/data_structures/line_numbers_spec.rb +63 -0
  226. data/spec/metric_fu/data_structures/location_spec.rb +110 -0
  227. data/spec/metric_fu/formatter/configuration_spec.rb +44 -0
  228. data/spec/metric_fu/formatter/html_spec.rb +138 -0
  229. data/spec/metric_fu/formatter/yaml_spec.rb +61 -0
  230. data/spec/metric_fu/formatter_spec.rb +49 -0
  231. data/spec/metric_fu/gem_version_spec.rb +12 -0
  232. data/spec/metric_fu/generator_spec.rb +130 -0
  233. data/spec/metric_fu/loader_spec.rb +10 -0
  234. data/spec/metric_fu/metric_spec.rb +46 -0
  235. data/spec/metric_fu/metrics/cane/configuration_spec.rb +22 -0
  236. data/spec/metric_fu/metrics/cane/generator_spec.rb +184 -0
  237. data/spec/metric_fu/metrics/churn/configuration_spec.rb +13 -0
  238. data/spec/metric_fu/metrics/churn/generator_spec.rb +64 -0
  239. data/spec/metric_fu/metrics/flay/configuration_spec.rb +13 -0
  240. data/spec/metric_fu/metrics/flay/generator_spec.rb +105 -0
  241. data/spec/metric_fu/metrics/flay/grapher_spec.rb +57 -0
  242. data/spec/metric_fu/metrics/flog/configuration_spec.rb +18 -0
  243. data/spec/metric_fu/metrics/flog/generator_spec.rb +77 -0
  244. data/spec/metric_fu/metrics/flog/grapher_spec.rb +107 -0
  245. data/spec/metric_fu/metrics/hotspots/analysis/analyzed_problems_spec.rb +104 -0
  246. data/spec/metric_fu/metrics/hotspots/analysis/analyzer_tables_spec.rb +71 -0
  247. data/spec/metric_fu/metrics/hotspots/analysis/ranking_spec.rb +30 -0
  248. data/spec/metric_fu/metrics/hotspots/analysis/rankings_spec.rb +97 -0
  249. data/spec/metric_fu/metrics/hotspots/analysis/table_spec.rb +6 -0
  250. data/spec/metric_fu/metrics/hotspots/generator_spec.rb +46 -0
  251. data/spec/metric_fu/metrics/hotspots/hotspot_analyzer_spec.rb +10 -0
  252. data/spec/metric_fu/metrics/hotspots/hotspot_spec.rb +16 -0
  253. data/spec/metric_fu/metrics/rails_best_practices/configuration_spec.rb +55 -0
  254. data/spec/metric_fu/metrics/rails_best_practices/generator_spec.rb +33 -0
  255. data/spec/metric_fu/metrics/rails_best_practices/grapher_spec.rb +62 -0
  256. data/spec/metric_fu/metrics/rcov/configuration_spec.rb +28 -0
  257. data/spec/metric_fu/metrics/rcov/generator_spec.rb +22 -0
  258. data/spec/metric_fu/metrics/rcov/grapher_spec.rb +57 -0
  259. data/spec/metric_fu/metrics/rcov/hotspot_spec.rb +20 -0
  260. data/spec/metric_fu/metrics/rcov/rcov_line_spec.rb +89 -0
  261. data/spec/metric_fu/metrics/rcov/simplecov_formatter_spec.rb +67 -0
  262. data/spec/metric_fu/metrics/reek/configuration_spec.rb +13 -0
  263. data/spec/metric_fu/metrics/reek/generator_spec.rb +169 -0
  264. data/spec/metric_fu/metrics/reek/grapher_spec.rb +66 -0
  265. data/spec/metric_fu/metrics/roodi/configuration_spec.rb +14 -0
  266. data/spec/metric_fu/metrics/roodi/generator_spec.rb +82 -0
  267. data/spec/metric_fu/metrics/roodi/grapher_spec.rb +57 -0
  268. data/spec/metric_fu/metrics/saikuro/configuration_spec.rb +25 -0
  269. data/spec/metric_fu/metrics/saikuro/generator_spec.rb +71 -0
  270. data/spec/metric_fu/metrics/stats/generator_spec.rb +96 -0
  271. data/spec/metric_fu/metrics/stats/grapher_spec.rb +69 -0
  272. data/spec/metric_fu/reporter_spec.rb +41 -0
  273. data/spec/metric_fu/reporting/graphs/graph_spec.rb +44 -0
  274. data/spec/metric_fu/reporting/graphs/grapher_spec.rb +24 -0
  275. data/spec/metric_fu/reporting/result_spec.rb +50 -0
  276. data/spec/metric_fu/run_spec.rb +197 -0
  277. data/spec/metric_fu/templates/configuration_spec.rb +51 -0
  278. data/spec/metric_fu/templates/metrics_template_spec.rb +11 -0
  279. data/spec/metric_fu/templates/report_spec.rb +15 -0
  280. data/spec/metric_fu/templates/template_spec.rb +233 -0
  281. data/spec/metric_fu/utility_spec.rb +12 -0
  282. data/spec/metric_fu_spec.rb +33 -0
  283. data/spec/quality_spec.rb +114 -0
  284. data/spec/shared/configured.rb +45 -0
  285. data/spec/shared/test_coverage.rb +95 -0
  286. data/spec/spec_helper.rb +54 -0
  287. data/spec/support/deferred_garbaged_collection.rb +33 -0
  288. data/spec/support/helper_methods.rb +32 -0
  289. data/spec/support/matcher_create_file.rb +37 -0
  290. data/spec/support/matcher_create_files.rb +43 -0
  291. data/spec/support/suite.rb +26 -0
  292. data/spec/support/test_fixtures.rb +37 -0
  293. data/spec/support/timeout.rb +7 -0
  294. data/spec/support/usage_test.rb +150 -0
  295. data/spec/usage_test_spec.rb +93 -0
  296. metadata +757 -0
@@ -0,0 +1,105 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "flay/generator" }
3
+
4
+ describe MetricFu::FlayGenerator do
5
+ describe "emit method" do
6
+ it "should look at the dirs" do
7
+ options = { dirs_to_flay: ["app", "lib"] }
8
+ allow(File).to receive(:directory?).and_return(true)
9
+ @flay = MetricFu::FlayGenerator.new(options)
10
+
11
+ expect(@flay).to receive(:run!).with(" app lib")
12
+ output = @flay.emit
13
+ end
14
+
15
+ it "should limit flay scores by the minimum_score" do
16
+ options = { dirs_to_flay: [], minimum_score: 99 }
17
+ allow(File).to receive(:directory?).and_return(true)
18
+ @flay = MetricFu::FlayGenerator.new(options)
19
+
20
+ expect(@flay).to receive(:run!).with("--mass 99 ")
21
+ output = @flay.emit
22
+ end
23
+ end
24
+
25
+ describe "analyze method" do
26
+ before :each do
27
+ lines = <<-HERE
28
+ Total score (lower is better) = 246
29
+
30
+
31
+ 1) IDENTICAL code found in :or (mass*2 = 68)
32
+ app/controllers/link_targets_controller.rb:57
33
+ app/controllers/primary_sites_controller.rb:138
34
+
35
+ 2) Similar code found in :if (mass = 64)
36
+ app/controllers/primary_sites_controller.rb:75
37
+ app/controllers/primary_sites_controller.rb:76
38
+ app/controllers/primary_sites_controller.rb:88
39
+ app/controllers/primary_sites_controller.rb:89
40
+ HERE
41
+ MetricFu::Configuration.run {}
42
+ allow(File).to receive(:directory?).and_return(true)
43
+ @flay = MetricFu::FlayGenerator.new("base_dir")
44
+ @flay.instance_variable_set(:@output, lines)
45
+ end
46
+
47
+ it "should analyze and return matches" do
48
+ expect(@flay.analyze).to eq([["Total score (lower is better) = 246"],
49
+ ["\n1) IDENTICAL code found in :or (mass*2 = 68)",
50
+ "app/controllers/link_targets_controller.rb:57",
51
+ "app/controllers/primary_sites_controller.rb:138"],
52
+ ["2) Similar code found in :if (mass = 64)",
53
+ "app/controllers/primary_sites_controller.rb:75",
54
+ "app/controllers/primary_sites_controller.rb:76",
55
+ "app/controllers/primary_sites_controller.rb:88",
56
+ "app/controllers/primary_sites_controller.rb:89"]])
57
+ end
58
+ end
59
+
60
+ describe "to_h method" do
61
+ before :each do
62
+ lines = [["Total score (lower is better) = 284"],
63
+ ["\n1) IDENTICAL code found in :or (mass*2 = 68)",
64
+ "app/controllers/link_targets_controller.rb:57",
65
+ "app/controllers/primary_sites_controller.rb:138"],
66
+ ["2) Similar code found in :if (mass = 64)",
67
+ "app/controllers/primary_sites_controller.rb:75",
68
+ "app/controllers/primary_sites_controller.rb:76",
69
+ "app/controllers/primary_sites_controller.rb:88",
70
+ "app/controllers/primary_sites_controller.rb:89"],
71
+ ["3) Similar code found in :defn (mass = 40)",
72
+ "app/controllers/link_targets_controller.rb:40",
73
+ "app/controllers/primary_sites_controller.rb:98"],
74
+ ["4) Similar code found in :defn (mass = 38)",
75
+ "app/controllers/link_targets_controller.rb:13",
76
+ "app/controllers/primary_sites_controller.rb:50"],
77
+ ["5) Similar code found in :defn (mass = 38)",
78
+ "app/models/primary_site.rb:104",
79
+ "app/models/primary_site.rb:109"],
80
+ ["6) Similar code found in :call (mass = 36)",
81
+ "app/controllers/bookmarklet_integration_controller.rb:6",
82
+ "app/controllers/bookmarklet_integration_controller.rb:17"]]
83
+
84
+ MetricFu::Configuration.run {}
85
+ allow(File).to receive(:directory?).and_return(true)
86
+ flay = MetricFu::FlayGenerator.new("base_dir")
87
+ flay.instance_variable_set(:@matches, lines)
88
+ @results = flay.to_h
89
+ end
90
+
91
+ it "should find the total_score" do
92
+ expect(@results[:flay][:total_score]).to eq("284")
93
+ end
94
+
95
+ it "should have 6 matches" do
96
+ expect(@results[:flay][:matches].size).to eq(6)
97
+ end
98
+
99
+ it "should capture info for match" do
100
+ expect(@results[:flay][:matches].first[:reason]).to match(/IDENTICAL/)
101
+ expect(@results[:flay][:matches].first[:matches].first[:name]).to match(/link_targets_controller/)
102
+ expect(@results[:flay][:matches].first[:matches].first[:line]).to eq("57")
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "flay/grapher" }
3
+
4
+ describe FlayGrapher do
5
+ before :each do
6
+ @flay_grapher = MetricFu::FlayGrapher.new
7
+ MetricFu.configuration
8
+ end
9
+
10
+ it "should respond to flay_score and labels" do
11
+ expect(@flay_grapher).to respond_to(:flay_score)
12
+ expect(@flay_grapher).to respond_to(:labels)
13
+ end
14
+
15
+ describe "responding to #initialize" do
16
+ it "should initialise flay_score and labels" do
17
+ expect(@flay_grapher.flay_score).to eq([])
18
+ expect(@flay_grapher.labels).to eq({})
19
+ end
20
+ end
21
+
22
+ describe "responding to #get_metrics" do
23
+ context "when metrics were not generated" do
24
+ before(:each) do
25
+ @metrics = FIXTURE.load_metric("metric_missing.yml")
26
+ @date = "1/2"
27
+ end
28
+
29
+ it "should not push to flay_score" do
30
+ expect(@flay_grapher.flay_score).not_to receive(:push)
31
+ @flay_grapher.get_metrics(@metrics, @date)
32
+ end
33
+
34
+ it "should not update labels with the date" do
35
+ expect(@flay_grapher.labels).not_to receive(:update)
36
+ @flay_grapher.get_metrics(@metrics, @date)
37
+ end
38
+ end
39
+
40
+ context "when metrics have been generated" do
41
+ before(:each) do
42
+ @metrics = FIXTURE.load_metric("20090630.yml")
43
+ @date = "1/2"
44
+ end
45
+
46
+ it "should push to flay_score" do
47
+ expect(@flay_grapher.flay_score).to receive(:push).with(476)
48
+ @flay_grapher.get_metrics(@metrics, @date)
49
+ end
50
+
51
+ it "should update labels with the date" do
52
+ expect(@flay_grapher.labels).to receive(:update).with(0 => "1/2")
53
+ @flay_grapher.get_metrics(@metrics, @date)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+ require "shared/configured"
3
+
4
+ describe MetricFu::Configuration, "for flog" do
5
+ it_behaves_like "configured" do
6
+ if MetricFu.configuration.mri?
7
+ it "should set @flog to {:dirs_to_flog => @code_dirs}" do
8
+ load_metric "flog"
9
+ expect(MetricFu::Metric.get_metric(:flog).run_options).to eq(
10
+ all: true,
11
+ continue: true,
12
+ dirs_to_flog: ["lib"],
13
+ quiet: true
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,77 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "flog/generator" }
3
+
4
+ describe MetricFu::FlogGenerator do
5
+ break if metric_not_activated?(:flog)
6
+
7
+ before :each do
8
+ allow(File).to receive(:directory?).and_return(true)
9
+ options = MetricFu::Metric.get_metric(:flog).run_options
10
+ @flog = MetricFu::FlogGenerator.new(options)
11
+ end
12
+
13
+ describe "emit method" do
14
+ it "should look for files and flog them" do
15
+ expect(FlogCLI).to receive(:parse_options).with(["--all", "--continue"]).and_return("options")
16
+ expect(FlogCLI).to receive(:new).with("options").and_return(flogger = double("flogger"))
17
+ files_to_flog = Dir[File.join('lib', '**/*.{rb,rake}')]
18
+ expect(flogger).to receive(:flog).with(*files_to_flog)
19
+ @flog.emit
20
+ end
21
+ end
22
+
23
+ describe "analyze method" do
24
+ it "should harvest the flog information and put it into method_containers" do
25
+ first_full_method_name = "ClassName#first_method_name"
26
+ second_full_method_name = "ClassName#second_method_name"
27
+
28
+ flogger = double("flogger", method_locations: { first_full_method_name => "/file/location.rb:11",
29
+ second_full_method_name => "/file/location.rb:22" },
30
+ totals: { first_full_method_name => 11.11,
31
+ second_full_method_name => 22.22 })
32
+ expect(flogger).to receive(:calculate)
33
+ expect(flogger).to receive(:each_by_score).and_yield(
34
+ first_full_method_name, 11.11, branch: 11.1, puts: 1.1
35
+ ).and_yield(
36
+ second_full_method_name, 22.22, branch: 22.2, puts: 2.2
37
+ )
38
+ @flog.instance_variable_set(:@flogger, flogger)
39
+ @flog.analyze
40
+ method_containers = @flog.instance_variable_get(:@method_containers)
41
+ expect(method_containers.size).to eq(1)
42
+
43
+ expected = { methods: { "ClassName#first_method_name" => { path: "/file/location.rb:11",
44
+ score: 11.11,
45
+ operators: { branch: 11.1,
46
+ puts: 1.1 } },
47
+ "ClassName#second_method_name" => { path: "/file/location.rb:22",
48
+ score: 22.22,
49
+ operators: { branch: 22.2,
50
+ puts: 2.2 } } },
51
+ path: "/file/location.rb",
52
+ average_score: ((11.11 + 22.22) / 2.0),
53
+ total_score: 33.33,
54
+ highest_score: 22.22,
55
+ name: "ClassName" }
56
+
57
+ expect(method_containers["ClassName"].to_h).to eq(expected)
58
+ end
59
+ end
60
+
61
+ describe "to_h method" do
62
+ it "should make-a nice hash" do
63
+ flogger = double("flogger", total_score: 111.1, average: 7.3)
64
+ @flog.instance_variable_set(:@flogger, flogger)
65
+ method_containers = { ignore_me_1: double("container_1", highest_score: 11.1, to_h: "container_1"),
66
+ ignore_me_2: double("container_2", highest_score: 33.3, to_h: "container_2"),
67
+ ignore_me_3: double("container_3", highest_score: 22.2, to_h: "container_3") }
68
+ @flog.instance_variable_set(:@method_containers, method_containers)
69
+
70
+ expected = { flog: { total: 111.1,
71
+ average: 7.3,
72
+ method_containers: ["container_2", "container_3", "container_1"] } }
73
+
74
+ expect(@flog.to_h).to eq(expected)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,107 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "flog/grapher" }
3
+
4
+ describe MetricFu::FlogGrapher do
5
+ before :each do
6
+ MetricFu.configuration
7
+ @flog_grapher = MetricFu::FlogGrapher.new
8
+ end
9
+
10
+ it "should respond to flog_total, flog_average and labels" do
11
+ expect(@flog_grapher).to respond_to(:flog_average)
12
+ expect(@flog_grapher).to respond_to(:labels)
13
+ expect(@flog_grapher).to respond_to(:top_five_percent_average)
14
+ end
15
+
16
+ describe "responding to #initialize" do
17
+ it "should initialize top_five_percent_average, flog_average and labels" do
18
+ expect(@flog_grapher.flog_average).to eq([])
19
+ expect(@flog_grapher.labels).to eq({})
20
+ expect(@flog_grapher.top_five_percent_average).to eq([])
21
+ end
22
+ end
23
+
24
+ describe "responding to #get_metrics" do
25
+ before(:each) do
26
+ methods = {}
27
+ 100.times do |i|
28
+ methods["method_name_#{i}"] = { score: i.to_f }
29
+ end
30
+
31
+ @metrics = { flog: { total: 111.1,
32
+ average: 7.7,
33
+ method_containers: [{ methods: methods }] } }
34
+ @date = "1/2"
35
+ end
36
+
37
+ it "should push to top_five_percent_average" do
38
+ average = (99.0 + 98.0 + 97.0 + 96.0 + 95.0) / 5.0
39
+ expect(@flog_grapher.top_five_percent_average).to receive(:push).with(average)
40
+ @flog_grapher.get_metrics(@metrics, @date)
41
+ end
42
+
43
+ it "should push 9.9 to flog_average" do
44
+ expect(@flog_grapher.flog_average).to receive(:push).with(7.7)
45
+ @flog_grapher.get_metrics(@metrics, @date)
46
+ end
47
+
48
+ context "when metrics were not generated" do
49
+ before(:each) do
50
+ @metrics = FIXTURE.load_metric("metric_missing.yml")
51
+ @date = "1/2"
52
+ end
53
+
54
+ it "should not push to top_five_percent_average" do
55
+ expect(@flog_grapher.top_five_percent_average).not_to receive(:push)
56
+ @flog_grapher.get_metrics(@metrics, @date)
57
+ end
58
+
59
+ it "should not push to flog_average" do
60
+ expect(@flog_grapher.flog_average).not_to receive(:push)
61
+ @flog_grapher.get_metrics(@metrics, @date)
62
+ end
63
+
64
+ it "should not update labels with the date" do
65
+ expect(@flog_grapher.labels).not_to receive(:update)
66
+ @flog_grapher.get_metrics(@metrics, @date)
67
+ end
68
+ end
69
+
70
+ context "when metrics have been generated" do
71
+ before(:each) do
72
+ @metrics = FIXTURE.load_metric("20090630.yml")
73
+ @date = "1/2"
74
+ end
75
+
76
+ it "should push to top_five_percent_average" do
77
+ average = (73.6 + 68.5 + 66.1 + 46.6 + 44.8 + 44.1 + 41.2 + 36.0) / 8.0
78
+ expect(@flog_grapher.top_five_percent_average).to receive(:push).with(average)
79
+ @flog_grapher.get_metrics(@metrics, @date)
80
+ end
81
+
82
+ it "should push to flog_average" do
83
+ expect(@flog_grapher.flog_average).to receive(:push).with(9.9)
84
+ @flog_grapher.get_metrics(@metrics, @date)
85
+ end
86
+
87
+ it "should update labels with the date" do
88
+ expect(@flog_grapher.labels).to receive(:update).with(0 => "1/2")
89
+ @flog_grapher.get_metrics(@metrics, @date)
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "responding to #get_metrics with legacy data" do
95
+ before(:each) do
96
+ @metrics = FIXTURE.load_metric("20090630.yml")
97
+
98
+ @date = "1/2"
99
+ end
100
+
101
+ it "should push to top_five_percent_average" do
102
+ average = (73.6 + 68.5 + 66.1 + 46.6 + 44.8 + 44.1 + 41.2 + 36.0) / 8.0
103
+ expect(@flog_grapher.top_five_percent_average).to receive(:push).with(average)
104
+ @flog_grapher.get_metrics(@metrics, @date)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,104 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "hotspots/analysis/analyzed_problems" }
3
+
4
+ describe MetricFu::HotspotAnalyzedProblems do
5
+ before do
6
+ enable_hotspots
7
+ end
8
+
9
+ def analyzed_problems(result_hash)
10
+ @analyzed_problems ||= {}
11
+ @analyzed_problems.fetch(result_hash) do
12
+ common_columns = %w{metric}
13
+ granularities = %w{file_path class_name method_name}
14
+ tool_analyzers = MetricFu::Hotspot.analyzers
15
+ analyzer_columns = common_columns + granularities + tool_analyzers.map(&:columns).flatten
16
+
17
+ analyzer_tables = MetricFu::AnalyzerTables.new(analyzer_columns)
18
+ tool_analyzers.each do |analyzer|
19
+ analyzer.generate_records(result_hash[analyzer.name], analyzer_tables.table)
20
+ end
21
+ analyzer_tables.generate_records
22
+ rankings = MetricFu::HotspotRankings.new(analyzer_tables.tool_tables)
23
+ rankings.calculate_scores(tool_analyzers, granularities)
24
+ analyzed_problems = MetricFu::HotspotAnalyzedProblems.new(rankings, analyzer_tables)
25
+ @analyzed_problems[result_hash] = analyzed_problems
26
+ analyzed_problems
27
+ end
28
+ end
29
+
30
+ context "with several types of data" do
31
+ before do
32
+ @result_hash = HOTSPOT_DATA["several_metrics.yml"]
33
+ @analyzed_problems = analyzed_problems(@result_hash)
34
+ @worst_items = @analyzed_problems.worst_items
35
+ end
36
+
37
+ it "gives all issues for a class" do
38
+ expected = {
39
+ reek: "found 2 code smells",
40
+ flog: "complexity is 37.9"
41
+ }
42
+ # TODO Unsure if we want to make problems_with and location public or private at this point
43
+ expect(@worst_items[:classes].first.problems).to eq(expected)
44
+ end
45
+
46
+ it "gives all issues for a method" do
47
+ expected = {
48
+ reek: "found 1 code smells",
49
+ flog: "complexity is 37.9" }
50
+ expect(@worst_items[:methods].first.problems).to eq(expected)
51
+ end
52
+
53
+ it "gives all issues for a file" do
54
+ expected = {
55
+ reek: "found 2 code smells",
56
+ flog: "complexity is 37.9",
57
+ churn: "detected high level of churn (changed 54 times)" }
58
+ expect(@worst_items[:files].first.problems).to eq(expected)
59
+ end
60
+
61
+ it "provide location for a method" do
62
+ expected = MetricFu::Location.new("lib/client/client.rb",
63
+ "Client",
64
+ "Client#client_requested_sync")
65
+ expect(@worst_items[:methods].first.location).to eq(expected)
66
+ end
67
+
68
+ it "provides location for a class" do
69
+ expected = MetricFu::Location.new("lib/client/client.rb",
70
+ "Client",
71
+ nil)
72
+ expect(@worst_items[:classes].first.location).to eq(expected)
73
+ end
74
+
75
+ it "provides location for a file" do
76
+ expected = MetricFu::Location.new("lib/client/client.rb",
77
+ nil,
78
+ nil)
79
+ expect(@worst_items[:files].first.location).to eq(expected)
80
+ end
81
+ end
82
+
83
+ context "with Saikuro data" do
84
+ before do
85
+ @result_hash = HOTSPOT_DATA["saikuro.yml"]
86
+ @analyzed_problems = analyzed_problems(@result_hash)
87
+ @worst_items = @analyzed_problems.worst_items
88
+ end
89
+
90
+ it "gives complexity for method" do
91
+ expected = {
92
+ saikuro: "complexity is 1.0"
93
+ }
94
+ expect(@worst_items[:methods].last.problems).to eq(expected)
95
+ end
96
+
97
+ it "gives average complexity for class" do
98
+ expected = {
99
+ saikuro: "average complexity is 5.0"
100
+ }
101
+ expect(@worst_items[:classes].last.problems).to eq(expected)
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,71 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "hotspots/analysis/analyzer_tables" }
3
+
4
+ describe MetricFu::AnalyzerTables do
5
+ before do
6
+ enable_hotspots
7
+ end
8
+
9
+ def analyzer_table(result_hash)
10
+ @analyzer_tables ||= {}
11
+ @analyzer_tables.fetch(result_hash) do
12
+ common_columns = %w{metric}
13
+ granularities = %w{file_path class_name method_name}
14
+ tool_analyzers = MetricFu::Hotspot.analyzers
15
+ analyzer_columns = common_columns + granularities + tool_analyzers.map(&:columns).flatten
16
+
17
+ analyzer_tables = MetricFu::AnalyzerTables.new(analyzer_columns)
18
+ tool_analyzers.each do |analyzer|
19
+ analyzer.generate_records(result_hash[analyzer.name], analyzer_tables.table)
20
+ end
21
+ analyzer_tables.generate_records
22
+ rankings = MetricFu::HotspotRankings.new(analyzer_tables.tool_tables)
23
+ rankings.calculate_scores(tool_analyzers, granularities)
24
+ @analyzer_tables[result_hash] = analyzer_tables
25
+ analyzer_tables
26
+ end
27
+ end
28
+
29
+ context "with Stats data" do
30
+ before do
31
+ @result_hash = HOTSPOT_DATA["stats.yml"]
32
+ @table = analyzer_table(@result_hash).table
33
+ end
34
+
35
+ it "should have codeLOC" do
36
+ row = @table.find { |row| row["stat_name"] == :codeLOC }
37
+ expect(row["stat_value"]).to eq(4222)
38
+ end
39
+
40
+ it "should have testLOC" do
41
+ row = @table.find { |row| row["stat_name"] == :testLOC }
42
+ expect(row["stat_value"]).to eq(2111)
43
+ end
44
+
45
+ it "should have code_to_test_ratio" do
46
+ row = @table.find { |row| row["stat_name"] == :code_to_test_ratio }
47
+ expect(row["stat_value"]).to eq(2)
48
+ end
49
+ end
50
+
51
+ context "with three different path representations of file (from Saikuro, Flog, and Reek)" do
52
+ before do
53
+ @result_hash = HOTSPOT_DATA["three_metrics_on_same_file.yml"]
54
+ @table = analyzer_table(@result_hash).table
55
+ end
56
+
57
+ specify "all records should have full file_path" do
58
+ @table.each do |row|
59
+ expect(row["file_path"]).to eq("lib/client/client.rb")
60
+ end
61
+ end
62
+
63
+ specify "all records should have class name" do
64
+ expect(@table.select { |rows| rows.fetch(:class_name, :no_key) == nil }.size).to eq(0)
65
+ end
66
+
67
+ specify "one record should not have method name" do
68
+ expect(@table.select { |rows| rows.fetch(:method_name, :no_key) == nil }.size).to eq(0)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,30 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "hotspots/analysis/ranking" }
3
+
4
+ describe MetricFu::Ranking do
5
+ context "with many items" do
6
+ specify "#top" do
7
+ ranking = Ranking.new
8
+ ranking[:a] = 10
9
+ ranking[:b] = 50
10
+ ranking[:c] = 1
11
+ expect(ranking.top).to eq([:b, :a, :c])
12
+ end
13
+
14
+ specify "lowest item is at 0 percentile" do
15
+ ranking = Ranking.new
16
+ ranking[:a] = 10
17
+ ranking[:b] = 50
18
+ expect(ranking.percentile(:a)).to eq(0)
19
+ end
20
+
21
+ specify "highest item is at high percentile" do
22
+ ranking = Ranking.new
23
+ ranking[:a] = 10
24
+ ranking[:b] = 50
25
+ ranking[:c] = 0
26
+ ranking[:d] = 5
27
+ expect(ranking.percentile(:b)).to eq(0.75)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,97 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "hotspots/analysis/rankings" }
3
+
4
+ describe MetricFu::HotspotRankings do
5
+ before do
6
+ enable_hotspots
7
+ end
8
+
9
+ # TODO: This helper method is a huge smell. Make unnecessary
10
+ def rankings(result_hash)
11
+ @rankings ||= {}
12
+ @rankings.fetch(result_hash) do
13
+ common_columns = %w{metric}
14
+ granularities = %w{file_path class_name method_name}
15
+ tool_analyzers = MetricFu::Hotspot.analyzers
16
+ analyzer_columns = common_columns + granularities + tool_analyzers.map(&:columns).flatten
17
+
18
+ analyzer_tables = MetricFu::AnalyzerTables.new(analyzer_columns)
19
+ tool_analyzers.each do |analyzer|
20
+ analyzer.generate_records(result_hash[analyzer.name], analyzer_tables.table)
21
+ end
22
+ analyzer_tables.generate_records
23
+ rankings = MetricFu::HotspotRankings.new(analyzer_tables.tool_tables)
24
+ rankings.calculate_scores(tool_analyzers, granularities)
25
+ @rankings[result_hash] = rankings
26
+ rankings
27
+ end
28
+ end
29
+ context "with several types of data" do
30
+ it "gives all files, in order, from worst to best" do
31
+ expected = [
32
+ "lib/client/client.rb",
33
+ "lib/client/foo.rb"]
34
+ expect(rankings(result_hash).worst_files).to eq(expected)
35
+ end
36
+ def result_hash
37
+ @result_hash ||= HOTSPOT_DATA["several_metrics.yml"]
38
+ end
39
+ end
40
+ context "with Reek data" do
41
+ before do
42
+ @result_hash = HOTSPOT_DATA["reek.yml"]
43
+ end
44
+
45
+ it "gives worst method" do
46
+ expect(rankings(@result_hash).worst_methods[0]).to eq("Client#client_requested_sync")
47
+ end
48
+
49
+ it "gives worst class" do
50
+ expect(rankings(@result_hash).worst_classes[0]).to eq("Client")
51
+ end
52
+
53
+ it "gives worst file" do
54
+ expect(rankings(@result_hash).worst_files[0]).to eq("lib/client/client.rb")
55
+ end
56
+ end
57
+ context "with Saikuro data" do
58
+ before do
59
+ @result_hash = HOTSPOT_DATA["saikuro.yml"]
60
+ end
61
+
62
+ it "gives worst method" do
63
+ expect(rankings(@result_hash).worst_methods[0]).to eq("Supr#self.handle_full_or_hash_option")
64
+ end
65
+
66
+ it "gives worst class" do
67
+ expect(rankings(@result_hash).worst_classes[0]).to eq("Bitly")
68
+ end
69
+ end
70
+ context "with Flog data" do
71
+ before do
72
+ @result_hash = HOTSPOT_DATA["flog.yml"]
73
+ end
74
+
75
+ it "gives worst method" do
76
+ expect(rankings(@result_hash).worst_methods[0]).to eq("main#none")
77
+ end
78
+
79
+ it "gives worst class" do
80
+ expect(rankings(@result_hash).worst_classes[0]).to eq("main")
81
+ end
82
+
83
+ it "gives worst file" do
84
+ expect(rankings(@result_hash).worst_files[0]).to eq("lib/generators/rcov.rb:57")
85
+ end
86
+ end
87
+
88
+ context "with Roodi data" do
89
+ before do
90
+ @result_hash = HOTSPOT_DATA["roodi.yml"]
91
+ end
92
+
93
+ it "gives worst file" do
94
+ expect(rankings(@result_hash).worst_files[0]).to eq("lib/client/client.rb")
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,6 @@
1
+ require "spec_helper"
2
+ MetricFu.metrics_require { "hotspots/analysis/table" }
3
+
4
+ describe MetricFu::Table do
5
+ it "needs tests"
6
+ end