cuke_slicer 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.2
6
+
7
+ script: bundle exec rake cuke_slicer:ci_build
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in cuke_slicer.gemspec
4
4
  gemspec
5
+
6
+ gem 'coveralls', require: false, :group => :development
@@ -0,0 +1,11 @@
1
+ === Version 2.0.0 / 2015-07-08
2
+
3
+ * When slicing a directory, the test cases returned can now be provided as model objects in addition to the
4
+ previous 'file_path:line_number' format.
5
+
6
+ * Major performance increase
7
+
8
+
9
+ === Version 1.0.0 / 2015-04-01
10
+
11
+ * Initial release
data/README.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # CukeSlicer
2
2
 
3
+ <a href="http://badge.fury.io/rb/cuke_slicer"><img src="https://badge.fury.io/rb/cuke_slicer.svg" alt="Gem Version"></a>
4
+
5
+ <a href='https://gemnasium.com/grange-insurance/cuke_slicer'><img src="https://gemnasium.com/grange-insurance/cuke_slicer.svg" alt="Dependency Status" /></a>
6
+
7
+ <a href='https://github.com/grange-insurance/cuke_slicer/blob/master/LICENSE.txt'><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Project License" /></a>
8
+
9
+ <a href="https://travis-ci.org/grange-insurance/cuke_slicer"><img src="https://travis-ci.org/grange-insurance/cuke_slicer.svg" alt="Build Status"></a>
10
+
11
+ <a href='https://coveralls.io/r/grange-insurance/cuke_slicer'><img src='https://coveralls.io/repos/grange-insurance/cuke_slicer/badge.svg' alt='Coverage Status' /></a>
12
+
13
+ <a href="https://codeclimate.com/github/grange-insurance/cuke_slicer"><img src="https://codeclimate.com/github/grange-insurance/cuke_slicer/badges/gpa.svg" alt="Code Quality" /></a>
14
+
15
+
3
16
  The cuke_slicer gem provides an easy and programmatic way to divide a Cucumber test suite into granular test
4
17
  cases that can then be dealt with on an individual basis. Often this means handing them off to a distributed
5
18
  testing system in order to parallelize test execution.
@@ -33,7 +46,7 @@ Or install it yourself as:
33
46
  included_paths: [/test_directory/]}
34
47
 
35
48
  # Use the slicer to find all tests matching those filters
36
- found_tests = CukeSlicer::Slicer.new.slice(test_directory, filters)
49
+ found_tests = CukeSlicer::Slicer.new.slice(test_directory, filters, :file_line)
37
50
 
38
51
 
39
52
  # Arrange the sliced pieces to suit your particular needs. In this case, we will dump them
