stepdown-patched 0.6.3.1patched
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.
- data/.bundle/config +1 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +31 -0
- data/History.txt +50 -0
- data/README.rdoc +28 -0
- data/Rakefile +14 -0
- data/bin/stepdown +23 -0
- data/lib/stepdown/analyzer.rb +74 -0
- data/lib/stepdown/feature_parser.rb +60 -0
- data/lib/stepdown/graph.rb +75 -0
- data/lib/stepdown/html_reporter.rb +37 -0
- data/lib/stepdown/options.rb +68 -0
- data/lib/stepdown/reporter.rb +23 -0
- data/lib/stepdown/scenario.rb +26 -0
- data/lib/stepdown/statistics.rb +162 -0
- data/lib/stepdown/step.rb +22 -0
- data/lib/stepdown/step_collection.rb +36 -0
- data/lib/stepdown/step_group.rb +45 -0
- data/lib/stepdown/step_instance.rb +63 -0
- data/lib/stepdown/step_usage.rb +15 -0
- data/lib/stepdown/text_reporter.rb +39 -0
- data/lib/stepdown/version.rb +3 -0
- data/lib/stepdown/yaml_writer.rb +14 -0
- data/lib/stepdown.rb +17 -0
- data/public/bluff-min.js +1 -0
- data/public/excanvas.js +35 -0
- data/public/jquery-1.6.1.min.js +18 -0
- data/public/js-class.js +1 -0
- data/public/step_down.js +41 -0
- data/public/stepdown.css +24 -0
- data/spec/fixtures/20110611.yml +5 -0
- data/spec/fixtures/20110612.yml +5 -0
- data/spec/lib/stepdown/analyzer_spec.rb +70 -0
- data/spec/lib/stepdown/feature_parser_spec.rb +93 -0
- data/spec/lib/stepdown/graph_spec.rb +82 -0
- data/spec/lib/stepdown/options_spec.rb +98 -0
- data/spec/lib/stepdown/scenario_spec.rb +40 -0
- data/spec/lib/stepdown/statistics_spec.rb +239 -0
- data/spec/lib/stepdown/step_collection_spec.rb +78 -0
- data/spec/lib/stepdown/step_group_spec.rb +43 -0
- data/spec/lib/stepdown/step_instance_spec.rb +85 -0
- data/spec/spec_helper.rb +4 -0
- data/stepdown.gemspec +30 -0
- data/templates/_empty.html.erb +5 -0
- data/templates/_grouping.html.erb +31 -0
- data/templates/_unused.html.erb +5 -0
- data/templates/_usages.html.erb +8 -0
- data/templates/index.html.erb +218 -0
- data/templates/style.sass +25 -0
- metadata +183 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'stepdown/step_group'
|
2
|
+
require 'stepdown/step_usage'
|
3
|
+
require 'delegate'
|
4
|
+
|
5
|
+
module Stepdown
|
6
|
+
class Reporter < Delegator
|
7
|
+
|
8
|
+
def initialize(statistics)
|
9
|
+
@statistics = statistics
|
10
|
+
super @statistics
|
11
|
+
end
|
12
|
+
|
13
|
+
def __getobj__
|
14
|
+
@statistics
|
15
|
+
end
|
16
|
+
|
17
|
+
def __setobj__(statistics)
|
18
|
+
@statistics = statistics
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'stepdown/step_collection'
|
2
|
+
|
3
|
+
module Stepdown
|
4
|
+
class Scenario
|
5
|
+
attr_reader :step_count, :name
|
6
|
+
def initialize(name)
|
7
|
+
@step_collection = Stepdown::StepCollection.new
|
8
|
+
@step_count = 0
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_step(step)
|
13
|
+
@step_count += 1
|
14
|
+
@step_collection.add_step(step.id, step.regex)
|
15
|
+
end
|
16
|
+
|
17
|
+
def steps
|
18
|
+
@step_collection.steps
|
19
|
+
end
|
20
|
+
|
21
|
+
def unique_step_count
|
22
|
+
@step_collection.length
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
|
2
|
+
module Stepdown
|
3
|
+
class Statistics
|
4
|
+
attr_reader :scenarios, :usages, :step_collection, :grouping
|
5
|
+
|
6
|
+
def initialize(scenarios, step_collection)
|
7
|
+
@scenarios = scenarios
|
8
|
+
@step_collection = step_collection
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate
|
12
|
+
puts "Performing analysis..." unless Stepdown.quiet
|
13
|
+
groupings
|
14
|
+
step_usages
|
15
|
+
empty
|
16
|
+
steps_per_scenario
|
17
|
+
unique_steps
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_h
|
21
|
+
stats = {}
|
22
|
+
stats[:number_scenarios] = total_scenarios
|
23
|
+
stats[:total_steps] = total_steps
|
24
|
+
stats[:steps_per_scenario] = steps_per_scenario
|
25
|
+
stats[:unused_steps] = unused_step_count
|
26
|
+
stats
|
27
|
+
end
|
28
|
+
|
29
|
+
def groupings_rest
|
30
|
+
groupings[10..groupings.length]
|
31
|
+
end
|
32
|
+
|
33
|
+
def groupings_top(limit = 10)
|
34
|
+
groupings[0...limit]
|
35
|
+
end
|
36
|
+
|
37
|
+
def groupings
|
38
|
+
@groupings ||= grouping(@scenarios)
|
39
|
+
end
|
40
|
+
|
41
|
+
def total_scenarios
|
42
|
+
@scenarios.length
|
43
|
+
end
|
44
|
+
|
45
|
+
def total_steps
|
46
|
+
@step_collection.length
|
47
|
+
end
|
48
|
+
|
49
|
+
def steps_per_scenario
|
50
|
+
@steps_per_scenario ||= steps_scenario(@scenarios)
|
51
|
+
end
|
52
|
+
|
53
|
+
def unique_steps
|
54
|
+
@uniq_steps_per_scenario ||= uniq_steps_per_scenario(@scenarios)
|
55
|
+
end
|
56
|
+
|
57
|
+
def grouping(scenarios)
|
58
|
+
step_groups = @step_collection.collect{|step| Stepdown::StepGroup.new(step) }
|
59
|
+
|
60
|
+
step_groups.each do |step_group|
|
61
|
+
scenarios.each do |scenario|
|
62
|
+
|
63
|
+
if scenario.steps.any?{|step| step.id == step_group.id}
|
64
|
+
step_group.add_steps(scenario.steps)
|
65
|
+
step_group.update_use_count(scenario.step_count)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
step_groups.sort{|a,b| b.use_count <=> a.use_count}
|
71
|
+
end
|
72
|
+
|
73
|
+
def step_usage(scenarios)
|
74
|
+
usages = @step_collection.collect{|step| Stepdown::StepUsage.new(step) }
|
75
|
+
scenarios.each do |scenario|
|
76
|
+
|
77
|
+
scenario.steps.each do |step|
|
78
|
+
usage = usages.detect{|use| use.step.id == step.id}
|
79
|
+
if usage
|
80
|
+
usage.total_usage += step.count
|
81
|
+
usage.number_scenarios += 1
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
usages.each do |usage|
|
87
|
+
if usage.number_scenarios > 0
|
88
|
+
use = sprintf "%.2f", (usage.total_usage / Float(usage.number_scenarios))
|
89
|
+
usage.use_scenario = use
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
usages.sort{|a,b| b.total_usage <=> a.total_usage}
|
94
|
+
end
|
95
|
+
|
96
|
+
def usages_top(limit = 10)
|
97
|
+
usages[0...limit]
|
98
|
+
end
|
99
|
+
|
100
|
+
def usages_rest
|
101
|
+
usages[10..usages.length]
|
102
|
+
end
|
103
|
+
|
104
|
+
def step_usages
|
105
|
+
@step_usages ||= step_usage(@scenarios)
|
106
|
+
end
|
107
|
+
|
108
|
+
def usages
|
109
|
+
step_usages.select{|use| use.total_usage > 0 }
|
110
|
+
end
|
111
|
+
|
112
|
+
def unused_rest
|
113
|
+
unused[10..unused.length]
|
114
|
+
end
|
115
|
+
|
116
|
+
def unused_top(limit = 10)
|
117
|
+
unused[0...limit]
|
118
|
+
end
|
119
|
+
|
120
|
+
def unused
|
121
|
+
step_usages.select{|use| use.total_usage == 0}
|
122
|
+
end
|
123
|
+
|
124
|
+
def unused_step_count
|
125
|
+
unused.length
|
126
|
+
end
|
127
|
+
|
128
|
+
def uniq_steps_per_scenario(scenarios)
|
129
|
+
total_steps = 0.0
|
130
|
+
uniq_steps = 0.0
|
131
|
+
scenarios.each do |scen|
|
132
|
+
total_steps += scen.step_count
|
133
|
+
uniq_steps += scen.unique_step_count
|
134
|
+
end
|
135
|
+
sprintf "%.2f", (total_steps / uniq_steps)
|
136
|
+
end
|
137
|
+
|
138
|
+
def steps_scenario(scenarios)
|
139
|
+
scen_count = scenarios.length
|
140
|
+
step_count = 0.0
|
141
|
+
scenarios.each do |scenario|
|
142
|
+
step_count += scenario.step_count
|
143
|
+
end
|
144
|
+
sprintf "%.2f", (step_count / scen_count)
|
145
|
+
end
|
146
|
+
|
147
|
+
def empty_rest
|
148
|
+
empty[10..empty.length] || []
|
149
|
+
end
|
150
|
+
|
151
|
+
def empty_top(limit = 10)
|
152
|
+
empty[0...limit]
|
153
|
+
end
|
154
|
+
|
155
|
+
def empty
|
156
|
+
@empty_scenarios ||= @scenarios.select do |scen|
|
157
|
+
scen.steps.empty?
|
158
|
+
end
|
159
|
+
@empty_scenarios
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Stepdown
|
2
|
+
class Step
|
3
|
+
|
4
|
+
attr_accessor :count
|
5
|
+
attr_reader :id, :regex
|
6
|
+
|
7
|
+
def initialize(id, regex)
|
8
|
+
@id = id
|
9
|
+
@regex = regex
|
10
|
+
@count = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def <=>(other)
|
14
|
+
other.count <=> self.count
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
self.id == other.id
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'stepdown/step'
|
2
|
+
|
3
|
+
module Stepdown
|
4
|
+
class StepCollection
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@steps = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_step(id, regex)
|
12
|
+
if @steps[id]
|
13
|
+
@steps[id].count += 1
|
14
|
+
else
|
15
|
+
@steps[id] = Stepdown::Step.new(id, regex)
|
16
|
+
@steps[id].count = 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def steps
|
21
|
+
@steps.collect{|id,step| step }
|
22
|
+
end
|
23
|
+
|
24
|
+
def each
|
25
|
+
@steps.each{|id, step| yield step }
|
26
|
+
end
|
27
|
+
|
28
|
+
def [](id)
|
29
|
+
@steps[id]
|
30
|
+
end
|
31
|
+
|
32
|
+
def length
|
33
|
+
@steps.length
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
require 'stepdown/step_collection'
|
3
|
+
|
4
|
+
module Stepdown
|
5
|
+
class StepGroup
|
6
|
+
attr_reader :id, :regex, :use_count
|
7
|
+
|
8
|
+
def initialize(step)
|
9
|
+
@id = step.id
|
10
|
+
@regex = step.regex
|
11
|
+
@use_count = 0
|
12
|
+
@step_collection = Stepdown::StepCollection.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def step_collection
|
16
|
+
@step_collection.sort
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_step(step)
|
20
|
+
@step_collection.add_step(step.id, step.regex)
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_steps(step_set)
|
24
|
+
step_set.each{|step| add_step(step)}
|
25
|
+
end
|
26
|
+
|
27
|
+
def update_use_count(num_steps)
|
28
|
+
@use_count += num_steps
|
29
|
+
end
|
30
|
+
|
31
|
+
def group_graph
|
32
|
+
base = "https://chart.googleapis.com/chart?cht=gv:dot&chl=graph{"
|
33
|
+
base += "a [label=\"#{CGI.escape(CGI.escapeHTML(@regex.inspect.to_s))}\"];"
|
34
|
+
|
35
|
+
step_collection[0..10].each do |step|
|
36
|
+
|
37
|
+
next if step.regex.nil?
|
38
|
+
base += "a--\"#{CGI.escape(CGI.escapeHTML(step.regex.inspect.to_s))}\" [weight=#{step.count}];"
|
39
|
+
#a [label=\"#{grouping.in_steps[0][:step].regex.inspect}\"]; a--b [penwidth=3,weight=2];b--d}"
|
40
|
+
end
|
41
|
+
base += "}"
|
42
|
+
base
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'stepdown/step_collection'
|
2
|
+
|
3
|
+
module Stepdown
|
4
|
+
class StepInstance
|
5
|
+
def initialize
|
6
|
+
@steps = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def Given(regex,&block)
|
10
|
+
define_step(regex,&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def When(regex,&block)
|
14
|
+
define_step(regex,&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def Then(regex,&block)
|
18
|
+
define_step(regex,&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def define_step(regex,&block)
|
22
|
+
@steps << regex
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.method_missing(*args)
|
26
|
+
#nothing
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_missing(*args)
|
30
|
+
#nothing
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.const_missing(*args)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def require(*args)
|
38
|
+
# do nothing
|
39
|
+
end
|
40
|
+
|
41
|
+
def line_matches(line)
|
42
|
+
#stripped_line = line.strip.gsub(/^(And|Given|When|Then) (.*)$/,'\2')
|
43
|
+
|
44
|
+
@steps.each_with_index do |regex,i|
|
45
|
+
match = regex.match(line)
|
46
|
+
if match
|
47
|
+
return step_collection.detect{|step| i == step.id}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
return nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def step_collection
|
55
|
+
return @step_collection if @step_collection
|
56
|
+
@step_collection = StepCollection.new
|
57
|
+
@steps.each_with_index do |regex, i|
|
58
|
+
@step_collection.add_step(i, regex)
|
59
|
+
end
|
60
|
+
@step_collection
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'stepdown/reporter'
|
2
|
+
|
3
|
+
module Stepdown
|
4
|
+
class TextReporter < Reporter
|
5
|
+
|
6
|
+
def output_overview
|
7
|
+
puts "Generating report..." unless Stepdown.quiet
|
8
|
+
output = File.new(Stepdown.output_directory + '/analysis.txt', "w+")
|
9
|
+
|
10
|
+
output.puts "Total number of scenarios: #{total_scenarios}"
|
11
|
+
output.puts "Total numer of steps: #{total_steps}"
|
12
|
+
output.puts "Unused steps: #{unused_step_count}"
|
13
|
+
output.puts "Steps per scenario: #{steps_per_scenario}"
|
14
|
+
output.puts "Unique steps per scenario: #{unique_steps}"
|
15
|
+
|
16
|
+
output.puts "Step usages"
|
17
|
+
output.puts "Step|Total usage|Scenarios|Use per scenario"
|
18
|
+
usages.each{|use| output.puts used_step_line(use) }
|
19
|
+
|
20
|
+
output.puts "Unused steps"
|
21
|
+
unused_steps.each{|use| output.puts unused_step_line(use) }
|
22
|
+
|
23
|
+
output.close
|
24
|
+
|
25
|
+
puts "Report output to #{Stepdown.output_directory}/analysis.txt" unless Stepdown.quiet
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def used_step_line(use)
|
30
|
+
line = [use.step.regex.inspect, use.total_usage, use.number_scenarios, use.use_scenario]
|
31
|
+
line.join("|")
|
32
|
+
end
|
33
|
+
|
34
|
+
def unused_step_line(use)
|
35
|
+
use.step.regex.inspect
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|