spinach 0.10.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +30 -0
  3. data/.ruby-version +1 -1
  4. data/.tool-versions +1 -0
  5. data/Gemfile +0 -1
  6. data/README.markdown +35 -38
  7. data/Rakefile +1 -1
  8. data/bin/spinach +1 -1
  9. data/features/feature_hooks_and_tags.feature +22 -0
  10. data/features/randomization.feature +16 -0
  11. data/features/reporting/display_run_summary.feature +19 -3
  12. data/features/steps/automatic_feature_generation.rb +1 -1
  13. data/features/steps/feature_hooks_and_tags.rb +55 -0
  14. data/features/steps/randomizing_features_scenarios.rb +68 -0
  15. data/features/steps/reporting/display_run_summary.rb +29 -1
  16. data/features/support/env.rb +0 -13
  17. data/features/support/spinach_runner.rb +11 -0
  18. data/lib/spinach/cli.rb +29 -2
  19. data/lib/spinach/config.rb +25 -0
  20. data/lib/spinach/feature.rb +8 -0
  21. data/lib/spinach/orderers/default.rb +25 -0
  22. data/lib/spinach/orderers/random.rb +35 -0
  23. data/lib/spinach/orderers.rb +2 -0
  24. data/lib/spinach/reporter/progress.rb +1 -1
  25. data/lib/spinach/reporter/reporting.rb +3 -1
  26. data/lib/spinach/reporter/stdout.rb +1 -1
  27. data/lib/spinach/reporter.rb +1 -0
  28. data/lib/spinach/runner/feature_runner.rb +7 -3
  29. data/lib/spinach/runner.rb +40 -17
  30. data/lib/spinach/scenario.rb +10 -0
  31. data/lib/spinach/tags_matcher.rb +11 -2
  32. data/lib/spinach/version.rb +1 -1
  33. data/lib/spinach.rb +1 -0
  34. data/spinach.gemspec +4 -5
  35. data/test/spinach/cli_test.rb +39 -5
  36. data/test/spinach/config_test.rb +22 -0
  37. data/test/spinach/dsl_test.rb +1 -1
  38. data/test/spinach/feature_test.rb +10 -0
  39. data/test/spinach/generators/feature_generator_test.rb +1 -1
  40. data/test/spinach/hooks_test.rb +1 -1
  41. data/test/spinach/orderers/default_test.rb +31 -0
  42. data/test/spinach/orderers/random_test.rb +39 -0
  43. data/test/spinach/reporter_test.rb +2 -2
  44. data/test/spinach/runner_test.rb +28 -8
  45. data/test/spinach/scenario_test.rb +14 -0
  46. data/test/test_helper.rb +1 -14
  47. metadata +26 -40
  48. data/.travis.yml +0 -8
@@ -0,0 +1,35 @@
1
+ require 'digest'
2
+
3
+ module Spinach
4
+ module Orderers
5
+ class Random
6
+ attr_reader :seed
7
+
8
+ def initialize(seed:)
9
+ @seed = seed.to_s
10
+ end
11
+
12
+ # Output the randomization seed in the report summary.
13
+ #
14
+ # @param [IO] io
15
+ # Output buffer for report.
16
+ #
17
+ # @api public
18
+ def attach_summary(io)
19
+ io.puts("Randomized with seed #{seed}\n\n")
20
+ end
21
+
22
+ # Returns a reordered version of the provided array
23
+ #
24
+ # @param [Array] items
25
+ # Items to order
26
+ #
27
+ # @api public
28
+ def order(items)
29
+ items.sort_by do |item|
30
+ Digest::MD5.hexdigest(seed + item.ordering_id)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'orderers/default'
2
+ require_relative 'orderers/random'
@@ -8,7 +8,7 @@ module Spinach
8
8
  class Progress < Reporter
9
9
  include Reporting
10
10
 
11
- # Initialitzes the runner
11
+ # Initializes the reporter
12
12
  #
13
13
  # @param [Hash] options
14
14
  # Sets a custom output buffer by setting options[:output]
