spinach 0.10.1 → 0.12.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.
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'