metric_fu 4.4.0 → 4.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/HISTORY.md +12 -0
  3. data/Rakefile +0 -1
  4. data/bin/mf-roodi +2 -2
  5. data/checksum/metric_fu-4.4.0.gem.sha512 +1 -1
  6. data/gem_tasks/build.rake +24 -22
  7. data/lib/metric_fu/configuration.rb +0 -10
  8. data/lib/metric_fu/data_structures/line_numbers.rb +2 -0
  9. data/lib/metric_fu/initial_requires.rb +0 -1
  10. data/lib/metric_fu/metric.rb +1 -1
  11. data/lib/metric_fu/metrics/churn/churn_hotspot.rb +10 -11
  12. data/lib/metric_fu/metrics/flay/flay_hotspot.rb +7 -20
  13. data/lib/metric_fu/metrics/flog/flog_hotspot.rb +7 -14
  14. data/lib/metric_fu/metrics/generator.rb +0 -14
  15. data/lib/metric_fu/metrics/graph.rb +50 -15
  16. data/lib/metric_fu/metrics/hotspots/analysis/analyzed_problems.rb +21 -27
  17. data/lib/metric_fu/metrics/hotspots/analysis/analyzer_tables.rb +0 -6
  18. data/lib/metric_fu/metrics/hotspots/analysis/grouping.rb +2 -17
  19. data/lib/metric_fu/metrics/hotspots/analysis/groupings.rb +1 -9
  20. data/lib/metric_fu/metrics/hotspots/analysis/problems.rb +3 -7
  21. data/lib/metric_fu/metrics/hotspots/analysis/ranking.rb +3 -7
  22. data/lib/metric_fu/metrics/hotspots/analysis/rankings.rb +6 -6
  23. data/lib/metric_fu/metrics/hotspots/analysis/record.rb +3 -12
  24. data/lib/metric_fu/metrics/hotspots/analysis/scoring_strategies.rb +9 -14
  25. data/lib/metric_fu/metrics/hotspots/analysis/table.rb +3 -43
  26. data/lib/metric_fu/metrics/hotspots/hotspot.rb +59 -7
  27. data/lib/metric_fu/metrics/hotspots/hotspot_analyzer.rb +1 -36
  28. data/lib/metric_fu/metrics/hotspots/hotspots.rb +0 -4
  29. data/lib/metric_fu/metrics/rails_best_practices/init.rb +0 -1
  30. data/lib/metric_fu/metrics/rcov/rcov_hotspot.rb +6 -13
  31. data/lib/metric_fu/metrics/reek/reek_hotspot.rb +6 -87
  32. data/lib/metric_fu/metrics/roodi/roodi_hotspot.rb +7 -18
  33. data/lib/metric_fu/metrics/saikuro/saikuro.rb +0 -5
  34. data/lib/metric_fu/metrics/saikuro/saikuro_hotspot.rb +7 -14
  35. data/lib/metric_fu/metrics/stats/stats_hotspot.rb +7 -7
  36. data/lib/metric_fu/reporting/templates/awesome/awesome_template.rb +2 -1
  37. data/lib/metric_fu/utility.rb +20 -0
  38. data/lib/metric_fu/version.rb +1 -1
  39. data/metric_fu.gemspec +6 -6
  40. data/spec/metric_fu/configuration_spec.rb +2 -21
  41. data/spec/metric_fu/metrics/flog/flog_grapher_spec.rb +2 -2
  42. data/spec/metric_fu/metrics/generator_spec.rb +0 -14
  43. data/spec/metric_fu/metrics/graph_spec.rb +7 -6
  44. data/spec/metric_fu/metrics/hotspots/analysis/analyzed_problems_spec.rb +113 -0
  45. data/spec/metric_fu/metrics/hotspots/analysis/analyzer_tables_spec.rb +71 -0
  46. data/spec/metric_fu/metrics/hotspots/analysis/ranking_spec.rb +3 -12
  47. data/spec/metric_fu/metrics/hotspots/analysis/rankings_spec.rb +100 -0
  48. data/spec/metric_fu/metrics/hotspots/analysis/table_spec.rb +1 -30
  49. data/spec/metric_fu/metrics/hotspots/hotspot_analyzer_spec.rb +3 -442
  50. data/spec/metric_fu/metrics/rcov/rcov_spec.rb +2 -0
  51. data/spec/metric_fu/metrics/saikuro/saikuro_spec.rb +0 -11
  52. data/spec/resources/yml/hotspots/flog.yml +86 -0
  53. data/spec/resources/yml/hotspots/reek.yml +14 -0
  54. data/spec/resources/yml/hotspots/roodi.yml +13 -0
  55. data/spec/resources/yml/hotspots/saikuro.yml +27 -0
  56. data/spec/resources/yml/hotspots/several_metrics.yml +47 -0
  57. data/spec/resources/yml/hotspots/stats.yml +4 -0
  58. data/spec/resources/yml/hotspots/three_metrics_on_same_file.yml +36 -0
  59. data/spec/support/helper_methods.rb +13 -0
  60. metadata +62 -21
  61. data/lib/metric_fu/data_structures/careful_array.rb +0 -11
  62. data/lib/metric_fu/metrics/hotspots/analysis/code_issue.rb +0 -109
  63. data/lib/metric_fu/parser_ext.rb +0 -15
  64. data/lib/metric_fu/sexp_ext.rb +0 -11