data/Rakefile CHANGED
@@ -1,49 +1,53 @@
1
- require "bundler/gem_tasks"
2
- require 'cucumber/rake/task'
3
- require 'rspec/core/rake_task'
4
-
5
-
6
- def set_cucumber_options(options)
7
- ENV['CUCUMBER_OPTS'] = options
8
- end
9
-
10
- def combine_options(set_1, set_2)
11
- set_2 ? "#{set_1} #{set_2}" : set_1
12
- end
13
-
14
-
15
- namespace 'cuke_slicer' do
16
-
17
- task :clear_coverage do
18
- puts 'Clearing old code coverage results...'
19
-
20
- # Remove previous coverage results so that they don't get merged in the new results
21
- code_coverage_directory = File.join(File.dirname(__FILE__), 'coverage')
22
- FileUtils.remove_dir(code_coverage_directory, true) if File.exists?(code_coverage_directory)
23
- end
24
-
25
- namespace 'cucumber' do
26
- desc 'Run all Cucumber tests for the gem'
27
- task :tests, [:command_options] do |t, args|
28
- set_cucumber_options(combine_options('-t ~@wip -t ~@off', args[:command_options]))
29
- end
30
- Cucumber::Rake::Task.new(:tests)
31
- end
32
-
33
- namespace 'rspec' do
34
- desc 'Run all RSpec tests for the gem'
35
- RSpec::Core::RakeTask.new(:specs, :command_options) do |t, args|
36
- t.rspec_opts = combine_options('--tag ~wip', args[:command_options])
37
- end
38
- end
39
-
40
- desc 'Run all tests for the gem'
41
- task :test_everything, [:command_options] => :clear_coverage do |t, args|
42
- Rake::Task['cuke_slicer:rspec:specs'].invoke(args[:command_options])
43
- Rake::Task['cuke_slicer:cucumber:tests'].invoke(args[:command_options])
44
- end
45
-
46
- end
47
-
48
-
49
- task :default => 'cuke_slicer:test_everything'
1
+ require "bundler/gem_tasks"
2
+ require 'cucumber/rake/task'
3
+ require 'rspec/core/rake_task'
4
+ require 'coveralls/rake/task'
5
+
6
+
7
+ def set_cucumber_options(options)
8
+ ENV['CUCUMBER_OPTS'] = options
9
+ end
10
+
11
+ def combine_options(set_1, set_2)
12
+ set_2 ? "#{set_1} #{set_2}" : set_1
13
+ end
14
+
15
+
16
+ namespace 'cuke_slicer' do
17
+
18
+ task :clear_coverage do
19
+ puts 'Clearing old code coverage results...'
20
+
21
+ # Remove previous coverage results so that they don't get merged in the new results
22
+ code_coverage_directory = File.join(File.dirname(__FILE__), 'coverage')
23
+ FileUtils.remove_dir(code_coverage_directory, true) if File.exists?(code_coverage_directory)
24
+ end
25
+
26
+ namespace 'cucumber' do
27
+ desc 'Run all Cucumber tests for the gem'
28
+ task :tests, [:command_options] do |t, args|
29
+ set_cucumber_options(combine_options('-t ~@wip -t ~@off', args[:command_options]))
30
+ end
31
+ Cucumber::Rake::Task.new(:tests)
32
+ end
33
+
34
+ namespace 'rspec' do
35
+ desc 'Run all RSpec tests for the gem'
36
+ RSpec::Core::RakeTask.new(:specs, :command_options) do |t, args|
37
+ t.rspec_opts = combine_options('--tag ~wip', args[:command_options])
38
+ end
39
+ end
40
+
41
+ desc 'Run all tests for the gem'
42
+ task :test_everything, [:command_options] => :clear_coverage do |t, args|
43
+ Rake::Task['cuke_slicer:rspec:specs'].invoke(args[:command_options])
44
+ Rake::Task['cuke_slicer:cucumber:tests'].invoke(args[:command_options])
45
+ end
46
+
47
+ Coveralls::RakeTask.new
48
+ task :ci_build => [:clear_coverage, :test_everything, 'coveralls:push']
49
+
50
+ end
51
+
52
+
53
+ task :default => 'cuke_slicer:test_everything'
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["morrow748@gmail.com"]
11
11
  spec.summary = %q{A gem for extracting test cases from a Cucumber test suite.}
12
12
  spec.description = spec.summary
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/grange-insurance/cuke_slicer"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -7,16 +7,17 @@ When(/^test cases are extracted from "([^"]*)"$/) do |target|
7
7
  filters[:excluded_paths] = @excluded_path_filters if @excluded_path_filters
8
8
  filters[:included_paths] = @included_path_filters if @included_path_filters
9
9
 
10
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", filters, &@custom_filter)
10
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", filters, :file_line, &@custom_filter)
11
11
  end
12
12
 
13
13
  When(/^test cases are extracted from it$/) do
14
14
  @output ||= {}
15
15
  filters = {}
16
16
  target = @targets.first
17
+ @output_type ||= :file_line
17
18
 
18
19
  begin
19
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", filters)
20
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", filters, @output_type)
20
21
  rescue ArgumentError => e
21
22
  @error_raised = e
22
23
  end
@@ -27,7 +28,7 @@ When(/^test cases are extracted from them$/) do
27
28
  filters = {}
28
29
 
29
30
  @targets.each do |target|
30
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", filters)
31
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", filters, :file_line)
31
32
  end
32
33
  end
33
34
 
@@ -37,7 +38,7 @@ When(/^test cases are extracted from "([^"]*)" using the following exclusive tag
37
38
 
38
39
  options[:excluded_tags] = filters.raw.flatten.collect { |filter| process_filter(filter) }
39
40
 
40
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options)
41
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options, :file_line)
41
42
  end
42
43
 
43
44
  When(/^test cases are extracted from "([^"]*)" using the following inclusive tag filters:$/) do |target, filters|
@@ -46,7 +47,7 @@ When(/^test cases are extracted from "([^"]*)" using the following inclusive tag
46
47
 
47
48
  options[:included_tags] = filters.raw.flatten.collect { |filter| process_filter(filter) }
48
49
 
49
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options)
50
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options, :file_line)
50
51
  end
51
52
 
