spinach 0.0.6 → 0.1.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 (41) hide show
  1. data/Gemfile +1 -0
  2. data/Readme.md +3 -0
  3. data/bin/spinach +3 -1
  4. data/features/steps/error_reporting.rb +4 -8
  5. data/features/steps/exit_status.rb +0 -1
  6. data/features/steps/feature_name_guessing.rb +1 -2
  7. data/features/support/spinach_runner.rb +0 -2
  8. data/lib/spinach/capybara.rb +8 -8
  9. data/lib/spinach/cli.rb +30 -18
  10. data/lib/spinach/config.rb +29 -10
  11. data/lib/spinach/dsl.rb +45 -21
  12. data/lib/spinach/exceptions.rb +21 -8
  13. data/lib/spinach/feature.rb +8 -4
  14. data/lib/spinach/parser.rb +13 -7
  15. data/lib/spinach/reporter/stdout.rb +251 -53
  16. data/lib/spinach/reporter.rb +43 -26
  17. data/lib/spinach/runner/feature.rb +39 -26
  18. data/lib/spinach/runner/scenario.rb +43 -28
  19. data/lib/spinach/runner.rb +40 -20
  20. data/lib/spinach/support.rb +8 -7
  21. data/lib/spinach/version.rb +2 -1
  22. data/lib/spinach.rb +17 -9
  23. data/spinach.gemspec +2 -1
  24. data/test/spinach/capybara_test.rb +32 -3
  25. data/test/spinach/cli_test.rb +32 -11
  26. data/test/spinach/config_test.rb +9 -6
  27. data/test/spinach/dsl_test.rb +8 -1
  28. data/test/spinach/feature_test.rb +14 -11
  29. data/test/spinach/parser_test.rb +33 -20
  30. data/test/spinach/reporter/stdout_test.rb +364 -103
  31. data/test/spinach/reporter_test.rb +145 -20
  32. data/test/spinach/runner/feature_test.rb +26 -51
  33. data/test/spinach/runner/scenario_test.rb +64 -35
  34. data/test/spinach/runner_test.rb +41 -32
  35. data/test/spinach/support_test.rb +2 -10
  36. data/test/spinach_test.rb +14 -14
  37. data/test/test_helper.rb +13 -5
  38. metadata +36 -28
  39. data/examples/steps/user_logs_in.rb +0 -23
  40. data/examples/user_logs_in.feature +0 -6
  41. data/examples/user_logs_in.rb +0 -23
@@ -1,24 +1,17 @@
1
1
  require_relative '../../test_helper'
2
2
 
3
3
  describe Spinach::Runner::Feature do
4
- before do
5
- @filename = 'feature/a_cool_feature.feature'
6
- @reporter = stub_everything
7
- @feature = Spinach::Runner::Feature.new(@filename, @reporter)
8
- end
4
+ let(:filename) { 'feature/a_cool_feature.feature' }
5
+ let(:feature) { Spinach::Runner::Feature.new(filename) }
9
6
 
10
7
  describe '#initialize' do
11
8
  it 'initializes the given filename' do
12
- @feature.filename.must_equal @filename
13
- end
14
-
15
- it 'initializes the given reporter' do
16
- @feature.reporter.must_equal @reporter
9
+ feature.filename.must_equal filename
17
10
  end
18
11
 
19
12
  it 'initalizes the given scenario line' do
20
13
  @filename = 'feature/a_cool_feature.feature:12'
21
- @feature = Spinach::Runner::Feature.new(@filename, @reporter)
14
+ @feature = Spinach::Runner::Feature.new(@filename)
22
15
 
23
16
  @feature.instance_variable_get(:@scenario_line).must_equal '12'
24
17
  end
@@ -26,77 +19,69 @@ describe Spinach::Runner::Feature do
26
19
 
27
20
  describe '#feature' do
28
21
  it 'finds the feature given a feature name' do
