stepdown 0.3.3 → 0.4.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.
- data/Gemfile +4 -2
- data/Gemfile.lock +14 -10
- data/History.txt +30 -0
- data/README.rdoc +2 -2
- data/Rakefile +13 -0
- data/bin/stepdown +4 -4
- data/lib/stepdown.rb +6 -0
- data/lib/stepdown/analyzer.rb +67 -0
- data/lib/stepdown/feature_parser.rb +30 -0
- data/lib/stepdown/html_reporter.rb +41 -0
- data/lib/stepdown/options.rb +59 -0
- data/lib/stepdown/reporter.rb +106 -0
- data/lib/stepdown/scenario.rb +25 -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 +38 -0
- data/spec/lib/{feature_parser_spec.rb → stepdown/feature_parser_spec.rb} +13 -12
- data/spec/lib/{options_spec.rb → stepdown/options_spec.rb} +24 -6
- data/spec/lib/stepdown/reporter_spec.rb +184 -0
- data/spec/lib/stepdown/scenario_spec.rb +40 -0
- data/spec/lib/stepdown/step_collection_spec.rb +78 -0
- data/spec/lib/stepdown/step_group_spec.rb +43 -0
- data/spec/lib/{step_instance_spec.rb → stepdown/step_instance_spec.rb} +13 -12
- data/spec/spec_helper.rb +4 -0
- data/stepdown.gemspec +7 -4
- data/templates/main.html.haml +3 -3
- data/templates/style.sass +5 -4
- metadata +64 -34
- data/lib/counting_step.rb +0 -14
- data/lib/feature_parser.rb +0 -32
- data/lib/html_reporter.rb +0 -37
- data/lib/options.rb +0 -69
- data/lib/reporter.rb +0 -62
- data/lib/scenario.rb +0 -19
- data/lib/step.rb +0 -10
- data/lib/step_down.rb +0 -112
- data/lib/step_group.rb +0 -52
- data/lib/step_instance.rb +0 -60
- data/lib/step_usage.rb +0 -13
- data/lib/text_reporter.rb +0 -36
- data/spec/lib/scenario_spec.rb +0 -42
- data/spec/lib/step_group_spec.rb +0 -119
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,20 +2,24 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
diff-lcs (1.1.2)
|
5
|
-
haml (
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
rspec-
|
10
|
-
|
11
|
-
|
5
|
+
haml (2.0.10)
|
6
|
+
rake (0.8.7)
|
7
|
+
rcov (0.9.9)
|
8
|
+
rspec (2.5.0)
|
9
|
+
rspec-core (~> 2.5.0)
|
10
|
+
rspec-expectations (~> 2.5.0)
|
11
|
+
rspec-mocks (~> 2.5.0)
|
12
|
+
rspec-core (2.5.1)
|
13
|
+
rspec-expectations (2.5.0)
|
12
14
|
diff-lcs (~> 1.1.2)
|
13
|
-
rspec-mocks (2.
|
15
|
+
rspec-mocks (2.5.0)
|
14
16
|
|
15
17
|
PLATFORMS
|
16
18
|
java
|
17
19
|
ruby
|
18
20
|
|
19
21
|
DEPENDENCIES
|
20
|
-
haml
|
21
|
-
|
22
|
+
haml (> 2.0.0)
|
23
|
+
rake
|
24
|
+
rcov (~> 0.9.9)
|
25
|
+
rspec (~> 2.5.0)
|
data/History.txt
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
== 0.4.0 2011-3-29
|
2
|
+
* Better HTML output
|
3
|
+
* Structured like other gems
|
4
|
+
* Maintainability improvements
|
5
|
+
* Better test coverage
|
6
|
+
|
7
|
+
== 0.3.3 2011-03-05
|
8
|
+
* Better HTML output
|
9
|
+
|
10
|
+
== 0.3.2 - 2011-02-27
|
11
|
+
* Bugfix in option parsing
|
12
|
+
* Bugfix for missing constants
|
13
|
+
|
14
|
+
== 0.3.1 - 2011-02-26
|
15
|
+
* Fix broken include [Robert Postill]
|
16
|
+
|
17
|
+
== 0.3.0 - 2011-02-26
|
18
|
+
* Added text report
|
19
|
+
* Bug fix for missing constants
|
20
|
+
|
21
|
+
== 0.2.1 - 2011-02-19
|
22
|
+
* Proper option parsing
|
23
|
+
|
24
|
+
== 0.2 - 2011-02-14
|
25
|
+
* Added some specs
|
26
|
+
* Improved output
|
27
|
+
* Updated usage message
|
28
|
+
|
29
|
+
== 0.1 - 2011-01-16
|
30
|
+
* Initial release
|
data/README.rdoc
CHANGED
@@ -17,5 +17,5 @@ Stepdown is available as a ruby gem
|
|
17
17
|
gem install stepdown
|
18
18
|
|
19
19
|
== Usage
|
20
|
-
stepdown <step definition directory> <feature file directory>
|
21
|
-
e.g. stepdown features/step_definitions features
|
20
|
+
stepdown --steps <step definition directory> --features <feature file directory>
|
21
|
+
e.g. stepdown --steps features/step_definitions --features features
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
|
3
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
4
|
+
t.fail_on_error = false
|
5
|
+
end
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
8
|
+
t.fail_on_error = false
|
9
|
+
t.rcov_opts = %w{ --exclude gems\/,spec\/,features\/}
|
10
|
+
t.rcov = true
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
data/bin/stepdown
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
lib = File.expand_path('../lib/', __FILE__)
|
3
3
|
$:.unshift lib unless $:.include?(lib)
|
4
4
|
|
5
|
-
require '
|
6
|
-
require 'options'
|
5
|
+
require 'stepdown'
|
6
|
+
require 'stepdown/options'
|
7
7
|
|
8
8
|
begin
|
9
9
|
|
10
|
-
options = Options.new
|
10
|
+
options = Stepdown::Options.new
|
11
11
|
options.parse(ARGV)
|
12
12
|
options.validate
|
13
13
|
|
14
|
-
|
14
|
+
Stepdown::Analyzer.new(options.steps_dir, options.features_dir, options.reporter).analyse
|
15
15
|
|
16
16
|
rescue Interrupt => e
|
17
17
|
puts "Quiting..."
|
data/lib/stepdown.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Stepdown
|
4
|
+
class Analyzer
|
5
|
+
def initialize(steps_dir, feature_dir, reporter)
|
6
|
+
@feature_dir = feature_dir
|
7
|
+
@steps_dir = steps_dir
|
8
|
+
@reporter = reporter
|
9
|
+
end
|
10
|
+
|
11
|
+
def analyse
|
12
|
+
puts "Parsing feature files..."
|
13
|
+
scenarios = process_feature_files(feature_files)
|
14
|
+
|
15
|
+
puts "Performing analysis..."
|
16
|
+
|
17
|
+
reporter = reporter(@reporter, scenarios, instance.step_collection)
|
18
|
+
reporter.output_overview
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_feature_files(feature_files)
|
23
|
+
parser = Stepdown::FeatureParser.new
|
24
|
+
|
25
|
+
scenarios = []
|
26
|
+
feature_files.each do |feature_file|
|
27
|
+
scenarios << parser.process_feature(feature_file, instance)
|
28
|
+
end
|
29
|
+
scenarios.flatten
|
30
|
+
end
|
31
|
+
|
32
|
+
def reporter(type, scenarios, step_collection)
|
33
|
+
case type
|
34
|
+
when "html"
|
35
|
+
Stepdown::HTMLReporter.new(scenarios, step_collection)
|
36
|
+
when "text"
|
37
|
+
Stepdown::TextReporter.new(scenarios, step_collection)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def step(id)
|
42
|
+
instance.steps.detect{|step| step.id == id}
|
43
|
+
end
|
44
|
+
|
45
|
+
def instance
|
46
|
+
@instance ||= begin
|
47
|
+
new_inst = Stepdown::StepInstance.new
|
48
|
+
|
49
|
+
Dir.glob(step_files).each do |file_name|
|
50
|
+
new_inst.instance_eval File.read(file_name)
|
51
|
+
end
|
52
|
+
new_inst
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def feature_files
|
58
|
+
return @feature_files if @feature_files
|
59
|
+
@feature_files = Dir.glob(@feature_dir + '/**/*.feature')
|
60
|
+
end
|
61
|
+
|
62
|
+
def step_files
|
63
|
+
return @step_files if @step_files
|
64
|
+
@step_files = Dir.glob(@steps_dir + '/**/*.rb')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'stepdown/step'
|
2
|
+
require 'stepdown/scenario'
|
3
|
+
module Stepdown
|
4
|
+
class FeatureParser
|
5
|
+
|
6
|
+
def process_feature(file, instance)
|
7
|
+
scenarios = []
|
8
|
+
file_lines = read_feature_file(file)
|
9
|
+
|
10
|
+
file_lines.each do |line|
|
11
|
+
|
12
|
+
if line =~ /Scenario|Background/
|
13
|
+
@scenario = Scenario.new
|
14
|
+
scenarios << @scenario
|
15
|
+
else
|
16
|
+
step = instance.line_matches(line)
|
17
|
+
@scenario.add_step(step) if step
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
scenarios
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
def read_feature_file(file_name)
|
26
|
+
File.read(file_name).split("\n")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'stepdown/reporter'
|
3
|
+
require 'haml'
|
4
|
+
require 'sass'
|
5
|
+
|
6
|
+
module Stepdown
|
7
|
+
class HTMLReporter < Reporter
|
8
|
+
|
9
|
+
def output_overview()
|
10
|
+
puts "Generating report..."
|
11
|
+
FileUtils.mkdir_p(Reporter::OUTPUT_DIR)
|
12
|
+
copy_files
|
13
|
+
|
14
|
+
template = File.open(File.expand_path(File.dirname(__FILE__)) + '/../../templates/main.html.haml').read()
|
15
|
+
engine = Haml::Engine.new(template)
|
16
|
+
|
17
|
+
out = File.new(Reporter::OUTPUT_DIR + '/analysis.html','w+')
|
18
|
+
out.puts engine.render(self)
|
19
|
+
out.close
|
20
|
+
|
21
|
+
template = File.open(File.expand_path(File.dirname(__FILE__)) + '/../../templates/style.sass').read
|
22
|
+
sass_engine = Sass::Engine.new(template)
|
23
|
+
|
24
|
+
out = File.new(Reporter::OUTPUT_DIR + '/style.css', 'w+')
|
25
|
+
out.puts sass_engine.render
|
26
|
+
|
27
|
+
out.close
|
28
|
+
|
29
|
+
$stdout.puts "\nReport output to #{Reporter::OUTPUT_DIR}/analysis.html"
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def copy_files
|
35
|
+
['step_down.js', 'jquery-1.4.3.min.js'].each do |file|
|
36
|
+
src = File.expand_path("#{File.dirname(__FILE__)}/../../public/#{file}")
|
37
|
+
FileUtils.cp(src, File.join(OUTPUT_DIR, "#{file}"))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Stepdown
|
4
|
+
class Options
|
5
|
+
attr_reader :steps_dir, :features_dir, :reporter
|
6
|
+
|
7
|
+
OUTPUT_FORMATS = ["html", "text"]
|
8
|
+
|
9
|
+
def parse(params)
|
10
|
+
@steps_dir = "features/step_definitions"
|
11
|
+
@features_dir = "features"
|
12
|
+
@reporter = "html"
|
13
|
+
parser = OptionParser.new do |opts|
|
14
|
+
opts.banner = "Usage: stepdown step_definition_dir feature_file_directory"
|
15
|
+
|
16
|
+
opts.separator("")
|
17
|
+
|
18
|
+
opts.on("--output=TYPE", OUTPUT_FORMATS, "Select ouput format (#{OUTPUT_FORMATS.join(',')}). Default: html") do |o|
|
19
|
+
@reporter = o
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("--steps=STEPS_DIR", "Step definition directory. Default: ./features/step_definitions") do |o|
|
23
|
+
@steps_dir = o
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("--features=FEATURE_DIR", "Feature file directory. Default: ./features") do |o|
|
27
|
+
@features_dir = o
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on_tail("-h", "--help", "You're looking at it") do |o|
|
31
|
+
puts opts
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
begin
|
38
|
+
parser.parse(params)
|
39
|
+
|
40
|
+
rescue OptionParser::ParseError => e
|
41
|
+
puts e
|
42
|
+
exit 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def validate(io = STDOUT)
|
47
|
+
@steps_dir = File.join(Dir.pwd, @steps_dir)
|
48
|
+
@features_dir = File.join(Dir.pwd, @features_dir)
|
49
|
+
|
50
|
+
[@steps_dir, @features_dir].each do |dir|
|
51
|
+
unless File.exists?(dir)
|
52
|
+
io.puts "Directory #{dir} does not exist"
|
53
|
+
exit 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'stepdown/step_group'
|
2
|
+
require 'stepdown/step_usage'
|
3
|
+
|
4
|
+
module Stepdown
|
5
|
+
class Reporter
|
6
|
+
OUTPUT_DIR = "./stepdown"
|
7
|
+
|
8
|
+
attr_reader :scenarios, :usages, :step_collection, :grouping
|
9
|
+
|
10
|
+
def initialize(scenarios, step_collection)
|
11
|
+
@scenarios = scenarios
|
12
|
+
@step_collection = step_collection
|
13
|
+
end
|
14
|
+
|
15
|
+
def groupings
|
16
|
+
@groupings ||= grouping(@scenarios)
|
17
|
+
end
|
18
|
+
|
19
|
+
def total_scenarios
|
20
|
+
@scenarios.length
|
21
|
+
end
|
22
|
+
|
23
|
+
def total_steps
|
24
|
+
@step_collection.length
|
25
|
+
end
|
26
|
+
|
27
|
+
def steps_per_scenario
|
28
|
+
steps_scenario(@scenarios)
|
29
|
+
end
|
30
|
+
|
31
|
+
def unique_steps
|
32
|
+
uniq_steps_per_scenario(@scenarios)
|
33
|
+
end
|
34
|
+
|
35
|
+
def grouping(scenarios)
|
36
|
+
step_groups = @step_collection.collect{|step| Stepdown::StepGroup.new(step) }
|
37
|
+
|
38
|
+
step_groups.each do |step_group|
|
39
|
+
scenarios.each do |scenario|
|
40
|
+
|
41
|
+
if scenario.steps.any?{|step| step.id == step_group.id}
|
42
|
+
step_group.add_steps(scenario.steps)
|
43
|
+
step_group.update_use_count(scenario.step_count)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
step_groups.sort{|a,b| b.use_count <=> a.use_count}
|
49
|
+
end
|
50
|
+
|
51
|
+
def step_usage(scenarios)
|
52
|
+
usages = @step_collection.collect{|step| Stepdown::StepUsage.new(step) }
|
53
|
+
scenarios.each do |scenario|
|
54
|
+
|
55
|
+
scenario.steps.each do |step|
|
56
|
+
usage = usages.detect{|use| use.step.id == step.id}
|
57
|
+
if usage
|
58
|
+
usage.total_usage += step.count
|
59
|
+
usage.number_scenarios += 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
usages.each do |usage|
|
65
|
+
if usage.number_scenarios > 0
|
66
|
+
use = sprintf "%.2f", (usage.total_usage / Float(usage.number_scenarios))
|
67
|
+
usage.use_scenario = use
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
usages.sort{|a,b| b.total_usage <=> a.total_usage}
|
72
|
+
end
|
73
|
+
|
74
|
+
def step_usages
|
75
|
+
@step_usages ||= step_usage(@scenarios)
|
76
|
+
end
|
77
|
+
|
78
|
+
def usages
|
79
|
+
step_usages.select{|use| use.total_usage > 0 }
|
80
|
+
end
|
81
|
+
|
82
|
+
def unused_steps
|
83
|
+
step_usages.select{|use| use.total_usage == 0}
|
84
|
+
end
|
85
|
+
|
86
|
+
def uniq_steps_per_scenario(scenarios)
|
87
|
+
total_steps = 0.0
|
88
|
+
uniq_steps = 0.0
|
89
|
+
scenarios.each do |scen|
|
90
|
+
total_steps += scen.step_count
|
91
|
+
uniq_steps += scen.unique_step_count
|
92
|
+
end
|
93
|
+
sprintf "%.2f", (total_steps / uniq_steps)
|
94
|
+
end
|
95
|
+
|
96
|
+
def steps_scenario(scenarios)
|
97
|
+
scen_count = scenarios.length
|
98
|
+
step_count = 0.0
|
99
|
+
scenarios.each do |scenario|
|
100
|
+
step_count += scenario.step_count
|
101
|
+
end
|
102
|
+
sprintf "%.2f", (step_count / scen_count)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'stepdown/step_collection'
|
2
|
+
|
3
|
+
module Stepdown
|
4
|
+
class Scenario
|
5
|
+
attr_reader :step_count
|
6
|
+
def initialize
|
7
|
+
@step_collection = Stepdown::StepCollection.new
|
8
|
+
@step_count = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_step(step)
|
12
|
+
@step_count += 1
|
13
|
+
@step_collection.add_step(step.id, step.regex)
|
14
|
+
end
|
15
|
+
|
16
|
+
def steps
|
17
|
+
@step_collection.steps
|
18
|
+
end
|
19
|
+
|
20
|
+
def unique_step_count
|
21
|
+
@step_collection.length
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|