52
53
  When(/^test cases are extracted from "([^"]*)" using the following inclusive path filters:$/) do |target, filters|
@@ -55,7 +56,7 @@ When(/^test cases are extracted from "([^"]*)" using the following inclusive pat
55
56
 
56
57
  options[:included_paths] = filters.raw.flatten.collect { |filter| process_filter(filter) }
57
58
 
58
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options)
59
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options, :file_line)
59
60
  end
60
61
 
61
62
  When(/^test cases are extracted from "([^"]*)" using the following exclusive path filters:$/) do |target, filters|
@@ -64,7 +65,7 @@ When(/^test cases are extracted from "([^"]*)" using the following exclusive pat
64
65
 
65
66
  options[:excluded_paths] = filters.raw.flatten.collect { |filter| process_filter(filter) }
66
67
 
67
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options)
68
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options, :file_line)
68
69
  end
69
70
 
70
71
  When(/^test cases are extracted from "([^"]*)" using the following custom filter:$/) do |target, filter_block|
@@ -72,7 +73,7 @@ When(/^test cases are extracted from "([^"]*)" using the following custom filter
72
73
 
73
74
  custom_filter = eval("Proc.new #{filter_block}")
74
75
 
75
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", &custom_filter)
76
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", :file_line, &custom_filter)
76
77
  end
77
78
 
78
79
  When(/^test cases are extracted from "([^"]*)" using "([^"]*)"$/) do |target, included_tag_filters|
@@ -81,7 +82,7 @@ When(/^test cases are extracted from "([^"]*)" using "([^"]*)"$/) do |target, in
81
82
 
82
83
  options[:included_tags] = eval("[#{included_tag_filters}]")
83
84
 
84
- @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options)
85
+ @output[target] = CukeSlicer::Slicer.new.slice("#{@default_file_directory}/#{target}", options, :file_line)
85
86
  end
86
87
 
87
88
  def process_filter(filter)
@@ -91,7 +92,7 @@ end
91
92
 
92
93
  When(/^it tries to extract test cases using an unknown filter type$/) do
93
94
  begin
94
- @slicer.slice(@default_file_directory, {unknown_filter: 'foo'})
95
+ @slicer.slice(@default_file_directory, {unknown_filter: 'foo'}, :file_line)
95
96
  rescue ArgumentError => e
96
97
  @error_raised = e
97
98
  end
@@ -99,7 +100,7 @@ end
99
100
 
100
101
  When(/^it tries to extract test cases using an invalid filter$/) do
101
102
  begin
102
- @slicer.slice(@default_file_directory, {included_tags: 7})
103
+ @slicer.slice(@default_file_directory, {included_tags: 7}, :file_line)
103
104
  rescue ArgumentError => e
104
105
  @error_raised = e
105
106
  end
@@ -77,3 +77,27 @@ end
77
77
  Given(/^a slicer$/) do
78
78
  @slicer = CukeSlicer::Slicer.new
79
79
  end
80
+
81
+ And(/^the test cases are to be extracted as objects$/) do
82
+ @output_type = :test_object
83
+ end
84
+
85
+ And(/^an invalid output option$/) do
86
+ @output_type = :invalid_option
87
+ end
88
+
89
+ Given(/^a test suite to extract from$/) do
90
+ @test_directory ||= @default_file_directory
91
+
92
+ @targets ||= []
93
+ @targets << @default_feature_file_name
94
+
95
+
96
+ test_suite = "Feature: Test feature
97
+
98
+ @tag
99
+ Scenario: Test scenario
100
+ * some step"
101
+
102
+ File.write("#{@test_directory}/#{@default_feature_file_name}", test_suite)
103
+ end
@@ -45,3 +45,14 @@ Then(/^an error indicating that the filter is invalid will be triggered$/) do
45
45
  expect(@error_raised).to_not be_nil
46
46
  expect(@error_raised.message).to match(/invalid filter/i)
47
47
  end
48
+
49
+ Then(/^the test cases are provided as objects$/) do
50
+ @output.values.flatten.each do |output|
51
+ expect(output).to be_a(CukeModeler::Scenario).or be_a(CukeModeler::Row)
52
+ end
53
+ end
54
+
55
+ Then(/^an error indicating that the output type is invalid will be triggered$/) do
56
+ expect(@error_raised).to_not be_nil
57
+ expect(@error_raised.message).to match(/Invalid Output Format/i)
58
+ end
@@ -1,6 +1,6 @@
1
1
  Feature: Test case extraction
