stepdown 0.3.2 → 0.3.3
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/bin/stepdown +4 -3
- data/lib/feature_parser.rb +8 -4
- data/lib/options.rb +5 -5
- data/lib/reporter.rb +2 -2
- data/lib/step_down.rb +2 -1
- data/lib/step_group.rb +1 -2
- data/lib/step_instance.rb +6 -2
- data/public/step_down.js +5 -0
- data/spec/lib/feature_parser_spec.rb +85 -0
- data/spec/lib/options_spec.rb +21 -20
- data/spec/lib/scenario_spec.rb +42 -0
- data/spec/lib/step_instance_spec.rb +60 -2
- data/stepdown.gemspec +1 -1
- data/templates/main.html.haml +16 -7
- metadata +6 -4
data/bin/stepdown
CHANGED
@@ -7,10 +7,11 @@ require 'options'
|
|
7
7
|
|
8
8
|
begin
|
9
9
|
|
10
|
-
Options.
|
11
|
-
|
10
|
+
options = Options.new
|
11
|
+
options.parse(ARGV)
|
12
|
+
options.validate
|
12
13
|
|
13
|
-
StepDown.new(
|
14
|
+
StepDown.new(options.steps_dir, options.features_dir, options.reporter).analyse
|
14
15
|
|
15
16
|
rescue Interrupt => e
|
16
17
|
puts "Quiting..."
|
data/lib/feature_parser.rb
CHANGED
@@ -8,21 +8,25 @@ class FeatureParser
|
|
8
8
|
|
9
9
|
def process_feature(file, instance)
|
10
10
|
@scenarios = []
|
11
|
+
file_lines = read_feature_file(file)
|
11
12
|
|
12
|
-
|
13
|
-
@line_no = line_no
|
13
|
+
file_lines.each do |line|
|
14
14
|
|
15
15
|
if line =~ /Scenario|Background/
|
16
16
|
@scenario = Scenario.new
|
17
17
|
@scenarios << @scenario
|
18
18
|
else
|
19
|
-
|
20
|
-
@scenario.add_step(
|
19
|
+
step = instance.line_matches(line)
|
20
|
+
@scenario.add_step(step) if step
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
return @scenarios
|
25
25
|
end
|
26
26
|
|
27
|
+
protected
|
28
|
+
def read_feature_file(file_name)
|
29
|
+
File.read(file_name).split("\n")
|
30
|
+
end
|
27
31
|
end
|
28
32
|
|
data/lib/options.rb
CHANGED
@@ -4,7 +4,7 @@ class Options
|
|
4
4
|
|
5
5
|
OUTPUT_FORMATS = ["html", "text"]
|
6
6
|
|
7
|
-
def
|
7
|
+
def parse(params)
|
8
8
|
@@steps_dir = "features/step_definitions"
|
9
9
|
@@features_dir = "features"
|
10
10
|
@@reporter = "html"
|
@@ -41,7 +41,7 @@ class Options
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
44
|
+
def validate
|
45
45
|
@@steps_dir = File.join(Dir.pwd, @@steps_dir)
|
46
46
|
@@features_dir = File.join(Dir.pwd, @@features_dir)
|
47
47
|
|
@@ -54,15 +54,15 @@ class Options
|
|
54
54
|
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
57
|
+
def steps_dir
|
58
58
|
@@steps_dir
|
59
59
|
end
|
60
60
|
|
61
|
-
def
|
61
|
+
def features_dir
|
62
62
|
@@features_dir
|
63
63
|
end
|
64
64
|
|
65
|
-
def
|
65
|
+
def reporter
|
66
66
|
@@reporter
|
67
67
|
end
|
68
68
|
|
data/lib/reporter.rb
CHANGED
@@ -46,7 +46,7 @@ class Reporter
|
|
46
46
|
total_steps += scen.steps.length
|
47
47
|
uniq_steps += scen.uniq_steps.length
|
48
48
|
end
|
49
|
-
total_steps / uniq_steps
|
49
|
+
sprintf "%.2f", (total_steps / uniq_steps)
|
50
50
|
end
|
51
51
|
|
52
52
|
def steps_scenario(scenarios)
|
@@ -55,7 +55,7 @@ class Reporter
|
|
55
55
|
scenarios.each do |scenario|
|
56
56
|
step_count += scenario.steps.length
|
57
57
|
end
|
58
|
-
step_count / scen_count
|
58
|
+
sprintf "%.2f", (step_count / scen_count)
|
59
59
|
end
|
60
60
|
|
61
61
|
end
|
data/lib/step_down.rb
CHANGED
@@ -67,7 +67,8 @@ class StepDown
|
|
67
67
|
|
68
68
|
usages.each do |usage|
|
69
69
|
if usage.number_scenarios > 0
|
70
|
-
|
70
|
+
use = sprintf "%.2f", (usage.total_usage / Float(usage.number_scenarios))
|
71
|
+
usage.use_scenario = use
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
data/lib/step_group.rb
CHANGED
data/lib/step_instance.rb
CHANGED
@@ -19,19 +19,23 @@ class StepInstance
|
|
19
19
|
@steps << regex
|
20
20
|
end
|
21
21
|
|
22
|
+
def self.method_missing(*args)
|
23
|
+
#nothing
|
24
|
+
end
|
25
|
+
|
22
26
|
def method_missing(*args)
|
23
27
|
#nothing
|
24
28
|
end
|
25
29
|
|
26
30
|
def self.const_missing(*args)
|
27
|
-
|
31
|
+
self
|
28
32
|
end
|
29
33
|
|
30
34
|
def require(*args)
|
31
35
|
# do nothing
|
32
36
|
end
|
33
37
|
|
34
|
-
def line_matches(line
|
38
|
+
def line_matches(line)
|
35
39
|
stripped_line = line.strip.gsub(/^(And|Given|When|Then) (.*)$/,'\2')
|
36
40
|
|
37
41
|
@steps.each_with_index do |regex,i|
|
data/public/step_down.js
CHANGED
@@ -9,6 +9,11 @@ $(document).ready(function(){
|
|
9
9
|
$("#scenario_filter").change(function(){
|
10
10
|
filter(this.options[this.selectedIndex].value, 2, $("#usages tr"));
|
11
11
|
});
|
12
|
+
|
13
|
+
$("a[class*=g]").click(function() {
|
14
|
+
$('.' + this.getAttribute("class")).show();
|
15
|
+
return false;
|
16
|
+
});
|
12
17
|
});
|
13
18
|
|
14
19
|
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/scenario')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/feature_parser')
|
3
|
+
|
4
|
+
describe FeatureParser do
|
5
|
+
def stub_line_match_with(instance, line, value)
|
6
|
+
instance.stub!(:line_matches).with(line).and_return(value)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "creating scenarios" do
|
10
|
+
before :each do
|
11
|
+
end
|
12
|
+
it "should create a scenario for a scenario line" do
|
13
|
+
|
14
|
+
file = mock("file")
|
15
|
+
instance = mock("instance")
|
16
|
+
file_lines = ["Scenario: My testing scenario"]
|
17
|
+
|
18
|
+
@parser = FeatureParser.new
|
19
|
+
@parser.should_receive(:read_feature_file).with(file).and_return(file_lines)
|
20
|
+
scenario = mock("scenario")
|
21
|
+
Scenario.should_receive(:new).and_return(scenario)
|
22
|
+
|
23
|
+
@parser.process_feature(file, instance).should =~ [scenario]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should create a scenario for a background line" do
|
27
|
+
file = mock("file")
|
28
|
+
instance = mock("instance")
|
29
|
+
file_lines = ["Background: My testing scenario"]
|
30
|
+
|
31
|
+
@parser = FeatureParser.new
|
32
|
+
@parser.should_receive(:read_feature_file).with(file).and_return(file_lines)
|
33
|
+
scenario = mock("scenario")
|
34
|
+
Scenario.should_receive(:new).and_return(scenario)
|
35
|
+
|
36
|
+
@parser.process_feature(file, instance).should =~ [scenario]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
describe "parsing step lines" do
|
42
|
+
before :each do
|
43
|
+
@parser = FeatureParser.new
|
44
|
+
@step_instance = mock("step_instance")
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should not add unmatched steps" do
|
49
|
+
lines = ["Scenario", "matched", "match 2"]
|
50
|
+
unmatched_lines = ["not matched", "not matched 2"]
|
51
|
+
steps = []
|
52
|
+
lines.each_with_index do |line, i|
|
53
|
+
step = Step.new(i, line)
|
54
|
+
stub_line_match_with(@step_instance, line, step)
|
55
|
+
steps << step
|
56
|
+
end
|
57
|
+
|
58
|
+
unmatched_lines.each do |line|
|
59
|
+
stub_line_match_with(@step_instance, line, nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
all_lines = [lines, unmatched_lines].flatten
|
63
|
+
@parser.should_receive(:read_feature_file).and_return(all_lines)
|
64
|
+
|
65
|
+
scenarios = @parser.process_feature(mock('file'), @step_instance)
|
66
|
+
scenarios.first.steps.should =~ steps[1..2]
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should add matched steps" do
|
70
|
+
lines = ["Scenario", "matched", "match 2"]
|
71
|
+
steps = []
|
72
|
+
lines.each_with_index do |line, i|
|
73
|
+
step = Step.new(i, line)
|
74
|
+
stub_line_match_with(@step_instance, line, step)
|
75
|
+
steps << step
|
76
|
+
end
|
77
|
+
@parser.should_receive(:read_feature_file).and_return(lines)
|
78
|
+
|
79
|
+
scenarios = @parser.process_feature(mock('file'), @step_instance)
|
80
|
+
scenarios.first.steps.should =~ steps[1..2]
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
data/spec/lib/options_spec.rb
CHANGED
@@ -1,66 +1,67 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/../../lib/options')
|
3
3
|
|
4
|
-
describe
|
4
|
+
describe @options do
|
5
5
|
|
6
6
|
before :each do
|
7
|
+
@options = Options.new
|
7
8
|
end
|
8
9
|
|
9
10
|
describe "setting input directories" do
|
10
11
|
it "should allow setting only steps directory" do
|
11
|
-
|
12
|
+
@options.parse(["--steps=step_dir"])
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
@options.steps_dir.should == "step_dir"
|
15
|
+
@options.features_dir.should == "features"
|
15
16
|
|
16
17
|
end
|
17
18
|
|
18
19
|
it "should allow setting only features directory" do
|
19
|
-
|
20
|
+
@options.parse(["--features=features_dir"])
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
@options.steps_dir.should == "features/step_definitions"
|
23
|
+
@options.features_dir.should == "features_dir"
|
23
24
|
end
|
24
25
|
|
25
26
|
it "should allow setting features and settings directory" do
|
26
|
-
|
27
|
+
@options.parse(["--features=features_dir", "--steps=steps_dir"])
|
27
28
|
|
28
|
-
|
29
|
-
|
29
|
+
@options.steps_dir.should == "steps_dir"
|
30
|
+
@options.features_dir.should == "features_dir"
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
34
|
describe "selecting reporter" do
|
34
35
|
it "should select html by default" do
|
35
|
-
|
36
|
+
@options.parse([])
|
36
37
|
|
37
|
-
|
38
|
+
@options.reporter.should == "html"
|
38
39
|
end
|
39
40
|
|
40
41
|
it "should allow selecting html" do
|
41
|
-
|
42
|
+
@options.parse(["--output=html"])
|
42
43
|
|
43
|
-
|
44
|
+
@options.reporter.should == "html"
|
44
45
|
end
|
45
46
|
|
46
47
|
it "should allow selecting text" do
|
47
|
-
|
48
|
+
@options.parse(["--output=text"])
|
48
49
|
|
49
|
-
|
50
|
+
@options.reporter.should == "text"
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
54
|
describe "using default directories" do
|
54
55
|
it "should select relative step directory" do
|
55
|
-
|
56
|
+
@options.parse([])
|
56
57
|
|
57
|
-
|
58
|
+
@options.steps_dir == "features/step_definitions"
|
58
59
|
end
|
59
60
|
|
60
61
|
it "should select relative feature directory" do
|
61
|
-
|
62
|
+
@options.parse([])
|
62
63
|
|
63
|
-
|
64
|
+
@options.features_dir.should == "features"
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/scenario')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/step')
|
3
|
+
|
4
|
+
|
5
|
+
describe Scenario do
|
6
|
+
before :each do
|
7
|
+
@scenario = Scenario.new
|
8
|
+
@s1 = Step.new(1, /step 1/)
|
9
|
+
@s2 = Step.new(2, /Step 2/)
|
10
|
+
@s2_dup = Step.new(2, /Step 2/)
|
11
|
+
@s3 = Step.new(3, /Step 3/)
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "adding steps" do
|
16
|
+
it "should add steps to cache" do
|
17
|
+
@scenario.add_step(@s1)
|
18
|
+
@scenario.add_step(@s2)
|
19
|
+
@scenario.add_step(@s2_dup)
|
20
|
+
@scenario.add_step(@s3)
|
21
|
+
|
22
|
+
steps = [@s1, @s2, @s2_dup, @s3]
|
23
|
+
@scenario.steps.should =~ steps
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "returning unique steps" do
|
29
|
+
it "should only return one instance of each step" do
|
30
|
+
@scenario.add_step(@s1)
|
31
|
+
@scenario.add_step(@s2)
|
32
|
+
@scenario.add_step(@s2_dup)
|
33
|
+
@scenario.add_step(@s3)
|
34
|
+
|
35
|
+
steps = [@s1, @s2, @s3]
|
36
|
+
@scenario.uniq_steps.should =~ steps
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/../../lib/step_instance')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../lib/step')
|
3
4
|
|
4
5
|
|
5
6
|
describe StepInstance do
|
@@ -10,17 +11,74 @@ describe StepInstance do
|
|
10
11
|
|
11
12
|
it "should deal with missing constants" do
|
12
13
|
lambda{ @step_instance.instance_eval("MissingConst") }.should_not raise_error
|
14
|
+
lambda{ @step_instance.instance_eval("MissingConst::MissingClass") }.should_not raise_error
|
15
|
+
lambda{ @step_instance.instance_eval("MissingConst::MissingClass.missing_method") }.should_not raise_error
|
13
16
|
end
|
17
|
+
|
14
18
|
it "should deal with missing methods" do
|
15
19
|
lambda{ @step_instance.doesnt_exist }.should_not raise_error
|
20
|
+
lambda{ StepInstance.doesnt_exist }.should_not raise_error
|
16
21
|
end
|
17
22
|
|
18
|
-
describe "steps" do
|
23
|
+
describe "returning steps" do
|
24
|
+
it "should return parsed steps" do
|
25
|
+
@step_instance.Given(/given/)
|
26
|
+
@step_instance.When(/when/)
|
27
|
+
@step_instance.Then(/then/)
|
28
|
+
|
29
|
+
@step_instance.steps.length.should == 3
|
30
|
+
end
|
19
31
|
|
20
32
|
end
|
21
33
|
|
22
|
-
describe "
|
34
|
+
describe "returning matched steps" do
|
35
|
+
it "should return nil when no matching step found" do
|
36
|
+
@step_instance.Given(/some step/)
|
37
|
+
@step_instance.line_matches("Given some other step").should be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should parse And steps" do
|
41
|
+
@step_instance.Given(/matched step/)
|
42
|
+
@step_instance.line_matches("And matched step").regex.should == /matched step/
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should parse Given steps" do
|
46
|
+
@step_instance.Given(/matched step/)
|
47
|
+
@step_instance.line_matches("Given matched step").regex.should == /matched step/
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should parse When steps" do
|
51
|
+
@step_instance.When(/matched step/)
|
52
|
+
@step_instance.line_matches("When matched step").regex.should == /matched step/
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should parse Then steps" do
|
56
|
+
@step_instance.Then(/matched step/)
|
57
|
+
@step_instance.line_matches("Then matched step").regex.should == /matched step/
|
58
|
+
end
|
23
59
|
|
24
60
|
end
|
61
|
+
|
62
|
+
describe "parsing step definitions" do
|
63
|
+
before :each do
|
64
|
+
@regex = /reg/
|
65
|
+
@step = mock('step')
|
66
|
+
Step.should_receive(:new).with(0, @regex).and_return(@step)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should define given steps" do
|
70
|
+
@step_instance.Given(@regex)
|
71
|
+
@step_instance.steps.should =~ [@step]
|
72
|
+
end
|
25
73
|
|
74
|
+
it "should define when steps" do
|
75
|
+
@step_instance.When(@regex)
|
76
|
+
@step_instance.steps.should =~ [@step]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should define then steps" do
|
80
|
+
@step_instance.Then(@regex)
|
81
|
+
@step_instance.steps.should =~ [@step]
|
82
|
+
end
|
83
|
+
end
|
26
84
|
end
|
data/stepdown.gemspec
CHANGED
data/templates/main.html.haml
CHANGED
@@ -96,14 +96,23 @@
|
|
96
96
|
%tbody
|
97
97
|
%th Step
|
98
98
|
%th Total step associations
|
99
|
-
%th
|
100
99
|
|
101
|
-
- groupings.
|
100
|
+
- groupings.each_with_index do |grouping, i|
|
101
|
+
- next if grouping.use_count == 0
|
102
102
|
%tr
|
103
|
-
%td
|
103
|
+
%td
|
104
|
+
= grouping.regex.inspect
|
105
|
+
%br
|
106
|
+
%a{:href => '#', :class => "g#{i}"}Show associated steps
|
104
107
|
%td= grouping.use_count
|
105
|
-
%tr
|
108
|
+
%tr{:class => "g#{i}", :style => "display: none;"}
|
106
109
|
%td{:colspan => 2}
|
107
|
-
|
108
|
-
%
|
109
|
-
|
110
|
+
%table
|
111
|
+
%tr
|
112
|
+
%th Association count
|
113
|
+
%th Step
|
114
|
+
%tbody
|
115
|
+
- grouping.in_steps.each do |step|
|
116
|
+
%tr
|
117
|
+
%td= step[1].count
|
118
|
+
%td= CGI.escapeHTML step[1].regex.inspect
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stepdown
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 3
|
10
|
+
version: 0.3.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sean Caffery
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-03-06 00:00:00 +11:00
|
19
19
|
default_executable: stepdown
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -79,7 +79,9 @@ files:
|
|
79
79
|
- lib/text_reporter.rb
|
80
80
|
- public/jquery-1.4.3.min.js
|
81
81
|
- public/step_down.js
|
82
|
+
- spec/lib/feature_parser_spec.rb
|
82
83
|
- spec/lib/options_spec.rb
|
84
|
+
- spec/lib/scenario_spec.rb
|
83
85
|
- spec/lib/step_group_spec.rb
|
84
86
|
- spec/lib/step_instance_spec.rb
|
85
87
|
- stepdown.gemspec
|