cucumber_characteristics 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+
19
+ features/characteristics/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cucumber_characteristics.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Stuart Ingram
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # CucumberCharacteristics
2
+
3
+ Gem to profile cucumber steps and features
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'cucumber_characteristics'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install cucumber_characteristics
18
+
19
+ ## Usage
20
+
21
+ 1. For always-on automatic loading (recommended), add `require 'cucumber_characteristics/autoload'` to `features/support/yourapp_env.rb`. It is recommended by cucumber that you do not enhance features/support/env.rb so that upgrades are painless (relatively)
22
+
23
+ 2. Add it to your `cucumber.yml` by adding `--format CucumberCharacteristics::Formatter` i.e.
24
+
25
+ `std_opts = "-r features/. -r --quiet --format CucumberCharacteristics::Formatter --format progress"`
26
+
27
+ 3. Use it via command line with `--format CucumberCharacteristics::Formatter`.
28
+
29
+ ## Configuration
30
+
31
+ You can configure the export of step characteristics via the following (defaults are same as example)
32
+
33
+ CucumberCharacteristics.configure do |config|
34
+ config.export_json = true
35
+ config.export_html = true
36
+ config.target_filename = 'cucumber_step_characteristics'
37
+ config.relative_path = 'features/characteristics'
38
+ end
39
+
40
+ ## Results
41
+
42
+ Exported characteristic information is listed out at the end of the cucumber run in a message similar to
43
+
44
+ Step characteristic report written to /home/singram/projects/gems/cucumber_characteristics/features/characteristics/cucumber_step_characteristics.html
45
+ Step characteristic report written to /home/singram/projects/gems/cucumber_characteristics/features/characteristics/cucumber_step_characteristics.json
46
+
47
+ depending on the options specified.
48
+
49
+ The JSON option is provided for convenience in case there is a further use case/analysis required that is not provided by the gem.
50
+
51
+ ## Problem
52
+
53
+ The formatting hooks on the face of it provide the necessary event points to profile any given feature file.
54
+ This is true for a Scenario, but consider the following ScenaioOutline
55
+
56
+ Feature: As a user I want to understand where my tests are spending their time
57
+
58
+ Scenario Outline: Timings for scenario outline
59
+ Given I wait <given_wait> seconds
60
+ When I wait <when_wait> seconds
61
+ Then I wait <then_wait> seconds
62
+ And I wait 0.2 seconds
63
+ Examples:
64
+ | given_wait | when_wait | then_wait |
65
+ | 1 | 2 | 3 |
66
+ | 5 | 6 | 7 |
67
+
68
+ Running
69
+
70
+ cucumber --format debug features/outline.feature
71
+
72
+ A couple of problems become evident
73
+
74
+ 1. There are step definitions walked prior to the examples_array. These steps are not actually invoked rendering these hooks points misleading for profiling purposes
75
+ 2. There are only 3 table_cell element blocks. These can be profiled, but what about the last step that does not have an input from the examples? There are no hook points to profile this step.
76
+
77
+ This is why when you use the 'progress' formatter you would get 4 'skipped' for the initial step hooks triggered and then only 6 green dots representing steps when there should be 8 as it key's off table cells not steps.
78
+
79
+ Possible solutions
80
+
81
+ 1. Introduce new hook point for all true step invokations irregardless of context.
82
+ 2. Adjust table_cell hooks to include 'null' cells when considering steps without definitions.
83
+ 3. Include profile information in runtime master object to parse out at end.
84
+
85
+ As it turns out it was pretty simple to enhance the runtime object to reliably return profile information.
86
+
87
+ ## Contributing
88
+
89
+ 1. Fork it
90
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
91
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
92
+ 4. Push to the branch (`git push origin my-new-feature`)
93
+ 5. Create new Pull Request
94
+
95
+ ## Credits
96
+ 1. Ryan Boucher [cucumber_timing_presenter](https://github.com/distributedlife/cucumber_timing_presenter) for inspiration.
97
+ 2. AlienFast [cucumber_statistics](https://github.com/alienfast/cucumber_statistics) for inspriation.
98
+ 3. [Brandon Hilker](http://brandonhilkert.com/blog/ruby-gem-configuration-patterns/) for gem building tutorials
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cucumber_characteristics/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cucumber_characteristics"
8
+ spec.version = CucumberCharacteristics::VERSION
9
+ spec.authors = ["Stuart Ingram"]
10
+ spec.email = ["stuart.ingram@gmail.com"]
11
+ spec.description = %q{Gem to profile cucumber steps and features}
12
+ spec.summary = %q{Gem to profile cucumber steps and features}
13
+ spec.homepage = "https://github.com/singram/cucumber_characteristics"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "haml"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "awesome_print"
26
+ spec.add_development_dependency 'simplecov', '0.8.2'
27
+ spec.add_development_dependency 'rspec', '2.14'
28
+ spec.add_development_dependency 'cucumber', '1.3.5'
29
+ end
@@ -0,0 +1,6 @@
1
+ Feature: As a user I want to understand where my tests are spending their time in a scenaio with a pending step
2
+
3
+ Scenario: Timings for normal scenario
4
+ Given I wait 1 seconds
5
+ When I fail
6
+ Then I wait 1 seconds
@@ -0,0 +1,6 @@
1
+ Feature: As a user I want to understand where my tests are spending their time in a scenaio with a pending step
2
+
3
+ Scenario: Timings for normal scenario
4
+ Given I wait 1 seconds
5
+ When I call a pending step
6
+ Then I wait 1 seconds
@@ -0,0 +1,6 @@
1
+ Feature: As a user I want to understand where my tests are spending their time in a scenario
2
+
3
+ Scenario: Timings for normal scenario
4
+ Given I wait 1 seconds
5
+ When I wait 1 seconds
6
+ Then I wait 1 seconds
@@ -0,0 +1,11 @@
1
+ Feature: As a user I want to understand where my tests are spending their time in a scenario outline
2
+
3
+ Scenario Outline: Timings for scenario outline
4
+ Given I wait <given_wait> seconds
5
+ When I wait <when_wait> seconds
6
+ Then I wait <then_wait> seconds
7
+ And I wait 0.2 seconds
8
+ Examples:
9
+ | given_wait | when_wait | then_wait |
10
+ | 0.1 | 0.2 | 0.3 |
11
+ | 0.5 | 0.6 | 0.7 |
@@ -0,0 +1,14 @@
1
+ Feature: As a user I want to understand where my tests are spending their time in a scenario outline with a background
2
+
3
+ Background:
4
+ Given I wait 0.4 seconds
5
+
6
+ Scenario Outline: Timings for scenario outline
7
+ Given I wait <given_wait> seconds
8
+ When I wait <when_wait> seconds
9
+ Then I wait <then_wait> seconds
10
+ And I wait 0.2 seconds
11
+ Examples:
12
+ | given_wait | when_wait | then_wait |
13
+ | 0.1 | 0.2 | 0.3 |
14
+ | 0.5 | 0.6 | 0.7 |
@@ -0,0 +1,14 @@
1
+ Feature: As a user I want to understand where my tests are spending their time in a scenaio with a background
2
+
3
+ Background:
4
+ Given I wait 0.4 seconds
5
+
6
+ Scenario: Timings for normal scenario
7
+ Given I wait 0.1 seconds
8
+ When I wait 0.2 seconds
9
+ Then I wait 0.3 seconds
10
+
11
+ Scenario: Timings for another normal scenario
12
+ Given I wait 0.5 seconds
13
+ When I wait 0.6 seconds
14
+ Then I wait 0.7 seconds
@@ -0,0 +1,3 @@
1
+ Given(/^I fail$/) do
2
+ fail "Expected step failure"
3
+ end
@@ -0,0 +1,3 @@
1
+ Given(/^I wait ([\d\.]+) seconds$/) do |s|
2
+ sleep(s.to_f)
3
+ end
@@ -0,0 +1,3 @@
1
+ AfterConfiguration do |configuration|
2
+ configuration.options[:formats] << ['CucumberCharacteristics::Formatter', nil]
3
+ end
@@ -0,0 +1,35 @@
1
+ module CucumberCharacteristics
2
+
3
+ class Configuration
4
+
5
+ attr_accessor :export_json, :export_html, :target_filename, :relative_path
6
+
7
+ def initialize
8
+ @export_json = true
9
+ @export_html = true
10
+ @target_filename = 'cucumber_step_characteristics'
11
+ @relative_path = 'features/characteristics'
12
+ end
13
+
14
+ def full_target_filename
15
+ "#{full_dir}/#{@target_filename}"
16
+ end
17
+
18
+ def full_dir
19
+ dir = resolve_path_from_root @relative_path
20
+ FileUtils.mkdir_p dir unless File.exists? dir
21
+ dir
22
+ end
23
+
24
+ def resolve_path_from_root(rel_path)
25
+ if defined?(Rails)
26
+ Rails.root.join(rel_path)
27
+ elsif defined?(Rake.original_dir)
28
+ File.expand_path(rel_path, Rake.original_dir)
29
+ else
30
+ File.expand_path(rel_path, Dir.pwd)
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ #http://stackoverflow.com/questions/4470108/when-monkey-patching-a-method-can-you-call-the-overridden-method-from-the-new-i
2
+
3
+ module Cucumber
4
+ class StepMatch
5
+ old_invoke = instance_method(:invoke)
6
+ attr_reader :duration
7
+
8
+ define_method(:invoke) do | multiline_arg |
9
+ start_time = Time.now
10
+ ret = old_invoke.bind(self).(multiline_arg)
11
+ @duration = Time.now - start_time
12
+ ret
13
+ end
14
+ end
15
+ end
16
+
17
+
18
+ module Cucumber
19
+ module Ast
20
+ class StepInvocation
21
+ attr_reader :step_match
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,54 @@
1
+ require 'haml'
2
+
3
+ module CucumberCharacteristics
4
+
5
+ class Exporter
6
+
7
+ attr_reader :profile
8
+ def initialize(profile)
9
+ @profile = profile
10
+ @config = CucumberCharacteristics.configuration
11
+ end
12
+
13
+ def export
14
+ filename = @config.full_target_filename
15
+ if @config.export_html
16
+ File.open(filename+'.html', 'w') { |file| file.write(to_html) }
17
+ puts "Step characteristics report written to #{filename}.html"
18
+ end
19
+ if @config.export_json
20
+ File.open(filename+'.json', 'w') { |file| file.write(to_json) }
21
+ puts "Step characteristics report written to #{filename}.json"
22
+ end
23
+ end
24
+
25
+ def to_html
26
+ template = File.read(File.expand_path('../view/step_report.html.haml', __FILE__))
27
+ haml_engine = Haml::Engine.new(template)
28
+ haml_engine.render(self)
29
+ end
30
+
31
+ def to_json
32
+ @profile.step_profiles.to_json
33
+ end
34
+
35
+ # HELPERS
36
+
37
+ def format_ts(t)
38
+ t ? sprintf("%0.4f", t) : '-'
39
+ end
40
+
41
+ def format_step_usage(step_feature_data)
42
+ step_feature_data[:feature_location].map do |location, timings|
43
+ "#{location}" + (timings.count > 1 ? " (x#{timings.count})" : '')
44
+ end.join("\n")
45
+ end
46
+
47
+ def step_status_summary(profile)
48
+ status = profile.step_count_by_status
49
+ status.keys.sort.map{|s| status[s]> 0 ? "#{s.capitalize}: #{status[s]}" : nil}.compact.join(', ')
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,19 @@
1
+ module CucumberCharacteristics
2
+
3
+ class Formatter
4
+
5
+ def initialize(runtime, io, options)
6
+ @runtime = runtime
7
+ @io = io
8
+ @options = options
9
+ end
10
+
11
+ def after_features(features)
12
+ profile = ProfileData.new(@runtime, features)
13
+ Exporter.new(profile).export
14
+ end
15
+
16
+ end
17
+
18
+
19
+ end
@@ -0,0 +1,98 @@
1
+ module CucumberCharacteristics
2
+
3
+ class ProfileData
4
+
5
+ extend Forwardable
6
+
7
+ def_delegators :@runtime, :scenarios, :steps
8
+ attr_reader :duration
9
+
10
+ STATUS = [:passed, :failed, :skipped, :undefined ]
11
+
12
+ def initialize(runtime, features)
13
+ @runtime = runtime
14
+ @duration = features.duration
15
+ end
16
+
17
+ def step_profiles
18
+ #return @step_profiles if @step_profiles
19
+ step_profiles = {}
20
+ @runtime.steps.each do |s|
21
+ step_name = s.status == :undefined ? s.name : s.step_match.step_definition.file_colon_line
22
+ # Initialize data structure
23
+ step_profiles[step_name] ||= { :total_count => 0}
24
+ STATUS.each {|status| step_profiles[step_name][status] ||= {:count => 0, :feature_location => {} }}
25
+ feature_location = s.file_colon_line
26
+ step_profiles[step_name][s.status][:count] += 1
27
+ step_profiles[step_name][:total_count] += 1
28
+ step_profiles[step_name][s.status][:feature_location][feature_location] ||= []
29
+ if s.status != :undefined
30
+ step_profiles[step_name][:regexp] = s.step_match.step_definition.regexp_source
31
+ if s.status == :passed
32
+ step_profiles[step_name][s.status][:feature_location][feature_location] << s.step_match.duration
33
+ end
34
+ end
35
+ end
36
+ with_calculations(step_profiles)
37
+ end
38
+
39
+ def with_calculations(step_profiles)
40
+ step_profiles.each do |step, meta|
41
+ meta.merge!(fastest: nil, slowest: nil, average: nil, total_duration: nil, standard_deviation: nil, variation: nil)
42
+ next unless meta[:passed][:count] > 0
43
+ timings = []
44
+ STATUS.each do |status|
45
+ timings << meta[status][:feature_location].values
46
+ end
47
+ timings = timings.flatten.compact
48
+
49
+ step_profiles[step][:fastest] = timings.min
50
+ step_profiles[step][:slowest] = timings.max
51
+ step_profiles[step][:variation] = step_profiles[step][:slowest] - step_profiles[step][:fastest]
52
+ step_profiles[step][:total_duration] = timings.inject(:+)
53
+ step_profiles[step][:average] = step_profiles[step][:total_duration] / meta[:passed][:count]
54
+ sum = timings.inject(0){|accum, i| accum +(i-step_profiles[step][:average])**2 }
55
+ step_profiles[step][:variance] = sum/(timings.length ).to_f
56
+ step_profiles[step][:standard_deviation] = Math.sqrt( step_profiles[step][:variance])
57
+ end
58
+ step_profiles
59
+ end
60
+
61
+ def step_duration
62
+ step_duration = []
63
+ step_profiles.each do | step, meta |
64
+ STATUS.each do |status|
65
+ meta[status][:feature_location].each do | location, timings |
66
+ step_duration << timings
67
+ end
68
+ end
69
+ end
70
+ step_duration.flatten.compact.inject(:+)
71
+ end
72
+
73
+ def nonstep_duration
74
+ duration - step_duration
75
+ end
76
+
77
+ def step_count_by_status
78
+ status = {}
79
+ @runtime.steps.each do |s|
80
+ status[s.status] ||= 0
81
+ status[s.status] += 1
82
+ end
83
+ status
84
+ end
85
+
86
+ def scenario_count_by_status
87
+ status = {}
88
+ @runtime.scenarios.each do |s|
89
+ status[s.status] ||= 0
90
+ status[s.status] += 1
91
+ end
92
+ status
93
+ end
94
+
95
+ end
96
+
97
+
98
+ end
@@ -0,0 +1,3 @@
1
+ module CucumberCharacteristics
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,106 @@
1
+ !!!
2
+ %html{:lang => "en"}
3
+ %head
4
+ %meta{:charset => "utf-8"}/
5
+ %meta{:content => "IE=edge", "http-equiv" => "X-UA-Compatible"}/
6
+ %meta{:content => "width=device-width, initial-scale=1", :name => "viewport"}/
7
+ %meta{:content => "Cucumber Step Characteristics", :name => "description"}/
8
+ %title Cucumber Step Characteristics
9
+ %link{:href => "http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css", :rel => "stylesheet"}/
10
+ %link{:href => "http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css", :rel => "stylesheet"}/
11
+ / Custom styles for this layout
12
+ :css
13
+ body {
14
+ min-height: 2000px;
15
+ padding-top: 70px;
16
+ }
17
+
18
+ td {
19
+ white-space: nowrap;
20
+ }
21
+
22
+ table.tablesorter thead tr .headerSortUp {
23
+ background-color: #8dbdd8;
24
+ }
25
+ table.tablesorter thead tr .headerSortDown {
26
+ background-color: #8dbdd8;
27
+ }
28
+ / HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries
29
+ /[if lt IE 9]
30
+ <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
31
+ <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
32
+ %body
33
+ .container
34
+ .page-header
35
+ %h1 Cucumber step characteristics
36
+ .alert.alert-info
37
+ %span
38
+ #{profile.scenarios.count} Scenarios,
39
+ #{profile.steps.count} Steps completed
40
+ %span.text-muted
41
+ (#{step_status_summary(profile)})
42
+ <br>
43
+ Test duration #{format_ts(profile.duration)}s.
44
+ %span.text-muted
45
+ (#{format_ts(profile.step_duration)}s steps, #{format_ts(profile.nonstep_duration)}s non-steps)
46
+ %span.text-muted.pull-right.small
47
+ Finished on #{Time.now}
48
+
49
+ %table.table.table-striped.table-bordered.table-condensed.tablesorter#profile_table
50
+ %thead
51
+ %tr
52
+ %th Step
53
+ %th Total time
54
+ %th Passed
55
+ %th Average
56
+ %th Fastest
57
+ %th Slowest
58
+ %th Variation
59
+ %th Variance
60
+ %th Std Deviation
61
+ %th Skipped
62
+ %th Error
63
+ %th Undef
64
+ %th Total count
65
+ %tbody
66
+ - profile.step_profiles.each do |step, meta|
67
+ %tr
68
+ %td
69
+ %abbr{:title => "#{meta[:regexp]}"} #{step}
70
+ %td #{format_ts(meta[:total_duration])}
71
+ %td
72
+ - if meta[:passed][:count] > 0
73
+ %abbr{:title => "#{ format_step_usage(meta[:passed]) }" } #{meta[:passed][:count]}
74
+ - else
75
+ 0
76
+ %td #{format_ts(meta[:average])}
77
+ %td #{format_ts(meta[:fastest])}
78
+ %td #{format_ts(meta[:slowest])}
79
+ %td #{format_ts(meta[:variation])}
80
+ %td #{format_ts(meta[:variance])}
81
+ %td #{format_ts(meta[:standard_deviation])}
82
+ %td
83
+ - if meta[:skipped][:count] > 0
84
+ %abbr{:title => "#{ format_step_usage(meta[:skipped]) }" } #{meta[:skipped][:count]}
85
+ - else
86
+ 0
87
+ %td
88
+ - if meta[:failed][:count] > 0
89
+ %abbr{:title => "#{ format_step_usage(meta[:failed]) }" } #{meta[:failed][:count]}
90
+ - else
91
+ 0
92
+ %td
93
+ - if meta[:undefined][:count] > 0
94
+ %abbr{:title => "#{ format_step_usage(meta[:undefined]) }" } #{meta[:undefined][:count]}
95
+ - else
96
+ 0
97
+ %td #{meta[:total_count]}
98
+ %script{:src => "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"}
99
+ %script{:src => "http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"}
100
+ %script{:src => "https://raw.githubusercontent.com/christianbach/tablesorter/master/jquery.tablesorter.min.js"}
101
+ :javascript
102
+ $(document).ready(function()
103
+ {
104
+ $("#profile_table").tablesorter( {sortList: [[1,1],[3,1]], widgets: ['zebra']} );
105
+ }
106
+ );
@@ -0,0 +1,23 @@
1
+ require "cucumber_characteristics/configuration"
2
+ require "cucumber_characteristics/cucumber_step_patch"
3
+ require "cucumber_characteristics/exporter"
4
+ require "cucumber_characteristics/formatter"
5
+ require "cucumber_characteristics/profile_data"
6
+
7
+ module CucumberCharacteristics
8
+ class << self
9
+ attr_writer :configuration
10
+ end
11
+
12
+ def self.configuration
13
+ @configuration ||= Configuration.new
14
+ end
15
+
16
+ def self.reset
17
+ @configuration = Configuration.new
18
+ end
19
+
20
+ def self.configure
21
+ yield(configuration)
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cucumber_characteristics
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Stuart Ingram
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-06-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: haml
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.3'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.3'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: awesome_print
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: simplecov
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - '='
84
+ - !ruby/object:Gem::Version
85
+ version: 0.8.2
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - '='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.8.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - '='
100
+ - !ruby/object:Gem::Version
101
+ version: '2.14'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - '='
108
+ - !ruby/object:Gem::Version
109
+ version: '2.14'
110
+ - !ruby/object:Gem::Dependency
111
+ name: cucumber
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 1.3.5
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - '='
124
+ - !ruby/object:Gem::Version
125
+ version: 1.3.5
126
+ description: Gem to profile cucumber steps and features
127
+ email:
128
+ - stuart.ingram@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - Gemfile
135
+ - LICENSE.txt
136
+ - README.md
137
+ - Rakefile
138
+ - cucumber_characteristics.gemspec
139
+ - features/failure.feature
140
+ - features/pending.feature
141
+ - features/scenario.feature
142
+ - features/scenario_outline.feature
143
+ - features/scenario_outline_with_background.feature
144
+ - features/scenario_with_background.feature
145
+ - features/step_definitions/fail_steps.rb
146
+ - features/step_definitions/wait_steps.rb
147
+ - lib/cucumber_characteristics.rb
148
+ - lib/cucumber_characteristics/autoload.rb
149
+ - lib/cucumber_characteristics/configuration.rb
150
+ - lib/cucumber_characteristics/cucumber_step_patch.rb
151
+ - lib/cucumber_characteristics/exporter.rb
152
+ - lib/cucumber_characteristics/formatter.rb
153
+ - lib/cucumber_characteristics/profile_data.rb
154
+ - lib/cucumber_characteristics/version.rb
155
+ - lib/cucumber_characteristics/view/step_report.html.haml
156
+ homepage: https://github.com/singram/cucumber_characteristics
157
+ licenses:
158
+ - MIT
159
+ post_install_message:
160
+ rdoc_options: []
161
+ require_paths:
162
+ - lib
163
+ required_ruby_version: !ruby/object:Gem::Requirement
164
+ none: false
165
+ requirements:
166
+ - - ! '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ requirements: []
176
+ rubyforge_project:
177
+ rubygems_version: 1.8.24
178
+ signing_key:
179
+ specification_version: 3
180
+ summary: Gem to profile cucumber steps and features
181
+ test_files:
182
+ - features/failure.feature
183
+ - features/pending.feature
184
+ - features/scenario.feature
185
+ - features/scenario_outline.feature
186
+ - features/scenario_outline_with_background.feature
187
+ - features/scenario_with_background.feature
188
+ - features/step_definitions/fail_steps.rb
189
+ - features/step_definitions/wait_steps.rb