multicuke 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
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/results
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'cucumber'
4
+ gem 'rspec'
5
+ gem 'nokogiri'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 simcap
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,29 @@
1
+ # Multicuke
2
+
3
+ Run your cucumber test suite faster. Run one cucumber process per features directory.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'multicuke'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install multicuke
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/lib/multicuke.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "multicuke/version"
2
+ require "multicuke/runner"
3
+
4
+ module Multicuke
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,119 @@
1
+ require 'fileutils'
2
+ require 'builder'
3
+ require 'nokogiri'
4
+ require 'ostruct'
5
+
6
+ module Multicuke
7
+
8
+ class Runner
9
+
10
+ attr_accessor :features_dir_path
11
+ attr_accessor :output_dir_name
12
+ attr_accessor :output_path
13
+ attr_accessor :excluded_dirs, :reports_path, :dry_run
14
+
15
+ def initialize
16
+ yield self if block_given?
17
+
18
+ @dry_run = false if dry_run.nil?
19
+ @output_dir_name = "cucumber_reports" unless output_dir_name
20
+ @output_path = "" unless output_path
21
+ @excluded_dirs = [] unless excluded_dirs
22
+ @reports_path = File.join(output_path, output_dir_name)
23
+ end
24
+
25
+ def start
26
+ FileUtils.mkdir_p reports_path
27
+ index_file_path = File.join(reports_path, "index.html")
28
+ index_file = File.new(index_file_path, "w")
29
+
30
+ unless dry_run
31
+ features_group.each_key { |features_group_name|
32
+ report_file_path = File.join(reports_path, "#{features_group_name}.html")
33
+ feature_full_path = File.join(features_dir_path, "#{features_group_name}")
34
+ fork {
35
+ command = "bundle exec cucumber #{feature_full_path} -r #{features_dir_path} --format html --out #{report_file_path}"
36
+ p "RUNNING #{command}"
37
+ system command
38
+ }
39
+
40
+ p Process.waitall
41
+ }
42
+ end
43
+
44
+ features_group.each_key { |features_group_name|
45
+ feature_file = File.join(reports_path, "#{features_group_name}.html")
46
+ File.open(feature_file) { |file|
47
+ content = file.read
48
+ duration_match = content.match(/Finished in\s+<\w+>(.*?)</)
49
+ duration = duration_match ? duration_match.captures.first : ""
50
+ scenarios_match = content.match(/\d+ scenarios? \((.*?)\)/)
51
+ scenarios = scenarios_match ? scenarios_match.captures.first : ""
52
+ steps_match = content.match(/\d+ steps? \((.*?)\)/)
53
+ steps = steps_match ? steps_match.captures.first : ""
54
+ failed = (scenarios.include?"failed") || (steps.include?"failed")
55
+
56
+ features_group[features_group_name] = OpenStruct.new(:scenarios => scenarios, :steps => steps, :duration => duration, :failed? => failed)
57
+ } if File.exists?(feature_file)
58
+ }
59
+
60
+ b = Builder::XmlMarkup.new :target => index_file, :indent => 2
61
+ b.html {
62
+ b.head {
63
+ b.title("Cucumber reports")
64
+ b.style(css_content)
65
+ }
66
+ b.body {
67
+ b.h2("Features")
68
+ b.ul {
69
+ features_group.each { |name, feature|
70
+ b.li(:class => (feature.failed? ? "failed" : "success")) {
71
+ b.a(name, :href => "#{name}.html")
72
+ b.span("[#{feature.duration}]", :class => "duration")
73
+ b.span("Scenarios: #{feature.scenarios}, Steps: #{feature.steps}", :class => "result")
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ index_file.close
81
+ end
82
+
83
+ private
84
+
85
+ def css_content
86
+ <<-CSS
87
+ body {font-family: "Lucida Grande", Helvetica, sans-serif; margin: 2em 8em 2em 8em;}
88
+ ul {list-style-type: square;}
89
+ li {margin: 1em 0 1em 0;}
90
+ li span {float: right; margin-left: 1em; padding: 0 0.3em;}
91
+ li.failed span.result{background: #DC6E6E;}
92
+ li.success span.result{background: #C1E799;}
93
+ span.duration {color: #999999;}
94
+ CSS
95
+ end
96
+
97
+ def match_excluded_dirs(path)
98
+ path.match(Regexp.new(excluded_dirs.join("|")))
99
+ end
100
+
101
+ def features_group
102
+ @features_group ||= find_features_group
103
+ end
104
+
105
+ def find_features_group
106
+ @features_group = {}
107
+ Dir.glob(File.join(features_dir_path, "*")).reject{ |path|
108
+ File.file?(path) || match_excluded_dirs(path)
109
+ }.map { |feature_path|
110
+ File.basename(feature_path)
111
+ }.each { |feature_name|
112
+ @features_group[feature_name] = OpenStruct.new(:scenarios => nil, :steps => nil, :duration => nil, :failed? => false)
113
+ }
114
+ @features_group
115
+ end
116
+
117
+ end
118
+
119
+ end
@@ -0,0 +1,3 @@
1
+ module Multicuke
2
+ VERSION = "0.0.1"
3
+ end
data/multicuke.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/multicuke/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Simon Caplette"]
6
+ gem.description = %q{Run your features faster}
7
+ gem.summary = %q{Run one cucumber process per features directory}
8
+ gem.homepage = "https://github.com/simcap/multicuke"
9
+
10
+ gem.files = `git ls-files`.split($\)
11
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
12
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
+ gem.name = "multicuke"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = Multicuke::VERSION
16
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ module Multicuke
4
+
5
+ describe "Reporting" do
6
+
7
+ after(:each) do
8
+ FileUtils.rm_r(Dir.glob("#{RESULTS_DIR_PATH}/*"), :force => true)
9
+ end
10
+
11
+ it "generates index file in output folder" do
12
+ runner = Multicuke::Runner.new do |r|
13
+ r.features_dir_path = File.expand_path("../features", __FILE__)
14
+ r.output_dir_name = "cuke_reports"
15
+ r.dry_run = true
16
+ r.output_path = RESULTS_DIR_PATH
17
+ end
18
+
19
+ File.should_not exist("#{RESULTS_DIR_PATH}/cuke_reports")
20
+
21
+ runner.start
22
+
23
+ File.should exist("#{RESULTS_DIR_PATH}/cuke_reports/index.html")
24
+ end
25
+
26
+ it "write link to each features on index file" do
27
+ runner = Multicuke::Runner.new do |r|
28
+ r.features_dir_path = File.expand_path("../features", __FILE__)
29
+ r.excluded_dirs = ["steps_definition"]
30
+ r.dry_run = true
31
+ r.output_path = RESULTS_DIR_PATH
32
+ end
33
+
34
+ runner.start
35
+
36
+ File.open("#{RESULTS_DIR_PATH}/cucumber_reports/index.html") { |file|
37
+ content = file.read
38
+ content.should match /.*Cucumber reports.*/
39
+ content.should match /.*<a href="addition.html">addition<\/a>.*/
40
+ content.should match /.*<a href="substraction.html">substraction<\/a>.*/
41
+ content.should match /.*<a href="division.html">division<\/a>.*/
42
+ content.should match /.*<a href="multiplication.html">multiplication<\/a>.*/
43
+ content.should_not match /.*steps_definition.*/
44
+ }
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,7 @@
1
+ Feature: Addition
2
+
3
+ Scenario: Add 2 numbers
4
+ Given a first number 1
5
+ And a second number 2
6
+ When I add them
7
+ Then I get 3
@@ -0,0 +1,7 @@
1
+ Feature: Addition going wrong
2
+
3
+ Scenario: Add 2 numbers
4
+ Given a first number 1
5
+ And a second number 2
6
+ When I add them
7
+ Then I get 4
@@ -0,0 +1,7 @@
1
+ Feature: Division
2
+
3
+ Scenario: Divide 2 numbers
4
+ Given a first number 10
5
+ And a second number 2
6
+ When I divide them
7
+ Then I get 5
@@ -0,0 +1 @@
1
+ Feature: Empty feature
@@ -0,0 +1,7 @@
1
+ Feature: Multiplication
2
+
3
+ Scenario: Multiply 2 numbers
4
+ Given a first number 3
5
+ And a second number 4
6
+ When I multiply them
7
+ Then I get 12
@@ -0,0 +1 @@
1
+ # random file to pollute entries
@@ -0,0 +1,27 @@
1
+ Given(/^a first number (\d+)$/) do |first_number|
2
+ @first_operand = first_number.to_i
3
+ end
4
+
5
+ Given(/^a second number (\d+)$/) do |second_number|
6
+ @second_operand = second_number.to_i
7
+ end
8
+
9
+ When(/^I add them$/) do
10
+ @result = @first_operand + @second_operand
11
+ end
12
+
13
+ When(/^I divide them$/) do
14
+ @result = @first_operand / @second_operand
15
+ end
16
+
17
+ When(/^I multiply them$/) do
18
+ @result = @first_operand * @second_operand
19
+ end
20
+
21
+ When(/^I substract them$/) do
22
+ @result = @first_operand - @second_operand
23
+ end
24
+
25
+ Then(/^I get (\d+)$/) do |expected_result|
26
+ expected_result.to_i.should == @result
27
+ end
@@ -0,0 +1,7 @@
1
+ Feature: Substraction
2
+
3
+ Scenario: Substract 2 numbers
4
+ Given a first number 3
5
+ And a second number 1
6
+ When I substract them
7
+ Then I get 2
data/spec/fork_spec.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ module Multicuke
4
+
5
+ describe "Forking" do
6
+
7
+ it "generates test results files" do
8
+ runner = Multicuke::Runner.new do |r|
9
+ r.features_dir_path = File.expand_path("../features", __FILE__)
10
+ r.excluded_dirs = ["steps_definition"]
11
+ r.output_path = RESULTS_DIR_PATH
12
+ end
13
+
14
+ runner.start
15
+
16
+ File.should exist("#{RESULTS_DIR_PATH}/cucumber_reports/addition.html")
17
+ File.should exist("#{RESULTS_DIR_PATH}/cucumber_reports/division.html")
18
+ File.should exist("#{RESULTS_DIR_PATH}/cucumber_reports/multiplication.html")
19
+ File.should exist("#{RESULTS_DIR_PATH}/cucumber_reports/substraction.html")
20
+
21
+ File.open("#{RESULTS_DIR_PATH}/cucumber_reports/index.html") { |file|
22
+ content = file.read
23
+ content.should match /.*Scenarios: 1 failed, Steps: 1 failed, 3 passed.*/i
24
+ }
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Multicuke
4
+
5
+ describe Runner do
6
+ it "initializes with provided configuration" do
7
+ runner = Multicuke::Runner.new do |r|
8
+ r.features_dir_path = "my_feature_path"
9
+ r.output_dir_name = "my_reports"
10
+ r.output_path = "my_output_path"
11
+ r.dry_run = true
12
+ r.excluded_dirs = ["my_first_dir", "my_second_dir"]
13
+ end
14
+
15
+ runner.features_dir_path.should == "my_feature_path"
16
+ runner.output_dir_name.should == "my_reports"
17
+ runner.output_path.should == "my_output_path"
18
+ runner.dry_run.should be_true
19
+ runner.reports_path.should == "my_output_path/my_reports"
20
+ runner.excluded_dirs.should include("my_first_dir", "my_second_dir")
21
+ end
22
+
23
+ it "initializes with default values" do
24
+ runner = Multicuke::Runner.new
25
+
26
+ runner.output_dir_name.should == "cucumber_reports"
27
+ runner.output_path.should == ""
28
+ runner.dry_run.should be_false
29
+ runner.excluded_dirs.should be_empty
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path '../../lib/multicuke', __FILE__
2
+ require 'fileutils'
3
+
4
+ RESULTS_DIR_PATH = File.expand_path '../results', __FILE__
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multicuke
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Simon Caplette
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-30 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Run your features faster
15
+ email:
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - Gemfile
22
+ - LICENSE
23
+ - README.md
24
+ - Rakefile
25
+ - lib/multicuke.rb
26
+ - lib/multicuke/runner.rb
27
+ - lib/multicuke/version.rb
28
+ - multicuke.gemspec
29
+ - spec/dryrun_spec.rb
30
+ - spec/features/addition/add_numbers.feature
31
+ - spec/features/bad_addition/bad_addition.feature
32
+ - spec/features/division/divide_numbers.feature
33
+ - spec/features/empty/empty_file.feature
34
+ - spec/features/multiplication/multiply_numbers.feature
35
+ - spec/features/random_file.rb
36
+ - spec/features/steps_definition/step_definitions.rb
37
+ - spec/features/substraction/substract_numbers.feature
38
+ - spec/fork_spec.rb
39
+ - spec/runner_spec.rb
40
+ - spec/spec_helper.rb
41
+ homepage: https://github.com/simcap/multicuke
42
+ licenses: []
43
+ post_install_message:
44
+ rdoc_options: []
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 1.8.24
62
+ signing_key:
63
+ specification_version: 3
64
+ summary: Run one cucumber process per features directory
65
+ test_files:
66
+ - spec/dryrun_spec.rb
67
+ - spec/features/addition/add_numbers.feature
68
+ - spec/features/bad_addition/bad_addition.feature
69
+ - spec/features/division/divide_numbers.feature
70
+ - spec/features/empty/empty_file.feature
71
+ - spec/features/multiplication/multiply_numbers.feature
72
+ - spec/features/random_file.rb
73
+ - spec/features/steps_definition/step_definitions.rb
74
+ - spec/features/substraction/substract_numbers.feature
75
+ - spec/fork_spec.rb
76
+ - spec/runner_spec.rb
77
+ - spec/spec_helper.rb
78
+ has_rdoc: