cuke_slicer 1.0.0 → 2.0.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.
@@ -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