@@ -23,7 +23,6 @@ module MetricFu
23
23
 
24
24
  def activate
25
25
  activate_library('rails_best_practices')
26
- activate_library('metric_fu/sexp_ext')
27
26
  super
28
27
  end
29
28
 
@@ -1,5 +1,4 @@
1
- class RcovHotspot < MetricFu::Hotspot
2
- include MetricFu::HotspotScoringStrategies
1
+ class MetricFu::RcovHotspot < MetricFu::Hotspot
3
2
 
4
3
  COLUMNS = %w{percentage_uncovered}
5
4
 
@@ -12,15 +11,15 @@ class RcovHotspot < MetricFu::Hotspot
12
11
  end
13
12
 
14
13
  def map(row)
15
- row.percentage_uncovered
14
+ :percentage_uncovered
16
15
  end
17
16
 
18
- def reduce(scores)
19
- MetricFu::HotspotScoringStrategies.average(scores)
17
+ def reduce_strategy
18
+ :average
20
19
  end
21
20
 
22
- def score(metric_ranking, item)
23
- MetricFu::HotspotScoringStrategies.identity(metric_ranking, item)
21
+ def score_strategy
22
+ :identity
24
23
  end
25
24
 
26
25
  def generate_records(data, table)
@@ -46,10 +45,4 @@ class RcovHotspot < MetricFu::Hotspot
46
45
  "#{"average " if occurences > 1}uncovered code is %.1f%" % average_code_uncoverage
47
46
  end
48
47
 
49
- # TODO determine if no-op in pre-factored
50
- # code was intentional
51
- def present_group_details(group)
52
-
53
- end
54
-
55
48
  end
@@ -1,83 +1,12 @@
1
1
  # coding: utf-8
2
2
 
3
3
  class ReekHotspot < MetricFu::Hotspot
