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
         
     |