@@ -221,7 +221,9 @@ module Spinach
221
221
  error_summary = format_summary(:red, error_steps, 'Error')
222
222
 
223
223
  out.puts "Steps Summary: #{successful_summary}, #{pending_summary}, #{undefined_summary}, #{failed_summary}, #{error_summary}\n\n"
224
- out.puts "Finished in #{Time.now - @start_time} seconds" if @start_time
224
+ out.puts "Finished in #{Time.now - @start_time} seconds\n\n" if @start_time
225
+
226
+ @orderer.attach_summary(out) if @orderer
225
227
  end
226
228
  end
227
229
  end
@@ -8,7 +8,7 @@ module Spinach
8
8
  class Stdout < Reporter
9
9
  include Reporting
10
10
 
11
- # Initialitzes the runner
11
+ # Initializes the reporter
12
12
  #
13
13
  # @param [Hash] options
14
14
  # Sets a custom output buffer by setting options[:output]
@@ -10,6 +10,7 @@ module Spinach
10
10
  def initialize(options = {})
11
11
  @errors = []
12
12
  @options = options
13
+ @orderer = options[:orderer]
13
14
  @undefined_features = []
14
15
  @successful_steps = []
15
16
  @undefined_steps = []
@@ -1,18 +1,20 @@
1
1
  require_relative '../tags_matcher'
2
+ require 'spinach/orderers/default'
2
3
 
3
4
  module Spinach
4
5
  class Runner
5
6
  # A feature runner handles a particular feature run.
6
7
  #
7
8
  class FeatureRunner
8
- attr_reader :feature
9
+ attr_reader :feature, :orderer
9
10
 
10
11
  # @param [GherkinRuby::AST::Feature] feature
11
12
  # The feature to run.
12
13
  #
13
14
  # @api public
14
- def initialize(feature)
15
+ def initialize(feature, orderer: Spinach::Orderers::Default.new)
15
16
  @feature = feature
17
+ @orderer = orderer
16
18
  end
17
19
 
18
20
  # @return [String]
@@ -80,7 +82,7 @@ module Spinach
80
82
  end
81
83
 
82
84
  def scenarios_to_run
83
- feature.scenarios.select do |scenario|
85
+ unordered_scenarios = feature.scenarios.select do |scenario|
84
86
  has_a_tag_that_will_be_run = TagsMatcher.match(feature_tags + scenario.tags)
85
87
  on_a_line_that_will_be_run = if feature.run_every_scenario?
86
88
  true
@@ -90,6 +92,8 @@ module Spinach
90
92
 
91
93
  has_a_tag_that_will_be_run && on_a_line_that_will_be_run
92
94
  end
95
+
96
+ orderer.order(unordered_scenarios)
93
97
  end
94
98
  end
95
99
  end
@@ -30,10 +30,10 @@ module Spinach
30
30
  def initialize(filenames, options = {})
31
31
  @filenames = filenames
32
32
 
33
- @step_definitions_path = options.delete(:step_definitions_path ) ||
33
+ @step_definitions_path = options.delete(:step_definitions_path) ||
34
34
  Spinach.config.step_definitions_path
35
35
 
36
- @support_path = options.delete(:support_path ) ||
36
+ @support_path = options.delete(:support_path) ||
37
37
  Spinach.config.support_path
38
38
  end
39
39
 
@@ -42,7 +42,9 @@ module Spinach
42
42
  # @api public
43
43
  def init_reporters
44
44
  Spinach.config[:reporter_classes].each do |reporter_class|
45
- reporter = Support.constantize(reporter_class).new(Spinach.config.reporter_options)
45
+ reporter_options = default_reporter_options.merge(Spinach.config.reporter_options)
46
+ reporter = Support.constantize(reporter_class).new(reporter_options)
47
+
46
48
  reporter.bind
47
49
  end
48
50
  end
@@ -58,24 +60,12 @@ module Spinach
58
60
  require_frameworks
59
61
  init_reporters
60
62
 
61
- features = filenames.map do |filename|
62
- file, *lines = filename.split(":") # little more complex than just a "filename"
63
-
64
- # FIXME Feature should be instantiated directly, not through an unrelated class method
65
- feature = Parser.open_file(file).parse
66
- feature.filename = file
67
-
68
- feature.lines_to_run = lines if lines.any?
69
-
70
- feature
71
- end
72
-
73
63
  suite_passed = true
74
64
 
75
65
  Spinach.hooks.run_before_run
76
66
 
77
- features.each do |feature|
78
- feature_passed = FeatureRunner.new(feature).run
67
+ features_to_run.each do |feature|
68
+ feature_passed = FeatureRunner.new(feature, orderer: orderer).run
79
69
  suite_passed &&= feature_passed
80
70
 
81
71
  break if fail_fast? && !feature_passed
@@ -139,11 +129,44 @@ module Spinach
139
129
  support_files + step_definition_files
140
130
  end
141
131
 
132
+ # The orderer for this run.
133
+ #
134
+ # @api public
135
+ def orderer
136
+ @orderer ||= Support.constantize(Spinach.config[:orderer_class]).new(
137
+ seed: Spinach.config.seed
138
+ )
139
+ end
140
+
141
+ # Default initialization options for the reporter
142
+ #
143
+ def default_reporter_options
144
+ {orderer: orderer}
145
+ end
146
+
142
147
  private
143
148
 
144
149
  def fail_fast?
145
150
  Spinach.config.fail_fast
146
151
  end
152
+
153
+ def features_to_run
154
+ unordered_features = filenames.reduce([]) do |features, filename|
155
+ file, *lines = filename.split(":") # little more complex than just a "filename"
156
+
157
+ # FIXME Feature should be instantiated directly, not through an unrelated class method
158
+ feature = Parser.open_file(file).parse
159
+ feature.filename = file
160
+
161
+ feature.lines_to_run = lines if lines.any?
162
+
163
+ features << feature if TagsMatcher.match_feature(feature)
164
+
165
+ features
166
+ end
167
+
168
+ orderer.order(unordered_features)
169
+ end
147
170
  end
148
171
  end
149
172
 
@@ -9,5 +9,15 @@ module Spinach
9
9
  @tags = []
10
10
  @lines = []
11
11
  end
12
+
13
+ # Identifier used by orderers.
14
+ #
15
+ # Needs to involve the relative file path and line number so that the
16
+ # ordering a seed generates is stable across both runs and machines.
17
+ #
18
+ # @api public
19
+ def ordering_id
20
+ "#{feature.ordering_id}:#{lines.first}"
21
+ end
12
22
  end
13
23
  end
@@ -6,9 +6,9 @@ module Spinach
6
6
  class << self
7
7
 
8
8
  # Matches an array of tags (e.g. of a scenario) against the tags present
9
- # in Spinach' runtime options.
9
+ # in Spinach's runtime options.
10
10
  #
11
- # Spinach' tag option is an array which consists of (possibly) multiple
11
+ # Spinach's tag option is an array which consists of (possibly) multiple
12
12
  # arrays containing tags provided by the user running the features and
13
13
  # scenarios. Each of these arrays is considered a tag group.
14
14
  #
@@ -23,6 +23,15 @@ module Spinach
23
23
  }
24
24
  end
25
25
 
26
+ # Matches the tags of a feature (and its scenarios) against the tags present
27
+ # in Spinach's runtime options.
28
+ #
29
+ # A feature matches when, for any of its scenarios, the combination of the
30
+ # feature's tags and that scenario's tags match the configured tags.
31
+ def match_feature(feature)
32
+ feature.scenarios.any? { |scenario| match(feature.tags + scenario.tags) }
33
+ end
34
+
26
35
  private
27
36
 
28
37
  def tag_groups
@@ -1,4 +1,4 @@
1
1
  module Spinach
2
2
  # Spinach version.
3
- VERSION = "0.10.1"
3
+ VERSION = "0.12.0"
4
4
  end