4
- include MetricFu::HotspotScoringStrategies
5
-
6
- REEK_ISSUE_INFO = {
7
- 'Uncommunicative Name' =>
8
- {'link' => 'http://wiki.github.com/kevinrutherford/reek/uncommunicative-name',
9
- 'info' => 'An Uncommunicative Name is a name that doesn’t communicate its intent well enough.'},
10
- 'Class Variable' =>
11
- {'link' => 'http://wiki.github.com/kevinrutherford/reek/class-variable',
12
- 'info' => 'Class variables form part of the global runtime state, and as such make it ' +
13
- 'easy for one part of the system to accidentally or inadvertently depend on ' +
14
- 'another part of the system.'},
15
- 'Duplication' =>
16
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/duplication',
17
- 'info' => 'Duplication occurs when two fragments of code look nearly identical, or when ' +
18
- 'two fragments of code have nearly identical effects at some conceptual level.'},
19
- 'Low Cohesion' =>
20
- {'link' => 'http://en.wikipedia.org/wiki/Cohesion_(computer_science)',
21
- 'info' => 'Low cohesion is associated with undesirable traits such as being difficult to ' +
22
- 'maintain, difficult to test, difficult to reuse, and even difficult to understand.'},
23
- 'Nested Iterators' =>
24
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/nested-iterators',
25
- 'info' => 'Nested Iterator occurs when a block contains another block.'},
26
- 'Control Couple' =>
27
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/control-couple',
28
- 'info' => 'Control coupling occurs when a method or block checks the value of a parameter in ' +
29
- 'order to decide which execution path to take. The offending parameter is often called a “Control Couple”.'},
30
- 'Irresponsible Module' =>
31
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/irresponsible-module',
32
- 'info' => 'Classes and modules are the units of reuse and release. It is therefore considered ' +
33
- 'good practice to annotate every class and module with a brief comment outlining its responsibilities.'},
34
- 'Long Parameter List' =>
35
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/long-parameter-list',
36
- 'info' => 'A Long Parameter List occurs when a method has more than one or two parameters, ' +
37
- 'or when a method yields more than one or two objects to an associated block.'},
38
- 'Data Clump' =>
39
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/data-clump',
40
- 'info' => 'In general, a Data Clump occurs when the same two or three items frequently appear ' +
41
- 'together in classes and parameter lists, or when a group of instance variable names ' +
42
- 'start or end with similar substrings.'},
43
- 'Simulated Polymorphism' =>
44
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/simulated-polymorphism',
45
- 'info' => 'Simulated Polymorphism occurs when, code uses a case statement (especially on a ' +
46
- 'type field) or code uses instance_of?, kind_of?, is_a?, or === to decide what code to execute'},
47
- 'Large Class' =>
48
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/large-class',
49
- 'info' => 'A Large Class is a class or module that has a large number of instance variables, ' +
50
- 'methods or lines of code in any one piece of its specification.'},
51
- 'Long Method' =>
52
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/long-method',
53
- 'info' => 'Long methods can be hard to read and understand. They often are harder to test and ' +
54
- 'maintain as well, which can lead to buggier code.'},
55
- 'Feature Envy' =>
56
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/feature-envy',
57
- 'info' => 'Feature Envy occurs when a code fragment references another object more often than ' +
58
- 'it references itself, or when several clients do the same series of manipulations ' +
59
- 'on a particular type of object.'},
60
- 'Utility Function' =>
61
- {'link' =>'http://wiki.github.com/kevinrutherford/reek/utility-function',
62
- 'info' => 'A Utility Function is any instance method that has no dependency on the state of the ' +
63
- 'instance. It reduces the code’s ability to communicate intent. Code that “belongs” on ' +
64
- 'one class but which is located in another can be hard to find.'},
65
- 'Attribute' =>
66
- {'link' => 'http://wiki.github.com/kevinrutherford/reek/attribute',
67
- 'info' => 'A class that publishes a getter or setter for an instance variable invites client ' +
68
- 'classes to become too intimate with its inner workings, and in particular with its ' +
69
- 'representation of state.'}
70
- }
71
4
 
72
5
  # Note that in practice, the prefix reek__ is appended to each one
73
6
  # This was a partially implemented idea to avoid column name collisions
74
7
  # but it is only done in the ReekHotspot
75
8
  COLUMNS = %w{type_name message value value_description comparable_message}
76
9
 
77
- def self.issue_link(issue)
78
- REEK_ISSUE_INFO[issue]
79
- end
80
-
81
10
  def columns
82
11
  COLUMNS.map{|column| "#{name}__#{column}"}
83
12
  end
@@ -86,16 +15,16 @@ class ReekHotspot < MetricFu::Hotspot
86
15
  :reek
87
16
  end
88
17
 
89
- def map(row)
90
- MetricFu::HotspotScoringStrategies.present(row)
18
+ def map_strategy
19
+ :present
91
20
  end
92
21
 
93
- def reduce(scores)
94
- MetricFu::HotspotScoringStrategies.sum(scores)
22
+ def reduce_strategy
23
+ :sum
95
24
  end
96
25
 
97
- def score(metric_ranking, item)
98
- MetricFu::HotspotScoringStrategies.percentile(metric_ranking, item)
26
+ def score_strategy
27
+ :percentile
99
28
  end
100
29
 
101
30
  def generate_records(data, table)
@@ -131,16 +60,6 @@ class ReekHotspot < MetricFu::Hotspot
131
60
  occurences = group.size
