cuke_iterations 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source "http://rubygems.org"
3
3
  group :development do
4
4
  gem 'rake', '>= 0.9.2'
5
5
  gem 'rspec'
6
- gem 'rspec-expectations', :git => "git://github.com/rspec/rspec-expectations.git"
6
+ gem 'rspec-expectations'
7
7
  end
8
8
 
9
9
  gemspec
@@ -1,30 +1,25 @@
1
- GIT
2
- remote: git://github.com/rspec/rspec-expectations.git
3
- revision: 0b63bf446ce84a613875417121980492571bfa90
4
- specs:
5
- rspec-expectations (2.6.0)
6
- diff-lcs (~> 1.1.2)
7
-
8
1
  PATH
9
2
  remote: .
10
3
  specs:
11
- cuke_iterations (0.0.1)
4
+ cuke_iterations (0.0.2)
12
5
  gherkin
13
6
 
14
7
  GEM
15
8
  remote: http://rubygems.org/
16
9
  specs:
17
- diff-lcs (1.1.2)
18
- gherkin (2.4.11)
10
+ diff-lcs (1.1.3)
11
+ gherkin (2.7.6)
19
12
  json (>= 1.4.6)
20
- json (1.5.3)
21
- rake (0.9.2)
22
- rspec (2.6.0)
23
- rspec-core (~> 2.6.0)
24
- rspec-expectations (~> 2.6.0)
25
- rspec-mocks (~> 2.6.0)
26
- rspec-core (2.6.4)
27
- rspec-mocks (2.6.0)
13
+ json (1.6.5)
14
+ rake (0.9.2.2)
15
+ rspec (2.8.0)
16
+ rspec-core (~> 2.8.0)
17
+ rspec-expectations (~> 2.8.0)
18
+ rspec-mocks (~> 2.8.0)
19
+ rspec-core (2.8.0)
20
+ rspec-expectations (2.8.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.8.0)
28
23
 
29
24
  PLATFORMS
30
25
  ruby
@@ -33,4 +28,4 @@ DEPENDENCIES
33
28
  cuke_iterations!
34
29
  rake (>= 0.9.2)
35
30
  rspec
36
- rspec-expectations!
31
+ rspec-expectations
data/README.md CHANGED
@@ -48,12 +48,10 @@ android:
48
48
  - ! '@iphone_only'