2
2
 
3
- Test cases can be extracted from a source file or directory as a collection of 'file:line' items that
3
+ Test cases can be extracted from a source file or directory as a collection of 'file:line' items or objects that
4
4
  can then be conveniently arranged for consumption by some other tool (e.g. Cucumber).
5
5
 
6
6
 
@@ -76,3 +76,9 @@ Feature: Test case extraction
76
76
  And the directory "test_directory/empty_directory"
77
77
  When test cases are extracted from "test_directory"
78
78
  Then no test cases are found
79
+
80
+ Scenario: Extracting objects
81
+ Given a test suite to extract from
82
+ And the test cases are to be extracted as objects
83
+ When test cases are extracted from it
84
+ Then the test cases are provided as objects
@@ -54,3 +54,9 @@ Feature: Validation
54
54
  When test cases are extracted from "test_directory"
55
55
  Then the following test cases are found
56
56
  | path/to/test_directory/a_test.feature:3 |
57
+
58
+ Scenario: Invalid output type are not allowed
59
+ Given a test suite to extract from
60
+ And an invalid output option
61
+ When test cases are extracted from it
62
+ Then an error indicating that the output type is invalid will be triggered
@@ -1,10 +1,10 @@
1
- require 'cuke_modeler'
2
-
3
- require "cuke_slicer/version"
4
- require "cuke_slicer/slicer"
5
-
6
-
7
- # Top level module under which the gem code lives.
8
- module CukeSlicer
9
- # Your code goes here...
10
- end
1
+ require 'cuke_modeler'
2
+
3
+ require "cuke_slicer/version"
4
+ require "cuke_slicer/slicer"
5
+
6
+
7
+ # Top level module under which the gem code lives.
8
+ module CukeSlicer
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,27 @@
1
+ require "cuke_slicer/helpers/helpers"
2
+
3
+
4
+ module CukeSlicer
5
+ class NestedTagCollection
6
+
7
+ include Helpers
8
+
9
+
10
+ def initialize collection
11
+ self.nested_collection = collection
12
+ end
13
+
14
+ def validate
15
+ nested_collection.each do |element|
16
+ raise(ArgumentError, "Tag filters cannot be nested more than one level deep.") if element.is_a?(Array)
17
+ raise(ArgumentError, "Filter '#{element}' must be a String or Regexp. Got #{element.class}") unless str_regex?(element)
18
+ end
19
+ end
20
+
21
+
22
+ private
23
+
24
+ attr_accessor :nested_collection
25
+
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ require "cuke_slicer/helpers/helpers"
2
+
3
+
4
+ module CukeSlicer
5
+ class PathCollection
6
+
7
+ include Helpers
8
+
9
+
10
+ def initialize filter_values
11
+ self.filter_values = filter_values
12
+ end
13
+
14
+ def validate
15
+ filter_values.each do |val|
16
+ raise(ArgumentError, "Filter '#{val}' must be a String or Regexp. Got #{val.class}") unless str_regex?(val)
17
+ end
18
+ end
19
+
20
+
21
+ private
22
+
23
+ attr_accessor :filter_values
24
+
25
+ end
26
+ end
@@ -0,0 +1,28 @@
1
+ require "cuke_slicer/helpers/helpers"
2
+ require "cuke_slicer/collections/nested_tag_collection"
3
+
4
+
5
+ module CukeSlicer
6
+ class TagCollection
7
+
8
+ include Helpers
9
+
10
+
11
+ def initialize parameters
12
+ self.filter_values = parameters
13
+ end
14
+
15
+ def validate
16
+ filter_values.each do |val|
17
+ raise(ArgumentError, "Filter '#{val}' must be a String, Regexp, or Array. Got #{val.class}") unless str_regex_arr?(val)
18
+ NestedTagCollection.new(val).validate if val.is_a?(Array)
19
+ end
20
+ end
21
+
22
+
23
+ private
24
+
25
+ attr_accessor :filter_values
26
+
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module CukeSlicer
2
+ class DirectoryExtractor
3
+
4
+ def extract(target, filters, format, &block)
5
+ Array.new.tap do |test_cases|
6
+ target.feature_files.each do |feature_file|
7
+ test_cases.concat(FileExtractor.new.extract(feature_file, filters, format, &block))
8
+ end
9
+
10
+ target.directories.each do |directory|
11
+ test_cases.concat(extract(directory, filters, format, &block))
12
+ end
13
+ end
14
+ end
15
+
16
+ end
17
+ end