132
61
  "found #{occurences} code smells"
133
62
  end
134
- def present_group_details(group)
135
- occurences = group.size
136
- message = "found #{occurences} code smells<br/>"
137
- group.each do |item|
138
- type = item.data["reek__type_name"]
139
- reek_message = item.data["reek__message"]
140
- message << "* #{type}: #{reek_message}<br/>"
141
- end
142
- message
143
- end
144
63
 
145
64
  private
146
65
 
@@ -1,5 +1,4 @@
1
- class RoodiHotspot < MetricFu::Hotspot
2
- include MetricFu::HotspotScoringStrategies
1
+ class MetricFu::RoodiHotspot < MetricFu::Hotspot
3
2
 
4
3
  COLUMNS = %w{problems}
5
4
 
@@ -11,16 +10,16 @@ class RoodiHotspot < MetricFu::Hotspot
11
10
  :roodi
12
11
  end
13
12
 
14
- def map(row)
15
- MetricFu::HotspotScoringStrategies.present(row)
13
+ def map_strategy
14
+ :present
16
15
  end
17
16
 
18
- def reduce(scores)
19
- MetricFu::HotspotScoringStrategies.sum(scores)
17
+ def reduce_strategy
18
+ :sum
20
19
  end
21
20
 
22
- def score(metric_ranking, item)
23
- MetricFu::HotspotScoringStrategies.percentile(metric_ranking, item)
21
+ def score_strategy
22
+ :percentile
24
23
  end
25
24
 
26
25
  def generate_records(data, table)
@@ -39,14 +38,4 @@ class RoodiHotspot < MetricFu::Hotspot
39
38
  "found #{occurences} design problems"
40
39
  end
41
40
 
42
- def present_group_details(group)
43
- occurences = group.size
44
- message = "found #{occurences} design problems<br/>"
45
- group.each do |item|
46
- problem = item.data["problems"]
47
- message << "* #{problem}<br/>"
48
- end
49
- message
50
- end
51
-
52
41
  end
@@ -20,11 +20,6 @@ module MetricFu
20
20
  `#{command}`
21
21
  end
22
22
 
23
- def format_directories
24
- dirs = options[:input_directory].join(" | ")
25
- "\"#{dirs}\""
26
- end
27
-
28
23
  def analyze
29
24
  @files = sort_files(assemble_files)
30
25
  @classes = sort_classes(assemble_classes(@files))
@@ -1,5 +1,4 @@
1
- class SaikuroHotspot < MetricFu::Hotspot
2
- include MetricFu::HotspotScoringStrategies
1
+ class MetricFu::SaikuroHotspot < MetricFu::Hotspot
3
2
 
4
3
  COLUMNS = %w{lines complexity}
5
4
 
@@ -11,16 +10,16 @@ class SaikuroHotspot < MetricFu::Hotspot
11
10
  :saikuro
12
11
  end
13
12
 
14
- def map(row)
15
- row.complexity
13
+ def map_strategy
14
+ :complexity
16
15
  end
17
16
 
18
- def reduce(scores)
19
- MetricFu::HotspotScoringStrategies.average(scores)
17
+ def reduce_strategy
18
+ :average
20
19
  end
21
20
 
22
- def score(metric_ranking, item)
23
- MetricFu::HotspotScoringStrategies.identity(metric_ranking, item)
21
+ def score_strategy
22
+ :identity
24
23
  end
25
24
 
26
25
  def generate_records(data, table)
@@ -51,10 +50,4 @@ class SaikuroHotspot < MetricFu::Hotspot
51
50
  "#{"average " if occurences > 1}complexity is %.1f" % complexity
52
51
  end
53
52
 
54
- def present_group_details(group)
55
- occurences = group.size
56
- complexity = get_mean(group.column("complexity"))
57
- "#{"average " if occurences > 1}complexity is %.1f" % complexity
58
- end
59
-
60
53
  end
@@ -1,4 +1,4 @@
1
- class StatsHotspot < MetricFu::Hotspot
1
+ class MetricFu::StatsHotspot < MetricFu::Hotspot
2
2
 
3
3
  COLUMNS = %w{stat_name stat_value}
4
4
 
@@ -10,16 +10,16 @@ class StatsHotspot < MetricFu::Hotspot
10
10
  :stats