49
49
  ```
50
50
 
51
- At present, you *must* specify all tags that are to be included. Excluded tags have priority over included ones (e.g. an `@iphone_only` scenario would not be included in the `android` iteration, even if it had the `@mobile` tag.
51
+ If you specify an empty array for `include_tags`, then all scenarios will be included. Excluded tags have priority over included ones (e.g. an `@iphone_only` scenario would not be included in the `android` iteration, even if it had the `@mobile` tag.
52
52
 
53
53
  ### Running it
54
54
 
55
- `cd features`
56
-
57
55
  With defaults:
58
56
  `cuke_iterations`
59
57
 
@@ -62,7 +60,7 @@ To see other options:
62
60
 
63
61
  ### What did it do?
64
62
 
65
- First, it created a set of empty directories under the `iterations` folder - one for each iteration that you defined. You should add this folder to your source-control ignore list (unless you're using Git which doesn't track empty folders).
63
+ First, it created a set of empty directories under the `iterations` folder inside your features folder - one for each iteration that you defined. You should add this folder to your source-control ignore list (unless you're using Git which doesn't track empty folders).
66
64
 
67
65
  Next, it created a run file for Cucumber. If you didn't specify a filename it will be called `run.txt`. Definitely add this to your source-control ignore list.
68
66
 
@@ -70,7 +68,7 @@ Next, it created a run file for Cucumber. If you didn't specify a filename it w
70
68
 
71
69
  `cucumber @run.txt`
72
70
 
73
- Note we haven't told Cucumber about our `features` folder like we normally would. This also means it doesn't know about your `support` or `step_definitions` folders, so make sure to add those to the command-line as well.
71
+ Note we haven't told Cucumber about our `features` folder like we normally would. If you're not using the conventional Cucumber folder structure, then you will need to explicitly require your `support` and `step_definitions` folders.
74
72
 
75
73
  ### Use the iterations inside your scenarios
76
74
 
@@ -5,23 +5,18 @@ require 'cuke_iterations'
5
5
  require 'trollop'
6
6
  require 'fileutils'
7
7
 
8
+ include CukeIterations
9
+
8
10
  opts = Trollop::options do
11
+ opt :features_dir, "Features directory", :default => 'features'
9
12
  opt :iteration_file, "Iterations file to use", :default => 'cuke_iterations.yml'
10
13
  opt :out, "Name of runfile to write", :default => 'run.txt'
11
14
  end
12
15
 
13
- Trollop::die "Couldn't find iterations file '#{opts[:iteration_file]}'" unless File.exist?(opts[:iteration_file])
14
- iterations = YAML.load(File.read(opts[:iteration_file]))
16
+ features_dir = opts[:features_dir]
17
+ Trollop::die "Couldn't find features dir '#{features_dir}'" unless Dir.exist?(features_dir)
15
18
 
16
- all_scenarios = []
17
- features = CukeIterations::CukeParser.parse_features(Dir.getwd)
18
- iterations.each do |iteration_name, iteration|
19
- iteration_dir = File.join('iterations', iteration_name, '..', '..')
20
- FileUtils.mkdir_p iteration_dir
19
+ iteration_file = IterationFileFinder.new.find(features_dir, opts[:iteration_file])
21
20
 
22
- CukeIterations::ScenarioListGenerator.for_iteration(features, iteration).each do |scenario|
23
- all_scenarios << File.join(iteration_dir, scenario[:filename] + ":#{scenario[:line]}")
24
- end
25
- end
21
+ ScenarioFileWriter.new.write_scenarios(features_dir, iteration_file, opts[:out])
26
22
 
27
- File.open(opts[:out], 'w') {|f| f.puts all_scenarios}
@@ -0,0 +1,7 @@
1
+ ## [v0.0.2](https://github.com/jmerrifield/cuke_iterations/compare/v0.0.1...v0.0.2)
2
+
3
+ * Deal with feature files that live in subdirectories of the `features` folder ([#1](https://github.com/jmerrifield/cuke_iterations/issues/1))
4
+ * Default to including all tags if none are specified ([#2](https://github.com/jmerrifield/cuke_iterations/issues/2))
5
+ * Don't require that we run from inside `features`, assume we're at the root and look for features in `features`, unless overridden by the `-f` parameter.
6
+
7
+ ## [v0.0.1](https://github.com/jmerrifield/cuke_iterations/tree/v0.0.1)
@@ -1,7 +1,11 @@
1
1
  $:.push File.expand_path("../cuke_iterations", __FILE__)
2
2
 
3
+ require 'fileutils'
4
+
3
5
  require 'version'
6
+ require 'cucumber_helper'
4
7
  require 'cuke_parser'
8
+ require 'iteration_file_finder'
5
9
  require 'scenario_extracting_formatter'
10
+ require 'scenario_file_writer'
6
11
  require 'scenario_list_generator'
7
- require 'cucumber_helper'
@@ -1,4 +1,5 @@
1
1
  require 'gherkin'
2
+ require 'pathname'
2
3
 
3
4
  module CukeIterations
4
5
  class CukeParser
@@ -11,11 +12,16 @@ module CukeIterations
11
12
  text = File.open(feature_file, 'r') { |f| f.read }
12
13
  parser.parse(text, __FILE__, __LINE__-1)
13
14
 
14
- scenarios << formatter.discovered_scenarios.each {|s| s[:filename] = File.basename(feature_file)}
15
+ scenarios << formatter.discovered_scenarios.each {|s| s[:filename] = relative_path(feature_file, dir)}
15
16
  end
16
17
 
17
18
  scenarios.flatten
18
19
  end
20
+
21
+ private
22
+ def relative_path(file, base_dir)
23
+ Pathname.new(file).relative_path_from(Pathname.new(base_dir)).to_s
24
+ end
19
25
  end
20
26
  end
21
27
  end
@@ -0,0 +1,17 @@
1
+ module CukeIterations
2
+ class IterationFileFinder
3
+ def find(features_dir, iteration_file = 'cuke_iterations.yml')
4
+ raise 'features_dir cannot be nil' unless features_dir
5
+
6
+ iteration_file_locations = [
7
+ iteration_file,
8
+ File.join(features_dir, iteration_file)
9
+ ]
10
+
11
+ location = iteration_file_locations.select { |location| File.exist? location }.first
12
+
13
+ raise "Couldn't find iterations file, tried the following: #{iteration_file_locations.join(', ')}" unless location
14
+ location
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module CukeIterations
2
+ class ScenarioFileWriter
3
+ def write_scenarios(features_dir, iteration_file, out_file)
4
+ iterations = YAML.load(File.read(iteration_file))
5
+
6
+ all_scenarios = []
7
+ features = CukeParser.parse_features(features_dir)
8
+ iterations.each do |iteration_name, iteration|
9
+ iteration_dir = File.join(features_dir, 'iterations', iteration_name, '..', '..')
10
+ FileUtils.mkdir_p iteration_dir
11
+
12
+ ScenarioListGenerator.for_iteration(features, iteration).each do |scenario|
13
+ all_scenarios << File.join(iteration_dir, scenario[:filename] + ":#{scenario[:line]}")
14
+ end
15
+ end
16
+
17
+ File.open(out_file, 'w') { |f| f.puts all_scenarios }
18
+ end
19
+ end
20
+ end
@@ -1,12 +1,24 @@
1
1
  module CukeIterations
2
2
  class ScenarioListGenerator
3
3
  class << self
4
- def for_iteration(parsed_features, iteration)
5
- parsed_features.select do |f|
6
- next if (f[:tags] & iteration[:exclude_tags]).any?
7
- (f[:tags] & iteration[:include_tags]).any?
4
+ def for_iteration(scenarios, iteration_info)
5
+ scenarios.select do |s|
6
+ next if is_excluded?(s, iteration_info)
7
+ is_included_by_tag?(s, iteration_info) || no_include_tags_specified?(iteration_info)
8
8
  end
9
9
  end
10
+
11
+ def no_include_tags_specified?(iteration)
12
+ iteration[:include_tags] == []
13
+ end
14
+
15
+ def is_included_by_tag?(scenario, iteration)
16
+ (scenario[:tags] & iteration[:include_tags]).any?
17
+ end
18
+
19
+ def is_excluded?(scenario, iteration)
20
+ (scenario[:tags] & iteration[:exclude_tags]).any?
21
+ end
10
22
  end
11
23
  end
12
24
  end
@@ -1,3 +1,3 @@
1
1
  module CukeIterations
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -13,10 +13,10 @@ describe "Extracting scenarios" do
13
13
  {filename: 'cuking_rocks.feature', line: 10},
14
14
  {filename: 'cuking_rocks.feature', line: 21},
15
15
  {filename: 'cuking_rocks.feature', line: 22},
16
- {filename: 'i_love_cukes.feature', line: 4},
17
- {filename: 'i_love_cukes.feature', line: 15},
18
- {filename: 'i_love_cukes.feature', line: 16},
19
- {filename: 'i_love_cukes.feature', line: 25},
16
+ {filename: 'subdirectory/i_love_cukes.feature', line: 4},
17
+ {filename: 'subdirectory/i_love_cukes.feature', line: 15},
18
+ {filename: 'subdirectory/i_love_cukes.feature', line: 16},
19
+ {filename: 'subdirectory/i_love_cukes.feature', line: 25},
20
20
  ]
21
21
 
22
22
  parsed_files_with_lines = @parsed_features.map{|x| {filename: x[:filename], line: x[:line]}}
@@ -24,7 +24,7 @@ describe "Extracting scenarios" do
24
24
  end
25
25
 
26
26
  it "should read scenario-level tags" do
27
- @parsed_features.should include filename: 'i_love_cukes.feature',
27
+ @parsed_features.should include filename: 'subdirectory/i_love_cukes.feature',
28
28
  line: 4,
29
29
  tags: ['@tag1', '@tag2']
30
30
  end
@@ -36,7 +36,7 @@ describe "Extracting scenarios" do
36
36
  end
37
37
 
38
38
  it "should read scenario-level tags on example rows" do
39
- @parsed_features.should include filename: 'i_love_cukes.feature',
39
+ @parsed_features.should include filename: 'subdirectory/i_love_cukes.feature',
40
40
  line: 15,
41
41
  tags: ['@tag3', '@tag4']
42
42
  end
@@ -48,7 +48,7 @@ describe "Extracting scenarios" do
48
48
  end
49
49
 
50
50
  it "should read example-group tags on example rows" do
51
- @parsed_features.should include filename: 'i_love_cukes.feature',
51
+ @parsed_features.should include filename: 'subdirectory/i_love_cukes.feature',
52
52
  line: 25,
53
53
  tags: ['@tag5', '@tag6', '@tag7', '@tag8']
54
54
  end
File without changes
@@ -9,6 +9,18 @@ describe "Scenario list generator" do
9
9
  ]
10
10
  end
11
11
 
12
+ it "should include all non-excluded scenarios if no include tags are specified" do
13
+ iteration = {
14
+ name: "iphone",
15
+ include_tags: [],
16
+ exclude_tags: ['@tag8']
17
+ }
18
+
19
+ list = ScenarioListGenerator.for_iteration(@parsed_features, iteration)
20
+
21
+ list.should =~ [@test1, @test2]
22
+ end
23
+
12
24
  it "should include the scenarios that have tags specified in the iteration" do
13
25
  iteration = {
14
26
  name: "iphone",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuke_iterations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-27 00:00:00.000000000Z
12
+ date: 2012-02-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gherkin
16
- requirement: &2155927060 !ruby/object:Gem::Requirement
16
+ requirement: &70344800299600 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2155927060
24
+ version_requirements: *70344800299600
25
25
  description: Run your Cucumber features multiple times within one Cucumber invocation
26
26
  email:
27
27
  - jon@jmerrifield.com
@@ -37,20 +37,24 @@ files:
37
37
  - README.md
38
38
  - Rakefile
39
39
  - bin/cuke_iterations
40
+ - changelog.md
40
41
  - cuke_iterations.gemspec
41
42
  - example/features/cuke_iterations.yml
42
43
  - example/features/cuking_rocks.feature
43
- - example/features/i_love_cukes.feature
44
+ - example/features/subdirectory/i_love_cukes.feature
44
45
  - example/features/support/env.rb
45
46
  - example/features/support/hooks.rb
46
47
  - lib/cuke_iterations.rb
47
48
  - lib/cuke_iterations/cucumber_helper.rb
48
49
  - lib/cuke_iterations/cuke_parser.rb
50
+ - lib/cuke_iterations/iteration_file_finder.rb
49
51
  - lib/cuke_iterations/scenario_extracting_formatter.rb
52
+ - lib/cuke_iterations/scenario_file_writer.rb
50
53
  - lib/cuke_iterations/scenario_list_generator.rb
51
54
  - lib/cuke_iterations/version.rb
52
55
  - lib/trollop.rb
53
56
  - spec/cuke_parser_spec.rb
57
+ - spec/scenario_file_writer_spec.rb
54
58
  - spec/scenario_list_generator_spec.rb
55
59
  - spec/spec_helper.rb
56
60
  homepage: https://github.com/jmerrifield/cuke_iterations
@@ -73,11 +77,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
77
  version: '0'
74
78
  requirements: []
75
79
  rubyforge_project: cuke_iterations
76
- rubygems_version: 1.8.6
80
+ rubygems_version: 1.8.10
77
81
  signing_key:
78
82
  specification_version: 3
79
83
  summary: Multiple iterations for Cucumber features
80
84
  test_files:
81
85
  - spec/cuke_parser_spec.rb
86
+ - spec/scenario_file_writer_spec.rb
82
87
  - spec/scenario_list_generator_spec.rb
83
88
  - spec/spec_helper.rb