data/lib/spinach.rb CHANGED
@@ -9,6 +9,7 @@ require_relative 'spinach/parser'
9
9
  require_relative 'spinach/dsl'
10
10
  require_relative 'spinach/feature_steps'
11
11
  require_relative 'spinach/reporter'
12
+ require_relative 'spinach/orderers'
12
13
  require_relative 'spinach/cli'
13
14
  require_relative 'spinach/generators'
14
15
  require_relative 'spinach/auditor'
data/spinach.gemspec CHANGED
@@ -3,8 +3,7 @@ require File.expand_path('../lib/spinach/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Josep Jaume Rey", "Josep M. Bach", "Oriol Gual", "Marc Divins Castellvi"]
6
- gem.email = ["info@codegram.com", "josep.m.bach@gmail.com",
7
- "oriolgual@gmail.com", "josepjaume@gmail.com", "marcdivc@gmail.com"]
6
+ gem.email = ["josep.m.bach@gmail.com", "oriolgual@gmail.com", "josepjaume@gmail.com", "marcdivc@gmail.com"]
8
7
  gem.description = %q{Spinach is a BDD framework on top of gherkin}
9
8
  gem.summary = %q{Spinach is a BDD framework on top of gherkin}
10
9
  gem.homepage = "http://github.com/codegram/spinach"
@@ -12,17 +11,17 @@ Gem::Specification.new do |gem|
12
11
 
13
12
  gem.add_runtime_dependency 'gherkin-ruby', '>= 0.3.2'
14
13
  gem.add_runtime_dependency 'colorize'
15
- gem.add_runtime_dependency 'json'
16
14
  gem.add_development_dependency 'rake'
17
- gem.add_development_dependency 'mocha', '~> 1.0'
15
+ gem.add_development_dependency 'mocha', "~> 1.5.0"
18
16
  gem.add_development_dependency 'sinatra'
19
17
  gem.add_development_dependency 'capybara'
20
18
  gem.add_development_dependency 'pry'
21
- gem.add_development_dependency 'simplecov'
22
19
  gem.add_development_dependency 'rspec'
23
20
  gem.add_development_dependency 'minitest', '< 5.0'
24
21
  gem.add_development_dependency 'fakefs', ">= 0.5.2"
25
22
 
23
+ gem.required_ruby_version = Gem::Requirement.new(">= 2.4".freeze)
24
+
26
25
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
27
26
  gem.files = `git ls-files`.split("\n")
28
27
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -89,6 +89,40 @@ tags:
89
89
  end
90
90
  end
91
91
 
92
+ describe 'rand' do
93
+ let(:config) { Spinach::Config.new }
94
+
95
+ before do
96
+ Spinach.stubs(:config).returns(config)
97
+ Spinach::Cli.new(%w(--rand)).options
98
+ end
99
+
100
+ it 'uses the Random orderer' do
101
+ config.orderer_class.must_equal 'Spinach::Orderers::Random'
102
+ end
103
+
104
+ it 'sets a numeric seed' do
105
+ config.seed.must_equal config.seed.to_i
106
+ end
107
+ end
108
+
109
+ describe 'seed' do
110
+ let(:config) { Spinach::Config.new }
111
+
112
+ before do
113
+ Spinach.stubs(:config).returns(config)
114
+ Spinach::Cli.new(%w(--seed 42)).options
115
+ end
116
+
117
+ it 'uses the random orderer' do
118
+ config.orderer_class.must_equal 'Spinach::Orderers::Random'
119
+ end
120
+
121
+ it 'sets the seed' do
122
+ config.seed.must_equal 42
123
+ end
124
+ end
125
+
92
126
  describe 'features_path' do
93
127
  %w{-f --features_path}.each do |opt|
94
128
  it 'sets the given features_path' do
@@ -242,14 +276,14 @@ tags:
242
276
  describe 'the feature really exists' do
243
277
  it 'runs the feature' do
244
278
  cli = Spinach::Cli.new(['features/some_feature.feature'])
245
- File.stubs(:exists?).returns(true)
279
+ File.stubs(:exist?).returns(true)
246
280
  cli.feature_files.must_equal ['features/some_feature.feature']
247
281
  end
248
282
  end
249
283
 
250
284
  it 'it fails if the feature does not exist' do
251
285
  cli = Spinach::Cli.new(['features/some_feature.feature'])
252
- File.stubs(:exists?).returns(false)
286
+ File.stubs(:exist?).returns(false)
253
287
  cli.expects(:fail!).with('features/some_feature.feature could not be found')
254
288
 
255
289
  cli.feature_files
@@ -259,7 +293,7 @@ tags:
259
293
  describe 'when a particular feature list is passed with line' do
260
294
  it 'returns the feature with the line number' do
261
295
  cli = Spinach::Cli.new(['features/some_feature.feature:10'])
262
- File.stubs(:exists?).returns(true)
296
+ File.stubs(:exist?).returns(true)
263
297
 
264
298
  cli.feature_files.must_equal ['features/some_feature.feature:10']
265
299
  end
@@ -268,7 +302,7 @@ tags:
268
302
  describe "when a particular feature list is passed with multiple lines" do
269
303
  it "returns the feature with the line numbers" do
270
304
  cli = Spinach::Cli.new(['features/some_feature.feature:10:20'])
271
- File.stubs(:exists?).returns(true)
305
+ File.stubs(:exist?).returns(true)
272
306
 
273
307
  cli.feature_files.must_equal ["features/some_feature.feature:10:20"]
274
308
  end
@@ -303,7 +337,7 @@ tags:
303
337
  Dir.expects(:glob).with('path/to/features/**/*.feature')
304
338
  .returns(['several features'])
305
339
 
306
- File.stubs(:exists?).returns(true)
340
+ File.stubs(:exist?).returns(true)
307
341
 
308
342
  cli.feature_files.must_equal ['several features', 'some_feature.feature']
309
343
  end
@@ -27,6 +27,28 @@ describe Spinach::Config do
27
27
  end
28
28
  end
29
29
 
30
+ describe '#orderer_class' do
31
+ it 'returns a default' do
32
+ subject[:orderer_class].must_equal "Spinach::Orderers::Default"
33
+ end
34
+
35
+ it 'can be overwritten' do
36
+ subject[:orderer_class] = "MyOwnOrderer"
37
+ subject[:orderer_class].must_equal "MyOwnOrderer"
38
+ end
39
+ end
40
+
41
+ describe '#seed' do
42
+ it 'has a default' do
43
+ subject[:seed].must_be_kind_of Integer
44
+ end
45
+
46
+ it 'can be overwritten' do
47
+ subject[:seed] = 54321
48
+ subject[:seed].must_equal 54321
49
+ end
50
+ end
51
+
30
52
  describe '#step_definitions_path' do
31
53
  it 'returns a default' do
32
54
  subject[:step_definitions_path].must_be_kind_of String
@@ -157,7 +157,7 @@ describe Spinach::DSL do
157
157
  end
158
158
 
159
159
  @feature.new.step_location_for('I say goodbye').first.must_include '/dsl_test.rb'
160
- @feature.new.step_location_for('I say goodbye').last.must_be_kind_of Fixnum
160
+ @feature.new.step_location_for('I say goodbye').last.must_be_kind_of Integer
161
161
  end
162
162
  end
163
163
  end
@@ -29,5 +29,15 @@ module Spinach
29
29
  end
30
30
  end
31
31
  end
32
+
33
+ describe "#ordering_id" do
34
+ subject { Feature.new }
35
+
36
+ before { subject.filename = "features/foo/bar.feature" }
37
+
38
+ it 'is the filename' do
39
+ subject.ordering_id.must_equal "features/foo/bar.feature"
40
+ end
41
+ end
32
42
  end
33
43
  end
@@ -71,7 +71,7 @@ Feature: Cheezburger can I has
71
71
  in_current_dir do
72
72
  subject.store
73
73
  File.directory?("features/steps/").must_equal true
74
- File.exists?("features/steps/cheezburger_can_i_has.rb").must_equal true
74
+ File.exist?("features/steps/cheezburger_can_i_has.rb").must_equal true
75
75
  File.read("features/steps/cheezburger_can_i_has.rb").strip.must_equal(
76
76
  subject.generate.strip
77
77
  )
@@ -108,7 +108,7 @@ describe Spinach::Hooks do
108
108
  subject.on_tag('screenshot') do
109
109
  assertion = true
110
110
  end
111
- subject.run_before_scenario(scenario)
111
+ subject.run_before_scenario(scenario, step_definitions)
112
112
  assertion.wont_equal true
113
113
  end
114
114
  end
@@ -0,0 +1,31 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe Spinach::Orderers::Default do
4
+ let(:orderer) { Spinach::Orderers::Default.new }
5
+
6
+ describe "#attach_summary" do
7
+ let(:io) { StringIO.new }
8
+
9
+ it 'appends nothing' do
10
+ contents_before_running = io.string.dup
11
+
12
+ orderer.attach_summary(io)
13
+
14
+ io.string.must_equal contents_before_running
15
+ end
16
+ end
17
+
18
+ describe "#order" do
19
+ let(:items) { Array(1..10) }
20
+
21
+ it "doesn't change the order of the items" do
22
+ orderer.order(items).must_equal items
23
+ end
24
+ end
25
+
26
+ describe "#initialize" do
27
+ it "can be provided options without raising an error" do
28
+ Spinach::Orderers::Default.new(seed: "seed")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../../test_helper'
2
+
3
+ describe Spinach::Orderers::Random do
4
+ let(:orderer) { Spinach::Orderers::Random.new(seed: Spinach.config.seed) }
5
+
6
+ describe "#attach_summary" do
7
+ let(:io) { StringIO.new }
8
+
9
+ it 'appends the seed' do
10
+ orderer.attach_summary(io)
11
+
12
+ io.string.must_match /Randomized\ with\ seed\ #{orderer.seed}/
13
+ end
14
+ end
15
+
16
+ describe "#order" do
17
+ Identifiable = Struct.new(:ordering_id)
18
+
19
+ let(:items) { (1..10).map { |n| Identifiable.new(n.to_s) } }
20
+
21
+ it "randomizes the items" do
22
+ orderer.order(items).wont_equal items
23
+ end
24
+
25
+ it "always randomizes items the same way with the same seed" do
26
+ orderer.order(items).must_equal orderer.order(items)
27
+ end
28
+ end
29
+
30
+ describe "#initialize" do
31
+ it "requires a seed parameter" do
32
+ proc {
33
+ Spinach::Orderers::Random.new
34
+ }.must_raise ArgumentError
35
+
36
+ Spinach::Orderers::Random.new(seed: 4)
37
+ end
38
+ end
39
+ end
@@ -89,8 +89,8 @@ module Spinach
89
89
 
90
90
  it "binds a callback around every scenario" do
91
91
  @reporter.expects(:around_scenario_run)
92
- Spinach.hooks.run_around_scenario(anything) do
93
- yield
92
+ Spinach.hooks.run_around_scenario(anything) do |&block|
93
+ block.call
94
94
  end
95
95
  end
96
96
 
@@ -65,7 +65,10 @@ describe Spinach::Runner do
65
65
  config.reporter_options = {backtrace: true}
66
66
  reporter = stub
67
67
  reporter.stubs(:bind)
68
- Spinach::Reporter::Stdout.expects(new: reporter).with(backtrace: true)
68
+ Spinach::Reporter::Stdout.expects(new: reporter).with(
69
+ backtrace: true,
70
+ **runner.default_reporter_options
71
+ )
69
72
  runner.init_reporters
70
73
  end
71
74
  end
@@ -74,15 +77,21 @@ describe Spinach::Runner do
74
77
  describe '#run' do
75
78
  before(:each) do
76
79
  @feature_runner = stub
80
+ @feature_runner.stubs(:run).returns(true)
81
+
77
82
  filenames.each do |filename|
78
- Spinach::Parser.stubs(:open_file).with(filename).returns parser = stub
79
- parser.stubs(:parse).returns feature = Spinach::Feature.new
83
+ parser = stub
84
+ Spinach::Parser.stubs(:open_file).with(filename).returns(parser)
85
+
86
+ feature = Spinach::Feature.new
87
+ feature.scenarios << Spinach::Scenario.new(feature)
88
+ parser.stubs(:parse).returns(feature)
89
+
80
90
  Spinach::Runner::FeatureRunner.stubs(:new).
81
91
  with(feature, anything).
82
92
  returns(@feature_runner)
83
93
  end
84
94
 
85
- @feature_runner.stubs(:run).returns(true)
86
95
  runner.stubs(required_files: [])
87
96
  end
88
97
 
@@ -130,12 +139,18 @@ describe Spinach::Runner do
130
139
  let(:runner) { Spinach::Runner.new(filenames) }
131
140
 
132
141
  before(:each) do
142
+ parser = stub
143
+ Spinach::Parser.stubs(:open_file).with(filename).returns(parser)
144
+
145
+ @feature = Spinach::Feature.new
146
+ @feature.scenarios << Spinach::Scenario.new(@feature)
147
+ parser.stubs(:parse).returns(@feature)
148
+
133
149
  @feature_runner = stub
134
- Spinach::Parser.stubs(:open_file).with(filename).returns parser = stub
135
- parser.stubs(:parse).returns @feature = Spinach::Feature.new
136
150
  Spinach::Runner::FeatureRunner.stubs(:new).
137
151
  with(@feature, anything).
138
152
  returns(@feature_runner)
153
+
139
154
  runner.stubs(required_files: [])
140
155
  end
141
156
 
@@ -171,8 +186,13 @@ describe Spinach::Runner do
171
186
 
172
187
  before(:each) do
173
188
  filenames.each_with_index do |filename, i|
174
- Spinach::Parser.stubs(:open_file).with(filename).returns parser = stub
175
- parser.stubs(:parse).returns feature = Spinach::Feature.new
189
+ parser = stub
190
+ Spinach::Parser.stubs(:open_file).with(filename).returns(parser)
191
+
192
+ feature = Spinach::Feature.new
193
+ feature.scenarios << Spinach::Scenario.new(feature)
194
+ parser.stubs(:parse).returns(feature)
195
+
176
196
  Spinach::Runner::FeatureRunner.stubs(:new).
177
197
  with(feature, anything).
178
198
  returns(feature_runners[i])
@@ -2,5 +2,19 @@ require 'test_helper'
2
2
 
3
3
  module Spinach
4
4
  describe Scenario do
5
+ describe "#ordering_id" do
6
+ let(:feature) { Feature.new }
7
+
8
+ subject { Scenario.new(feature) }
9
+
10
+ before do
11
+ feature.filename = "features/foo/bar.feature"
12
+ subject.lines = Array(4..12)
13
+ end
14
+
15
+ it 'is the filename and starting line number' do
16
+ subject.ordering_id.must_equal "features/foo/bar.feature:4"
17
+ end
18
+ end
5
19
  end
6
20
  end
data/test/test_helper.rb CHANGED
@@ -1,19 +1,6 @@
1
- require 'simplecov'
2
- require 'coveralls'
3
-
4
- SimpleCov.formatter = Coveralls::SimpleCov::Formatter
5
- if ENV['CI'] && !defined?(Rubinius)
6
- require 'simplecov'
7
-
8
- SimpleCov.start do
9
- add_filter '/test/'
10
- add_filter '/features/'
11
- end
12
- end
13
-
14
1
  require 'minitest/autorun'
15
2
  require 'minitest/spec'
16
- require 'mocha/mini_test'
3
+ require 'mocha/minitest'
17
4
  require 'ostruct'
18
5
  require 'stringio'
19
6
  require 'pry'