11
11
  end
12
12
 
13
- def map(row)
14
- 0
13
+ def map_strategy
14
+ :absent
15
15
  end
16
16
 
17
- def reduce(scores)
18
- 0
17
+ def reduce_strategy
18
+ :absent
19
19
  end
20
20
 
21
- def score(metric_ranking, item)
22
- 0
21
+ def score_strategy
22
+ :absent
23
23
  end
24
24
 
25
25
  def generate_records(data, table)
@@ -1,6 +1,7 @@
1
1
  require 'fileutils'
2
2
  require 'coderay'
3
3
  MetricFu.metrics_require { 'base_template' }
4
+ MetricFu.lib_require { 'utility' }
4
5
 
5
6
  class AwesomeTemplate < MetricFu::Template
6
7
 
@@ -44,7 +45,7 @@ class AwesomeTemplate < MetricFu::Template
44
45
  end
45
46
 
46
47
  def convert_ruby_to_html(ruby_text, line_number)
47
- tokens = CodeRay.scan(ruby_text, :ruby)
48
+ tokens = CodeRay.scan(MetricFu::Utility.clean_ascii_text(ruby_text), :ruby)
48
49
  options = { :css => :class, :style => :alpha }
49
50
  if line_number.to_i > 0
50
51
  options = options.merge({:line_numbers => :inline, :line_number_start => line_number.to_i })
@@ -0,0 +1,20 @@
1
+ module MetricFu
2
+ module Utility
3
+ module_function
4
+
5
+ # Removes non-ASCII characters
6
+ def clean_ascii_text(text)
7
+ if text.respond_to?(:encode)
8
+ # avoids invalid multi-byte escape error
9
+ ascii_text = text.encode( 'ASCII', invalid: :replace, undef: :replace, replace: '' )
10
+ # see http://www.ruby-forum.com/topic/183413
11
+ pattern = Regexp.new('[\x80-\xff]', nil, 'n')
12
+ ascii_text.gsub(pattern, '')
13
+ else
14
+ text
15
+ end
16
+ end
17
+
18
+
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module MetricFu
2
- VERSION = "4.4.0"
2
+ VERSION = "4.4.1"
3
3
  end
data/metric_fu.gemspec CHANGED
@@ -28,14 +28,14 @@ Gem::Specification.new do |s|
28
28
  s.rdoc_options = ["--main", "README.md"]
29
29
 
30
30
  # metric dependencies
31
- s.add_runtime_dependency 'flay', ['~> 2.0.1']
31
+ s.add_runtime_dependency 'flay', ['>= 2.0.1', '~> 2.1']
32
32
  s.add_runtime_dependency 'churn', ['~> 0.0.28']
33
- s.add_runtime_dependency 'flog', ['~> 4.1.1']
34
- s.add_runtime_dependency 'reek', ['~> 1.3.1']
35
- s.add_runtime_dependency 'cane', ['~> 2.5.2']
36
- s.add_runtime_dependency 'rails_best_practices', ['>= 1.14.1', '~> 1.14']
33
+ s.add_runtime_dependency 'flog', ['>= 4.1.1', '~> 4.1']
34
+ s.add_runtime_dependency 'reek', ['>= 1.3.3', '~> 1.3']
35
+ s.add_runtime_dependency 'cane', ['>= 2.5.2', '~> 2.5']
36
+ s.add_runtime_dependency 'rails_best_practices', ['>= 1.14.3', '~> 1.14']
37
37
  s.add_runtime_dependency 'metric_fu-Saikuro', ['>= 1.1.1.0']
38
- s.add_runtime_dependency 'metric_fu-roodi', ['>= 2.2.1']
38
+ s.add_runtime_dependency 'roodi', ['~> 3.1']
39
39
  s.add_runtime_dependency 'code_metrics', ['~> 0.1']
40
40
 
41
41
  # other dependencies
@@ -10,8 +10,6 @@ describe MetricFu::Configuration do
10
10
  rcov.enabled = true
11
11
  end
12
12
  MetricFu.configure
13
- mri_only_metrics = MetricFu.mri_only_metrics.reject {|metric| MetricFu::Metric.get_metric(metric).enabled }
14
- MetricFu.stub(:mri_only_metrics).and_return(mri_only_metrics)
15
13
  MetricFu::Io::FileSystem.stub(:create_directories) # no need to create directories for the tests
16
14
  @config
17
15
  end
@@ -216,17 +214,11 @@ describe MetricFu::Configuration do
216
214
  @config.stub(:rails?).and_return(true)
217
215
  @config.reset
218
216
  MetricFu.configure
219
- %w(stats rails_best_practices).each do |metric|
217
+ %w(rails_best_practices).each do |metric|
220
218
  load_metric metric
221
219
  end
222
220
  end
223
221
 
224
- describe '#set_metrics ' do
225
- it 'should set the metrics to include stats' do
226
- MetricFu::Metric.enabled_metrics.map(&:name).should include(:stats)
227
- end
228
- end
229
-
230
222
  describe '#set_graphs ' do
231
223
  it 'should set the graphs to include rails_best_practices' do
232
224
  expect(MetricFu::Metric.get_metric(:rails_best_practices).has_graph?).to be_true
@@ -239,13 +231,6 @@ describe MetricFu::Configuration do
239
231
  should == ['app','lib']
240
232
  end
241
233
  end
242
- it 'should set @stats to {}' do
243
- load_metric 'stats'
244
- expect(MetricFu::Metric.get_metric(:stats).run_options).to eq({
245
- :additional_test_directories=>[{:glob_pattern=>"./spec/**/*_spec.rb", :file_pattern=>"spec"}],
246
- :additional_app_directories=>[{:glob_pattern=>"./engines/**/*.rb", :file_pattern=>""}]
247
- })
248
- end
249
234
 
250
235
  it 'should set @rails_best_practices to {}' do
251
236
  load_metric 'rails_best_practices'
@@ -257,15 +242,11 @@ describe MetricFu::Configuration do
257
242
  before(:each) do
258
243
  get_new_config
259
244
  @config.stub(:rails?).and_return(false)
260
- %w(stats rails_best_practices).each do |metric|
245
+ %w(rails_best_practices).each do |metric|
261
246
  load_metric metric
262
247
  end
263
248
  end
264
249
 
265
- it 'should set the available metrics' do
266
- MetricFu::Metric.enabled_metrics.map(&:name).should =~ [:churn, :flog, :flay, :reek, :roodi, :rcov, :hotspots, :saikuro, :cane, :stats] - MetricFu.mri_only_metrics
267
- end
268
-
269
250
  it 'should set the registered code_dirs to ["lib"]' do
270
251
  directory('code_dirs').should == ['lib']
271
252
  end
@@ -47,7 +47,7 @@ describe MetricFu::FlogGrapher do
47
47
 
48
48
  context "when metrics were not generated" do
49
49
  before(:each) do
50
- @metrics = YAML::load(File.open("#{resources_path}/yml/metric_missing.yml"))
50
+ @metrics = metric_data('metric_missing.yml')
51
51
  @date = "1/2"
52
52
  end
53
53
 
@@ -69,7 +69,7 @@ describe MetricFu::FlogGrapher do
69
69
 
70
70
  context "when metrics have been generated" do
71
71
  before(:each) do
72
- @metrics = YAML::load(File.open("#{resources_path}/yml/20090630.yml"))
72
+ @metrics = metric_data('20090630.yml')
73
73
  @date = "1/2"
74
74
  end
75
75
 
@@ -83,20 +83,6 @@ describe MetricFu::Generator do
83
83
  end
84
84
  end
85
85
 
86
- describe 'ConcreteClass#generate_result' do
87
- it 'should create a new instance of ConcreteClass' do
88
- ConcreteClass.should_receive(:new).and_return(@concrete_class)
89
- @concrete_class.should_receive(:generate_result).and_return(true)
90
- ConcreteClass.generate_result
91
- end
92
-
93
- it 'should call #generate_result on the new ConcreteClass' do
94
- ConcreteClass.should_receive(:new).and_return(@concrete_class)
95
- @concrete_class.should_receive(:generate_result).and_return(true)
96
- ConcreteClass.generate_result
97
- end
98
- end
99
-
100
86
  describe '@concrete_class should have hook methods for '\
101
87
  +'[before|after]_[emit|analyze|to_h]' do
102
88