29
- feature = stub_everything
30
- @feature.stubs(feature_name: 'A cool feature')
31
- Spinach.expects(:find_feature).with('A cool feature').returns(feature)
32
- @feature.feature
22
+ @feature = stub_everything
23
+ feature.stubs(feature_name: 'A cool feature')
24
+
25
+ Spinach.expects(:find_feature).with('A cool feature').returns(@feature)
26
+ feature.feature
33
27
  end
34
28
  end
35
29
 
36
30
  describe '#data' do
37
31
  it 'returns the parsed data' do
38
- parsed_data = {'name' => 'A cool feature'}
39
- parser = stub(:parse => parsed_data)
32
+ parsed_data = {name: 'A cool feature'}
33
+ parser = stub(parse: parsed_data)
40
34
  Spinach::Parser.expects(:new).returns(parser)
41
- @feature.data.must_equal parsed_data
35
+ feature.data.must_equal parsed_data
42
36
  end
43
37
  end
44
38
 
45
39
  describe '#scenarios' do
46
40
  it 'returns the parsed scenarios' do
47
- @feature.stubs(data: {'elements' => [1, 2, 3]})
48
- @feature.scenarios.must_equal [1,2,3]
41
+ feature.stubs(data: {'elements' => [1, 2, 3]})
42
+ feature.scenarios.must_equal [1,2,3]
49
43
  end
50
44
  end
51
45
 
52
46
  describe '#run' do
53
47
  before do
