yari 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module Yari
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,125 @@
1
+ class << self
2
+ def feature(name = nil, new_metadata = {}, &block)
3
+ raise ArgumentError.new("requires a name") if name.nil?
4
+
5
+ new_metadata = ::RSpec.configuration.feature_metadata.merge(new_metadata)
6
+ matching_feature = find_feature(name)
7
+ new_metadata[:feature_name]= name
8
+
9
+ if matching_feature
10
+ if matching_feature.tags.include?('@updated')
11
+ pending_feature(name, new_metadata, block.source_location,
12
+ "Feature has been marked as updated\n \t# Update specs for this feature and remove the @updated tag\n \t# Feature file: '#{feature_path(block.source_location)}"
13
+ )
14
+ else
15
+ describe("Feature: #{name}", new_metadata.merge(:current_feature => matching_feature), &block)
16
+ end
17
+ else
18
+ pending_feature(name, new_metadata, block.source_location, "No such feature in '#{feature_path(block.source_location)}'")
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def find_feature(name)
25
+ Yari.features.find do |feature|
26
+ feature.name == name
27
+ end
28
+ end
29
+
30
+ def feature_path(spec_location)
31
+ Yari.spec_to_feature(spec_location.first, false)
32
+ end
33
+
34
+ def pending_feature(name, new_metadata, spec_location, reason)
35
+ describe "Feature: #{name}", new_metadata do
36
+ it do |example|
37
+ example.metadata.merge!(
38
+ file_path: spec_location[0],
39
+ location: "#{spec_location[0]}:#{spec_location[1]}"
40
+ )
41
+ skip reason
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ module Yari
48
+ module DSL
49
+ module Rspec
50
+ def background(&block)
51
+ before(:each, &block)
52
+ end
53
+
54
+ def scenario(name = nil, new_metadata = {}, &block)
55
+ raise ArgumentError.new("requires a name") if name.nil?
56
+
57
+ matching_scenario = find_scenario(self.metadata[:current_feature], name)
58
+ new_metadata[:scenario_name]= name
59
+
60
+ if matching_scenario
61
+ if matching_scenario.tags.include?('@updated')
62
+ pending_scenario(name, new_metadata, block.source_location,
63
+ "Scenario has been marked as updated\n \t# Update specs for this scenario and remove the @updated tag\n \t# Feature file: '#{feature_path(block.source_location)}'"
64
+ )
65
+ # elsif matching_scenario.arguments
66
+ # specify "Scenario: #{name}", new_metadata do
67
+ # instance_exec(*matching_scenario.arguments, &block)
68
+ # end
69
+ else
70
+ specify("Scenario: #{name}", new_metadata, &block)
71
+ end
72
+ else
73
+ pending_scenario(name, new_metadata, block.source_location, "No such scenario in '#{feature_path(block.source_location)}'")
74
+ end
75
+ end
76
+
77
+
78
+ def scenario_with_test_cases(name = nil, new_metadata = {}, &block)
79
+ raise ArgumentError.new("requires a name") if name.nil?
80
+
81
+ matching_scenario = find_scenario(self.metadata[:current_feature], name)
82
+
83
+ if matching_scenario
84
+ if matching_scenario.tags.include?('@updated')
85
+ pending_scenario(name, new_metadata, block.source_location,
86
+ "Scenario has been marked as updated\n \t# Update specs for this scenario and remove the @updated tag\n \t# Feature file: '#{feature_path(block.source_location)}'"
87
+ )
88
+ else
89
+ describe("Scenario: #{name}", new_metadata.merge(:scenario_name => name), &block)
90
+ end
91
+ else
92
+ pending_scenario(name, new_metadata, block.source_location, "No such scenario in '#{feature_path(block.source_location)}'")
93
+ end
94
+ end
95
+
96
+ def test_case(name = nil, new_metadata = {}, &block)
97
+ raise ArgumentError.new("requires a name") if name.nil?
98
+ new_metadata[:test_case_name]= name
99
+ specify("Test_Case: #{name}", new_metadata, &block)
100
+ end
101
+
102
+ private
103
+
104
+ def find_scenario(feature, name)
105
+ feature.scenarios.find do |scenario|
106
+ scenario.name == name
107
+ end
108
+ end
109
+
110
+ def feature_path(spec_location)
111
+ Yari.spec_to_feature(spec_location.first, false)
112
+ end
113
+
114
+ def pending_scenario(name, new_metadata, spec_location, reason)
115
+ specify name, new_metadata do |example|
116
+ example.metadata.merge!(
117
+ full_description: "Scenario: #{name}",
118
+ location: "#{spec_location[0]}:#{spec_location[1]}"
119
+ )
120
+ skip reason
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,52 @@
1
+ require 'yari'
2
+ require 'rspec'
3
+
4
+ module Yari
5
+ module RSpec
6
+ module Loader
7
+ def load(*paths, &block)
8
+
9
+ # Override feature exclusion filter if running features
10
+ if paths.any? { |path| Yari.feature?(path) }
11
+ ::RSpec.configuration.filter_manager.exclusions.rules.reject! do |key, value|
12
+ key == :feature || (key == :type && value == 'feature')
13
+ end
14
+ end
15
+
16
+ paths = paths.map do |path|
17
+ if Yari.feature?(path)
18
+ spec_path = Yari.feature_to_spec(path)
19
+ if File.exist?(spec_path)
20
+ spec_path
21
+ else
22
+ Yari::Builder.build(path).features.each do |feature|
23
+ ::RSpec.describe("Feature: #{feature.name}", :type => :feature, :feature => true) do
24
+ it do |example|
25
+ example.metadata[:location] = path << ':1'
26
+ skip('No spec implemented for feature')
27
+ end
28
+ end
29
+ end
30
+ nil
31
+ end
32
+ else
33
+ path
34
+ end
35
+ end.compact
36
+
37
+ # Load needed features to Yari.features array
38
+ paths.each do |path|
39
+ if Yari.feature_spec?(path)
40
+ feature_path = Yari.spec_to_feature(path)
41
+
42
+ if File.exists?(feature_path)
43
+ Yari.features += Yari::Builder.build(feature_path).features
44
+ end
45
+ end
46
+ end
47
+
48
+ super(*paths, &block) if paths.size > 0
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Yari::Builder do
4
+
5
+ context 'a simple feature' do
6
+ let(:feature_file) { File.expand_path('../features/simple_feature.feature', File.dirname(__FILE__)) }
7
+ let(:builder) { Yari::Builder.build(feature_file) }
8
+ let(:feature) { builder.features.first }
9
+
10
+ it 'parses the feature' do
11
+ expect(feature).to be_a_kind_of(Yari::Feature)
12
+ expect(feature.name).to eq('A simple feature')
13
+ end
14
+
15
+ it 'gets all the scenarios in the feature' do
16
+ expect(feature.scenarios.count).to eq(4)
17
+ expect(feature.scenarios.first).to be_a_kind_of(Yari::Scenario)
18
+ expect(feature.scenarios.first.name).to eq('A simple scenario')
19
+ end
20
+
21
+ it 'gets tags associated with the feature' do
22
+ expect(feature.tags).to eq(['@feature_tag'])
23
+ end
24
+
25
+ it 'gets tags associated with the scenario' do
26
+ expect(feature.scenarios.first.tags).to eq(['@scenario_tag'])
27
+ end
28
+ end
29
+
30
+ context 'with scenario outlines' do
31
+ let(:feature_file) { File.expand_path('../features/scenario_outline.feature', File.dirname(__FILE__)) }
32
+ let(:builder) { Yari::Builder.build(feature_file) }
33
+ let(:feature) { builder.features.first }
34
+
35
+
36
+ it 'extracts scenario' do
37
+ expect(feature.scenarios.map(&:name)).to eq(['a simple outline'])
38
+ expect(feature.scenarios.first.type).to eq(:ScenarioOutline)
39
+ end
40
+
41
+ it 'extracts examples from an outline' do
42
+ expect(feature.scenarios.first.examples).to eq(Yari::Example)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'Missing feature' do
4
+ scenario 'This should never be executed' do
5
+ raise 'Scenario in spec with missing feature should not be executed'
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ feature 'Missing scenario' do
2
+ scenario 'Non-existing scenario' do
3
+ expect(1).to eq(1)
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'using scenario outlines' do
4
+ scenario 'a simple outline' do |hp, damage, state, happy|
5
+ expect(hp).to be_a(Float)
6
+ expect(damage).to be_a(Fixnum)
7
+ expect(state).to be_a(String)
8
+ expect([true, false]).to include happy
9
+ end
10
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'A simple feature' do
4
+ # ensure background is executed as before(:each)
5
+ background do
6
+ @number ||= 41
7
+ @number += 1
8
+ end
9
+
10
+ scenario 'A simple scenario' do
11
+ expect(@number).to eq(42)
12
+ end
13
+
14
+ scenario 'Raising error' do
15
+ raise ArgumentError.new("Your argument is invalid!")
16
+ end
17
+
18
+ scenario 'Different metadata type', :type => :controller, :feature => false do
19
+ expect(RSpec.current_example.metadata[:type]).to eq(:controller)
20
+ expect(RSpec.current_example.metadata[:feature]).to eq(false)
21
+ end
22
+
23
+ scenario 'Custom metadata tag', :custom => "foobar" do
24
+ expect(RSpec.current_example.metadata[:custom]).to eq("foobar")
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ feature 'A feature with test cases' do
2
+
3
+ scenario_with_test_cases 'A scenario requiring multiple cases to prove' do
4
+ test_case 'a passing test case' do
5
+ fail('the first test case failed')
6
+ end
7
+
8
+ test_case 'a failing test case' do
9
+ fail('the second test case also also failed')
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,11 @@
1
+ # This feature should be marked as pending
2
+ # because it is tagged as @updated in gherkin
3
+ feature 'Updated feature' do
4
+ scenario 'Attack a monster with cool tag' do
5
+ expect(1).to eq(1)
6
+ end
7
+
8
+ scenario 'Attack another monster' do
9
+ expect(1).to eq(1)
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # This feature should be marked as pending
2
+ # because it is tagged as @updated in gherkin
3
+ feature 'Feature with updated scenario' do
4
+ scenario 'Updated scenario' do
5
+ expect(1).to eq(1)
6
+ end
7
+
8
+ scenario 'Attack another monster' do
9
+ expect(1).to eq(1)
10
+ end
11
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'The CLI', :type => :integration do
4
+ context 'running features from features directory' do
5
+
6
+ it 'ignores --tag ~feature flag when running features' do
7
+ expect(%x(rspec features --tag ~feature 2>&1)).to include('11 examples, 3 failures, 3 pending')
8
+ end
9
+
10
+ it 'ignores --tag ~type:feature flag when running features' do
11
+ expect(%x(rspec features --tag ~type:feature 2>&1)).to include('11 examples, 3 failures, 3 pending')
12
+ end
13
+ end
14
+
15
+ context 'running features specs on their own' do
16
+ before(:all) do
17
+ @result = %x(rspec --tag feature --format documentation 2>&1)
18
+ end
19
+
20
+ it 'passes all specs' do
21
+ expect(@result).to include('11 examples, 3 failures, 4 pending')
22
+ end
23
+
24
+ it 'prepends features with "Feature: " prefix' do
25
+ expect(@result).to include('Feature: A simple feature')
26
+ end
27
+
28
+ it 'prepends scenarios with "Scenario: " prefix' do
29
+ expect(@result).to include('Scenario: A simple scenario')
30
+ end
31
+
32
+ context 'non-existing scenario' do
33
+ it 'shows name of non-existing scenario' do
34
+ expect(@result).to include("Scenario: Non-existing scenario")
35
+ end
36
+
37
+ it 'shows that spec implements non-existing scenario' do
38
+ expect(@result).to include("No such scenario in 'features/no_scenario.feature'")
39
+ end
40
+
41
+ it 'shows line number where missing scenario is mentioned' do
42
+ expect(@result).to include("/spec/features/no_scenario_spec.rb:2")
43
+ end
44
+ end
45
+
46
+ context 'non-existing feature' do
47
+ it 'shows name of non-existing feature' do
48
+ expect(@result).to include("Feature: Missing feature")
49
+ end
50
+
51
+ it 'shows that spec implements non-existing feature' do
52
+ expect(@result).to include("No such feature in 'features/no_feature.feature'")
53
+ end
54
+
55
+ it 'shows line number where missing scenario is mentioned' do
56
+ expect(@result).to include("/spec/features/no_feature_spec.rb:3")
57
+ end
58
+ end
59
+
60
+ context 'updated features and scenarios' do
61
+ it 'recognizes and notifies when feature is marked as @updated' do
62
+ expect(@result).to include('Feature has been marked as updated')
63
+ end
64
+
65
+ it 'recognizes and notifies when scenario is marked as @updated' do
66
+ expect(@result).to include('Scenario has been marked as updated')
67
+ end
68
+ end
69
+ end
70
+
71
+ # it "shows the correct description" do
72
+ # @result.should include('A simple feature')
73
+ # @result.should include('is a simple feature')
74
+ # end
75
+
76
+ # it "prints out failures and successes" do
77
+ # @result.should include('35 examples, 3 failures, 5 pending')
78
+ # end
79
+
80
+ # it "includes features in backtraces" do
81
+ # @result.should include('examples/errors.feature:5:in `raise error')
82
+ # end
83
+
84
+ # it "includes the right step name when steps call steps" do
85
+ # @result.should include("No such step: 'this is an unimplemented step'")
86
+ # end
87
+ end
@@ -0,0 +1,3 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+ require 'yari'
data/spec/yari_spec.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe Yari do
4
+ let(:feature_path) { '/project/features/awesome-def_file.feature' }
5
+ let(:spec_path) { '/project/spec/features/awesome-def_file_spec.rb' }
6
+
7
+ let(:short_feature_path) { 'features/awesome-def_file.feature' }
8
+ let(:short_spec_path) { 'spec/features/awesome-def_file_spec.rb' }
9
+
10
+ context '#feature?' do
11
+ it 'recognizes if path is feature path' do
12
+ expect(Yari.feature?(feature_path)).to eq(true)
13
+ end
14
+
15
+ it 'recognizes if path is not feature path' do
16
+ expect(Yari.feature?(spec_path)).to eq(false)
17
+ end
18
+ end
19
+
20
+ context '#feature_spec?' do
21
+ it 'recognizes if path is spec path' do
22
+ expect(Yari.feature_spec?(spec_path)).to eq(true)
23
+ end
24
+
25
+ it 'recognizes if path is not spec path' do
26
+ expect(Yari.feature_spec?(feature_path)).to eq(false)
27
+ end
28
+ end
29
+
30
+ context '#feature_to_spec' do
31
+ it 'properly translates feature file to spec file' do
32
+ expect(Yari.feature_to_spec(feature_path)).to eq(spec_path)
33
+ end
34
+
35
+ it 'excludes prefix when requested' do
36
+ expect(Yari.feature_to_spec(feature_path, false)).
37
+ to eq(short_spec_path)
38
+ end
39
+ end
40
+
41
+ context '#spec_to_feature' do
42
+ it 'properly translates spec file to feature file' do
43
+ expect(Yari.spec_to_feature(spec_path)).
44
+ to eq(feature_path)
45
+ end
46
+
47
+ it 'excludes prefix when requested' do
48
+ expect(Yari.spec_to_feature(spec_path, false)).
49
+ to eq(short_feature_path)
50
+ end
51
+ end
52
+
53
+ specify '#spec_to_feature and #feature_to_spec should be independent' do
54
+ p1 = Yari.feature_to_spec(Yari.spec_to_feature(spec_path))
55
+ p2 = Yari.feature_to_spec(feature_path)
56
+ expect(p1).to eq(p2)
57
+ end
58
+ end