54
- @feature.stubs(data: {
48
+ feature.stubs(data: {
55
49
  'name' => 'A cool feature',
56
50
  'elements' => [{'keyword'=>'Scenario', 'name'=>'Basic guess', 'line'=>6, 'description'=>'', 'type'=>'scenario'},
57
51
  {'keyword'=>'Scenario', 'name'=>'Basic guess II', 'line'=>12, 'description'=>'', 'type'=>'scenario'},
58
52
  {'keyword'=>'Scenario', 'name'=>'Basic guess III', 'line'=>18, 'description'=>'', 'type'=>'scenario'}]
59
53
  })
60
- @feature.stubs(feature: stub_everything)
61
- end
62
-
63
- it 'reports' do
64
- Spinach::Runner::Scenario.stubs(new: stub_everything)
65
-
66
- @reporter.expects(:feature).with('A cool feature')
67
- @feature.run
54
+ feature.stubs(feature: stub_everything)
68
55
  end
69
56
 
70
57
  it 'calls the steps as expected' do
71
58
  seq = sequence('feature')
59
+ feature.feature.expects(:run_hook).with(:before, kind_of(Hash))
72
60
  3.times do
73
- @feature.feature.expects(:before).in_sequence(seq)
74
61
  Spinach::Runner::Scenario.
75
62
  expects(:new).
76
63
  returns(stub_everything).
77
64
  in_sequence(seq)
78
- @feature.feature.expects(:after).in_sequence(seq)
79
65
  end
80
- @feature.run
66
+ feature.feature.expects(:run_hook).with(:after, kind_of(Hash))
67
+ feature.run
81
68
  end
82
69
 
83
- it "returns true if the execution succeeds" do
84
- @feature.stubs(reporter: stub_everything)
70
+ it 'returns true if the execution succeeds' do
85
71
  Spinach::Runner::Scenario.any_instance.
86
- expects(run: nil).times(3)
87
- @feature.run.must_equal true
72
+ expects(run: true).times(3)
73
+ feature.run.must_equal true
88
74
  end
89
75
 
90
- it "returns false if the execution fails" do
91
- @feature.stubs(reporter: stub_everything)
76
+ it 'returns false if the execution fails' do
92
77
  Spinach::Runner::Scenario.any_instance.
93
- expects(run: stub_everything).times(3)
94
- @feature.run.must_equal false
78
+ expects(run: false).times(3)
79
+ feature.run.must_equal false
95
80
  end
96
81
 
97
82
  it 'calls only the given scenario' do
98
83
  @filename = 'feature/a_cool_feature.feature:12'
99
- @feature = Spinach::Runner::Feature.new(@filename, @reporter)
84
+ @feature = Spinach::Runner::Feature.new(@filename)
100
85
  @feature.stubs(data: {
101
86
  'name' => 'A cool feature',
102
87
  'elements' => [{'keyword'=>'Scenario', 'name'=>'Basic guess', 'line'=>6, 'description'=>'', 'type'=>'scenario'},
@@ -108,15 +93,5 @@ describe Spinach::Runner::Feature do
108
93
  Spinach::Runner::Scenario.expects(:new).with(anything, anything, @feature.scenarios[1], anything).once.returns(stub_everything)
109
94
  @feature.run
110
95
  end
111
-
112
- it "calls an error summary if there are any failures" do
113
- failure = stub('failure')
114
- scenario = stub(run: failure)
115
- Spinach::Runner::Scenario.stubs(:new).returns scenario
116
-
117
- @reporter.expects(:error_summary).with [failure, failure, failure]
118
-
119
- @feature.run
120
- end
121
96
  end
122
97
  end
@@ -1,8 +1,8 @@
1
1
  require_relative '../../test_helper'
2
2
 
3
3
  describe Spinach::Runner::Scenario do
4
- before do
5
- @data = {
4
+ let(:data) do
5
+ {
6
6
  'name' => 'A cool scenario',
7
7
  'steps' => [
8
8
  {'keyword' => 'Given', 'name' => 'I herd you like steps'},
@@ -10,68 +10,97 @@ describe Spinach::Runner::Scenario do
10
10
  {'keyword' => 'Then', 'name' => 'I go step by step'}
11
11
  ]
12
12
  }
13
- @feature = stub_everything
14
- @feature_name = "My feature"
15
- @reporter = stub_everything
16
- @scenario = Spinach::Runner::Scenario.new(@feature_name, @feature, @data, @reporter)
17
13
  end
18
14
 
19
- describe '#initialize' do
20
- it 'initializes a scenario name' do
21
- @scenario.name.must_equal 'A cool scenario'
22
- end
15
+ let(:feature) { stub_everything }
16
+ let(:feature_name) { 'My feature' }
17
+ let(:scenario) { Spinach::Runner::Scenario.new(feature_name, feature, data) }
23
18
 
19
+ describe '#initialize' do
24
20
  it 'lists all the steps' do
25
- @scenario.steps.count.must_equal 3
26
- end
27
-
28
- it 'sets the reporter' do
29
- @scenario.reporter.must_equal @reporter
21
+ scenario.steps.count.must_equal 3
30
22
  end
31
23
 
32
24
  it 'sets the feature' do
33
- @scenario.feature.must_equal @feature
25
+ scenario.feature.must_equal feature
34
26
  end
35
27
  end
36
28
 
37
29
  describe '#run' do
38
30
  it 'calls the appropiate feature steps' do
39
- @feature.expects(:execute_step).with('I herd you like steps')
40
- @feature.expects(:execute_step).with('I test steps')
41
- @feature.expects(:execute_step).with('I go step by step')
42
- @scenario.run
31
+ feature.expects(:execute_step).with('I herd you like steps')
32
+ feature.expects(:execute_step).with('I test steps')
33
+ feature.expects(:execute_step).with('I go step by step')
34
+ scenario.run
43
35
  end
44
36
 
45
37
  describe 'when throwing exceptions' do
46
38
  it 'rescues a MiniTest::Assertion' do
47
- @feature.expects(:execute_step).raises(MiniTest::Assertion)
48
- @reporter.expects(:step).with(anything, anything, :failure)
49
- @scenario.run
39
+ feature.expects(:execute_step).raises(MiniTest::Assertion)
40
+ scenario.expects(:run_hook).with(:before_run, has_value("A cool scenario"))
41
+ scenario.expects(:run_hook).with(:after_run, has_value("A cool scenario"))
42
+ scenario.expects(:run_hook).with(
43
+ :on_failed_step, anything, anything, anything)
44
+ scenario.expects(:run_hook).with(
45
+ :on_skipped_step, anything, anything).twice
46
+ scenario.run
50
47
  end
51
48
 
52
49
  it 'rescues a Spinach::StepNotDefinedException' do
53
- @feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('foo', 'bar'))
54
- @reporter.expects(:step).with(anything, anything, :undefined_step)
55
- @scenario.run
50
+ feature.expects(:execute_step).raises(
51
+ Spinach::StepNotDefinedException.new('foo', 'bar'))
52
+ scenario.expects(:run_hook).with(:before_run, has_value("A cool scenario"))
53
+ scenario.expects(:run_hook).with(:after_run, has_value("A cool scenario"))
54
+ scenario.expects(:run_hook).with(
55
+ :on_undefined_step, anything, anything, anything)
56
+ scenario.expects(:run_hook).with(
57
+ :on_skipped_step, anything, anything).twice
58
+ scenario.run
56
59
  end
57
60
 
58
61
  it 'rescues any other error' do
59
- @feature.expects(:execute_step).raises
60
- @reporter.expects(:step).with(anything, anything, :error)
61
- @scenario.run
62
+ feature.expects(:execute_step).raises
63
+ scenario.expects(:run_hook).with(:after_run, has_value("A cool scenario"))
64
+ scenario.expects(:run_hook).with(:before_run, has_value("A cool scenario"))
65
+ scenario.expects(:run_hook).with(
66
+ :on_error_step, anything, anything, anything)
67
+ scenario.expects(:run_hook).with(
68
+ :on_skipped_step, anything, anything).twice
69
+ scenario.run
62
70
  end
63
71
 
64
- it "returns an failure" do
65
- @feature.expects(:execute_step).raises(MiniTest::Assertion)
66
- @scenario.run.wont_equal nil
72
+ it 'returns an failure' do
73
+ feature.expects(:execute_step).raises(MiniTest::Assertion)
74
+ scenario.run.wont_equal nil
67
75
  end
68
-
69
76
  end
70
77
 
71
78
  it 'runs a step' do
72
- @reporter.expects(:step).with(anything, anything, :success).times(3)
73
- @scenario.run.must_equal nil
79
+ feature.expects(:execute_step).with(anything).times(3)
80
+ scenario.run.must_equal true
74
81
  end
75
82
 
83
+ describe 'hooks' do
84
+ it 'fires up the scenario hooks' do
85
+ feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('foo', 'bar'))
86
+ feature.expects(:run_hook).with(:before_scenario, has_value("A cool scenario"))
87
+ feature.expects(:run_hook).with(:after_scenario, has_value("A cool scenario"))
88
+ scenario.run
89
+ end
90
+
91
+ it 'fires up the step hooks' do
92
+ feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('foo', 'bar'))
93
+ %w{before_step after_step}.each do |hook|
94
+ feature.expects(:run_hook).with(
95
+ hook.to_sym, kind_of(Hash))
96
+ feature.expects(:run_hook).with(
97
+ hook.to_sym, kind_of(Hash))
98
+ feature.expects(:run_hook).with(
99
+ hook.to_sym, kind_of(Hash))
100
+ end
101
+
102
+ scenario.run
103
+ end
104
+ end
76
105
  end
77
106
  end
@@ -1,61 +1,70 @@
1
1
  require_relative '../test_helper'
2
2
 
3
3
  describe Spinach::Runner do
4
- before do
5
- @filenames =
6
- %w{features/cool_feature.feature features/great_feature.feature}
4
+ let(:filenames) { %w{features/cool_feature.feature features/great_feature.feature} }
5
+ let(:runner) { Spinach::Runner.new(filenames) }
7
6
 
8
- @runner = Spinach::Runner.new(@filenames)
9
- end
10
- describe "#initialize" do
11
- it "sets the filenames" do
12
- @runner.filenames.must_equal @filenames
7
+ describe '#initialize' do
8
+ it 'sets the filenames' do
9
+ runner.filenames.must_equal filenames
13
10
  end
14
- describe "step_definitions_path" do
15
- it "sets a default" do
16
- @runner.step_definitions_path.must_be_kind_of String
11
+
12
+ describe 'step_definitions_path' do
13
+ it 'sets a default' do
14
+ runner.step_definitions_path.must_be_kind_of String
17
15
  end
18
- it "can be overriden" do
19
- @runner = Spinach::Runner.new(
16
+
17
+ it 'can be overriden' do
18
+ runner = Spinach::Runner.new(
20
19
  @filename, step_definitions_path: 'spinach/step_definitions'
21
20
  )
22
- @runner.step_definitions_path.must_equal 'spinach/step_definitions'
21
+ runner.step_definitions_path.must_equal 'spinach/step_definitions'
23
22
  end
24
23
  end
25
- describe "support_path" do
26
- it "sets a default" do
27
- @runner.support_path.must_be_kind_of String
24
+
25
+ describe 'support_path' do
26
+ it 'sets a default' do
27
+ runner.support_path.must_be_kind_of String
28
28
  end
29
- it "can be overriden" do
30
- @runner = Spinach::Runner.new(
29
+
30
+ it 'can be overriden' do
31
+ runner = Spinach::Runner.new(
31
32
  @filename, support_path: 'spinach/environment'
32
33
  )
33
- @runner.support_path.must_equal 'spinach/environment'
34
+ runner.support_path.must_equal 'spinach/environment'
34
35
  end
35
36
  end
36
37
  end
37
- describe "#reporter" do
38
- it "returns a default reporter" do
39
- @runner.reporter.wont_equal nil
40
- end
41
- end
42
- describe "#run" do
38
+
39
+ describe '#run' do
43
40
  before do
44
41
  @feature = stub
45
- @runner.stubs(reporter: stub_everything)
46
- @filenames.each do |filename|
42
+ filenames.each do |filename|
47
43
  Spinach::Runner::Feature.expects(:new).
48
44
  with(filename, anything).
49
45
  returns(@feature)
50
46
  end
51
47
  end
52
- it "instantiates a new Feature and runs it with every file" do
48
+
49
+ it 'instantiates a new Feature and runs it with every file' do
53
50
  @feature.stubs(run: true)
54
- @runner.run.must_equal true
51
+ runner.run.must_equal true
55
52
  end
56
- it "returns false if it fails" do
53
+
54
+ it 'returns false if it fails' do
57
55
  @feature.stubs(run: false)
58
- @runner.run
56
+ runner.run
57
+ end
58
+ end
59
+ describe '#require_dependencies' do
60
+ it 'requires support files and step definitions' do
61
+ runner.stubs(
62
+ support_files: ['a', 'b'], step_definition_files: ['c', 'd']
63
+ )
64
+ %w{a b c d}.each do |file|
65
+ runner.expects(:require).with(file)
66
+ end
67
+ runner.require_dependencies
59
68
  end
60
69
  end
61
70
  end
@@ -7,26 +7,18 @@ describe Spinach::Support do
7
7
  end
8
8
 
9
9
  it 'downcases the given value' do
10
- ActiveSupport::Inflector.expects(:camelize).with('value').returns('value')
11
-
12
- Spinach::Support.camelize('VALUE').must_equal 'value'
10
+ Spinach::Support.camelize('VALUE').must_equal 'Value'
13
11
  end
14
12
 
15
13
  it 'squeezes the spaces for the given value' do
16
- ActiveSupport::Inflector.expects(:camelize).with('feature_name').returns('FeatureName')
17
-
18
14
  Spinach::Support.camelize('feature name').must_equal 'FeatureName'
19
15
  end
20
16
 
21
17
  it 'strips the given value' do
22
- ActiveSupport::Inflector.expects(:camelize).with('value').returns('value')
23
-
24
- Spinach::Support.camelize(' value ').must_equal 'value'
18
+ Spinach::Support.camelize(' value ').must_equal 'Value'
25
19
  end
26
20
 
27
21
  it 'strips the given value' do
28
- ActiveSupport::Inflector.expects(:camelize).with('feature_name').returns('FeatureName')
29
-
30
22
  Spinach::Support.camelize('feature name').must_equal 'FeatureName'
31
23
  end
32
24
  end
data/test/spinach_test.rb CHANGED
@@ -2,25 +2,25 @@ require_relative 'test_helper'
2
2
 
3
3
  describe Spinach do
4
4
  before do
5
- @feature1 = OpenStruct.new(feature_name: "User authentication")
6
- @feature2 = OpenStruct.new(feature_name: "Slip management")
7
- @feature3 = OpenStruct.new(feature_name: "File attachments")
8
- @feature4 = OpenStruct.new(name: "UserSendsAMessage")
5
+ @feature1 = OpenStruct.new(feature_name: 'User authentication')
6
+ @feature2 = OpenStruct.new(feature_name: 'Slip management')
7
+ @feature3 = OpenStruct.new(feature_name: 'File attachments')
8
+ @feature4 = OpenStruct.new(name: 'UserSendsAMessage')
9
9
  [@feature1, @feature2, @feature3, @feature4].each do |feature|
10
10
  Spinach.features << feature
11
11
  end
12
12
  end
13
13
 
14
- describe "#features" do
15
- it "returns all the loaded features" do
14
+ describe '#features' do
15
+ it 'returns all the loaded features' do
16
16
  Spinach.features.must_include @feature1
17
17
  Spinach.features.must_include @feature2
18
18
  Spinach.features.must_include @feature3
19
19
  end
20
20
  end
21
21
 
22
- describe "#reset_features" do
23
- it "resets the features to a pristine state" do
22
+ describe '#reset_features' do
23
+ it 'resets the features to a pristine state' do
24
24
  Spinach.reset_features
25
25
  [@feature1, @feature3, @feature3].each do |feature|
26
26
  Spinach.features.wont_include feature
@@ -28,14 +28,14 @@ describe Spinach do
28
28
  end
29
29
  end
30
30
 
31
- describe "#find_feature" do
32
- it "finds a feature by name" do
33
- Spinach.find_feature("User authentication").must_equal @feature1
34
- Spinach.find_feature("Slip management").must_equal @feature2
35
- Spinach.find_feature("File attachments").must_equal @feature3
31
+ describe '#find_feature' do
32
+ it 'finds a feature by name' do
33
+ Spinach.find_feature('User authentication').must_equal @feature1
34
+ Spinach.find_feature('Slip management').must_equal @feature2
35
+ Spinach.find_feature('File attachments').must_equal @feature3
36
36
  end
37
37
 
38
- describe "when a feature class does no set a feature_name" do
38
+ describe 'when a feature class does no set a feature_name' do
39
39
  it 'guesses the feature class from the feature name' do
40
40
  Spinach.find_feature('User sends a message').must_equal @feature4
41
41
  end
data/test/test_helper.rb CHANGED
@@ -1,17 +1,26 @@
1
1
  gem 'minitest'
2
- require 'minitest/unit'
2
+
3
+ if ENV['COVERAGE']
4
+ require 'simplecov'
5
+
6
+ SimpleCov.start do
7
+ add_filter '/test/'
8
+ add_filter '/features/'
9
+ end
10
+ end
11
+
12
+ require 'minitest/spec'
3
13
  require 'minitest/autorun'
4
14
  require 'mocha'
5
15
  require 'ostruct'
6
16
  require 'purdytest'
17
+ require 'stringio'
18
+ require 'pry'
7
19
 
8
20
  require 'spinach'
9
21
  require 'spinach/capybara'
10
22
 
11
- require 'stringio'
12
-
13
23
  module Kernel
14
-
15
24
  def capture_stdout
16
25
  out = StringIO.new
17
26
  $stdout = out
@@ -20,5 +29,4 @@ module Kernel
20
29
  ensure
21
30
  $stdout = STDOUT
22
31
  end
23
-
24
32
  end