rspec-gherkin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8c9bab3b667c903dfa4cf5449becaa7778099a1e
4
+ data.tar.gz: fe2a11c885696386a5adcc938dde4204fb571266
5
+ SHA512:
6
+ metadata.gz: c0fda6e78aa39013889fdb409ec4810ecad15e3757952e0661cbccb7e60a04a8149fcebcc56c16d257fc299f9c2cdb6af20b48845e117b06fd26c250f8b8d0f6
7
+ data.tar.gz: 871433b8d10a664de7be4147d9b4fdf4745508c9eb7aba85834cab997988d93326050cfbffe1bbda8ab946e3c335cf8b2d7601727c6728ea5a272b99ce46db47
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ bundler_stubs
4
+ Gemfile.lock
5
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ -r rspec-gherkin
2
+ --color
3
+ --tag ~feature
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ - ruby-head
5
+ - rbx-19mode
6
+ matrix:
7
+ allow_failures:
8
+ - rvm: ruby-head
9
+ script:
10
+ bundle exec rspec
11
+
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # RSpec Gherkin [![Build Status][travis-img-url]][travis-url]
2
+
3
+ [travis-img-url]: https://travis-ci.org/sheerun/rspec-gherkin.png
4
+ [travis-url]: https://travis-ci.org/rspec-gherkin
5
+
6
+ Different approach to Gherkin features in RSpec. It is based on two premises:
7
+
8
+ 1. Requirements are written by **business** in semi-formal, human-readable Gherkin.
9
+ 2. Automation of those is done by **programmers** in formal, machine-readable RSpec.
10
+
11
+ It resigns from the idea of regexp-parseable Cucumber features. As Uncle Bob [noticed in his article](http://blog.8thlight.com/uncle-bob/2013/09/26/AT-FAIL.html):
12
+
13
+ > I mean, the point was to get the *business* to provide a formal specification of the system so that the *programmers* could understand it. What in the name of heaven is the point of having the *programmers* write the formal specification so that the *programmers* can then understand it?
14
+
15
+ ## Installation
16
+
17
+ Add this gem to `test` group in `Gemfile`:
18
+
19
+ ```ruby
20
+ group :test do
21
+ gem 'rspec-gherkin'
22
+ end
23
+ ```
24
+
25
+ In your `spec_helper` include environment and `rspec-gherkin`:
26
+
27
+ ```ruby
28
+ require File.expand_path('../../config/environment', __FILE__)
29
+ require 'capybara/rails' # only for Rails
30
+ require 'rspec-gherkin'
31
+ ```
32
+
33
+ ## Basic Usage
34
+
35
+ 1. Put your requirements in `features` directory under application's root path:
36
+
37
+ ```
38
+ features/manage_articles.feature
39
+ ```
40
+
41
+ ```
42
+ Feature: Manage Articles
43
+ In order to make a blog
44
+ As an author
45
+ I want to create and manage articles
46
+
47
+ Scenario: Articles List
48
+ Given I have articles titled Pizza, Breadsticks
49
+ When I go to the list of articles
50
+ Then I should see "Pizza"
51
+ And I should see "Breadsticks"
52
+ ```
53
+
54
+ 2. Put specs for for those features in `spec/features` directory:
55
+
56
+ ```
57
+ spec/features/manage_articles_spec.rb
58
+ ```
59
+
60
+ ```ruby
61
+ require 'spec_helper'
62
+
63
+ feature 'Manage Articles' do
64
+ scenario 'Articles List' do
65
+ create(:article, :title => "Pizza")
66
+ create(:article, :title => "Breadsticks")
67
+ visit articles_path
68
+ expect(page).to have_content 'Pizza'
69
+ expect(page).to have_content 'Breadsticks'
70
+ end
71
+ end
72
+ ```
73
+
74
+ In specs you can use Capybara, FactoryGirl, helpers, and whatever you want.
75
+
76
+ You can run both `*.feature` files and `_spec.rb` spec as usual.
77
+
78
+ ```sh
79
+ # Run all features
80
+ rspec features
81
+ rspec spec/features
82
+ rspec --tag feature
83
+
84
+ # Run individual features
85
+ rspec features/manage_articles.feature
86
+ rspec spec/features/manage_articles_spec.rb
87
+ ```
88
+
89
+ You may want to add `--tag ~feature` to your `.rspec` file to not run
90
+ slow features specs by default.
91
+
92
+ ## Configuration
93
+
94
+ By default features in `features` directory are mapped to specs in `spec/features`.
95
+
96
+ Also each feature has an additional metadata: `{ :type => :feature, :feature => true }`.
97
+
98
+ You can change this by adding configuration options in `spec_helper`. Here are the defaults:
99
+
100
+ ```ruby
101
+ RSpec.configure do |config|
102
+ config.feature_mapping = {
103
+ :feature => 'features/**/*.feature',
104
+ :spec => 'spec/features/**/*_spec.rb'
105
+ }
106
+ config.feature_metadata = { :type => :feature, :feature => :true }
107
+ end
108
+ ```
109
+
110
+ ## FAQ
111
+
112
+ *How it differs from `capybara/rspec`*
113
+
114
+ It is an extension to it. `rspec-gherin` among others:
115
+
116
+ 1. Focuses on strong mapping between features and specs for them
117
+ 2. Allows for running feature files directly
118
+ 3. Notifies if any features/scenarios have pending specs
119
+ 4. Notifies if any specs have no matching features/scenarios
120
+ 5. Marks specs as pending if matchinf feature has been tagged as `@updated`
121
+ 6. Provides RSpec messages, indicating location of feature and spec files.
122
+
123
+ ## License
124
+
125
+ This gem is MIT-licensed. You are awesome.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ Feature: Missing scenario
@@ -0,0 +1,10 @@
1
+ Feature: using scenario outlines
2
+ Scenario Outline: a simple outline
3
+ Given there is a monster with <hp> hitpoints
4
+ When I attack the monster and do <damage> points damage
5
+ Then the monster should be <state>
6
+
7
+ Examples:
8
+ | hp | damage | state | happy |
9
+ | 10.0 | 13 | dead | false |
10
+ | 8.0 | 5 | alive | true |
@@ -0,0 +1,16 @@
1
+ Feature: A simple feature
2
+ Background:
3
+ Given we live in monster world
4
+ Scenario: A simple scenario
5
+ Given there is a monster
6
+ When I attack it
7
+ Then it should die
8
+ Scenario: Raising error
9
+ When Running this scenario
10
+ Then Error should be raisen
11
+ Scenario: Diferant metadata type
12
+ When Running this scenario
13
+ Then Type of this scenario should be :controller
14
+ Scenario: Custom metadata tag
15
+ When Running this scenario
16
+ Then Metadata should contain :custom key with 'foobar' value
@@ -0,0 +1,12 @@
1
+ @updated
2
+ Feature: Updated feature
3
+ Scenario: Attack a monster with cool tag
4
+ Given there is a monster
5
+ When I attack it
6
+ Then it should die
7
+
8
+ Scenario: Attack another monster
9
+ Given there is a strong monster
10
+ When I attack it
11
+ And I attack it
12
+ Then it should die
@@ -0,0 +1,12 @@
1
+ Feature: Feature with updated scenario
2
+ @updated
3
+ Scenario: Updated scenario
4
+ Given there is a monster
5
+ When I attack it
6
+ Then it should die
7
+
8
+ Scenario: Attack another monster
9
+ Given there is a strong monster
10
+ When I attack it
11
+ And I attack it
12
+ Then it should die
@@ -0,0 +1,157 @@
1
+ require "gherkin"
2
+
3
+ module RSpecGherkin
4
+ class Builder
5
+ module Tags
6
+ def tags
7
+ @raw.tags.map { |tag| tag.name.sub(/^@/, '') }
8
+ end
9
+
10
+ def tags_hash
11
+ Hash[tags.map { |t| [t.to_sym, true] }]
12
+ end
13
+
14
+ def metadata_hash
15
+ tags_hash
16
+ end
17
+ end
18
+
19
+ module Name
20
+ def name
21
+ @raw.name
22
+ end
23
+ end
24
+
25
+ class Feature
26
+ include Tags
27
+ include Name
28
+
29
+ attr_reader :scenarios, :backgrounds
30
+ attr_accessor :feature_tag
31
+
32
+ def initialize(raw)
33
+ @raw = raw
34
+ @scenarios = []
35
+ @backgrounds = []
36
+ end
37
+
38
+ def line
39
+ @raw.line
40
+ end
41
+ end
42
+
43
+ class Background
44
+ def initialize(raw)
45
+ @raw = raw
46
+ end
47
+ end
48
+
49
+ class Scenario
50
+ include Tags
51
+ include Name
52
+
53
+ attr_accessor :arguments
54
+
55
+ def initialize(raw)
56
+ @raw = raw
57
+ @arguments = []
58
+ end
59
+ end
60
+
61
+ class Step < Struct.new(:description, :extra_args, :line)
62
+ # 1.9.2 support hack
63
+ def split(*args)
64
+ self.to_s.split(*args)
65
+ end
66
+
67
+ def to_s
68
+ description
69
+ end
70
+ end
71
+
72
+ attr_reader :features
73
+
74
+ class << self
75
+ def build(feature_file)
76
+ RSpecGherkin::Builder.new.tap do |builder|
77
+ parser = Gherkin::Parser::Parser.new(builder, true)
78
+ parser.parse(File.read(feature_file), feature_file, 0)
79
+ end
80
+ end
81
+ end
82
+
83
+ def initialize
84
+ @features = []
85
+ end
86
+
87
+ def background(background)
88
+ @current_step_context = Background.new(background)
89
+ @current_feature.backgrounds << @current_step_context
90
+ end
91
+
92
+ def feature(feature)
93
+ @current_feature = Feature.new(feature)
94
+ @features << @current_feature
95
+ end
96
+
97
+ def scenario(scenario)
98
+ @current_step_context = Scenario.new(scenario)
99
+ @current_feature.scenarios << @current_step_context
100
+ end
101
+
102
+ def scenario_outline(outline)
103
+ @current_scenario_template = outline
104
+ end
105
+
106
+ def examples(examples)
107
+ rows_to_array(examples.rows).each do |arguments|
108
+ scenario = Scenario.new(@current_scenario_template)
109
+ scenario.arguments = arguments.map do |argument|
110
+ if numeric?(argument)
111
+ integer?(argument) ? argument.to_i : argument.to_f
112
+ elsif boolean?(argument)
113
+ to_bool(argument)
114
+ else
115
+ argument
116
+ end
117
+ end
118
+
119
+ @current_feature.scenarios << scenario
120
+ end
121
+ end
122
+
123
+ def step(*)
124
+ end
125
+
126
+ def uri(*)
127
+ end
128
+
129
+ def eof
130
+ end
131
+
132
+ private
133
+
134
+ def integer?(string)
135
+ return true if string =~ /^\d+$/
136
+ end
137
+
138
+ def numeric?(string)
139
+ return true if string =~ /^\d+$/
140
+ true if Float(string) rescue false
141
+ end
142
+
143
+ def boolean?(string)
144
+ string =~ (/(true|t|yes|y)$/i) ||
145
+ string =~ (/(false|f|no|n)$/i)
146
+ end
147
+
148
+ def to_bool(string)
149
+ return true if string =~ (/(true|t|yes|y|1)$/i)
150
+ return false if string =~ (/(false|f|no|n|0)$/i)
151
+ end
152
+
153
+ def rows_to_array(rows)
154
+ rows.map { |row| row.cells(&:value) }.drop(1)
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,112 @@
1
+ require "capybara/rspec" rescue nil
2
+
3
+ class << self
4
+ def feature(name = nil, new_metadata = {}, &block)
5
+ raise ArgumentError.new("requires a name") if name.nil?
6
+
7
+ new_metadata = ::RSpec.configuration.feature_metadata.merge(new_metadata)
8
+ matching_feature = find_feature(name)
9
+
10
+ if matching_feature
11
+ if matching_feature.tags.include?('updated')
12
+ pending_feature(name, new_metadata, block.source_location, [
13
+ "Feature has been marked as updated",
14
+ "Update specs for this feature and remove the @updated tag",
15
+ "Feature file: '#{feature_path(block.source_location)}'"
16
+ ])
17
+ else
18
+ describe("Feature: #{name}", new_metadata.merge(:current_feature => matching_feature), &block)
19
+ end
20
+ else
21
+ pending_feature(name, new_metadata, block.source_location,
22
+ "No such feature in '#{feature_path(block.source_location)}'"
23
+ )
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def find_feature(name)
30
+ RSpecGherkin.features.find do |feature|
31
+ feature.name == name
32
+ end
33
+ end
34
+
35
+ def feature_path(spec_location)
36
+ RSpecGherkin.spec_to_feature(spec_location.first, false)
37
+ end
38
+
39
+ def pending_feature(name, new_metadata, spec_location, reason)
40
+ describe "Feature: #{name}", new_metadata do
41
+ it do
42
+ example.metadata.merge!(
43
+ file_path: spec_location[0],
44
+ line_number: spec_location[1]
45
+ )
46
+
47
+ pending [*reason].join("\n # ")
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ module RSpecGherkin
54
+ module DSL
55
+ module Rspec
56
+ def background(&block)
57
+ before(:each, &block)
58
+ end
59
+
60
+ def scenario(name = nil, new_metadata = {}, &block)
61
+ raise ArgumentError.new("requires a name") if name.nil?
62
+
63
+ matching_scenario = find_scenario(self.metadata[:current_feature], name)
64
+
65
+ if matching_scenario
66
+ if matching_scenario.tags.include?('updated')
67
+ pending_scenario(name, new_metadata, block.source_location, [
68
+ "Scenario has been marked as updated",
69
+ "Update specs for this scenario and remove the @updated tag",
70
+ "Feature file: '#{feature_path(block.source_location)}'"
71
+ ])
72
+ elsif matching_scenario.arguments
73
+ specify "Scenario: #{name}", new_metadata do
74
+ instance_exec(*matching_scenario.arguments, &block)
75
+ end
76
+ else
77
+ specify("Scenario: #{name}", new_metadata, &block)
78
+ end
79
+ else
80
+ pending_scenario(name, new_metadata, block.source_location,
81
+ "No such scenario in '#{feature_path(block.source_location)}'"
82
+ )
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def find_scenario(feature, name)
89
+ feature.scenarios.find do |scenario|
90
+ scenario.name == name
91
+ end
92
+ end
93
+
94
+ def feature_path(spec_location)
95
+ RSpecGherkin.spec_to_feature(spec_location.first, false)
96
+ end
97
+
98
+ def pending_scenario(name, new_metadata, spec_location, reason)
99
+ specify name, new_metadata do
100
+ example.metadata.merge!(
101
+ file_path: spec_location[0],
102
+ line_number: spec_location[1]
103
+ )
104
+ example.metadata[:example_group].merge!(
105
+ description_args: ["Scenario:"]
106
+ )
107
+ pending [*reason].join("\n # ")
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,56 @@
1
+ require "rspec-gherkin"
2
+ require "rspec"
3
+
4
+ module RSpecGherkin
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| RSpecGherkin.feature?(path) }
11
+ ::RSpec.configuration.filter_manager.exclusions.reject! do |key, value|
12
+ key == :feature || (key == :type && value == 'feature')
13
+ end
14
+ end
15
+
16
+ paths = paths.map do |path|
17
+ if RSpecGherkin.feature?(path)
18
+ spec_path = RSpecGherkin.feature_to_spec(path)
19
+ if File.exist?(spec_path)
20
+ spec_path
21
+ else
22
+ RSpecGherkin::Builder.build(path).features.each do |feature|
23
+ ::RSpec::Core::ExampleGroup.describe(
24
+ "Feature: #{feature.name}", :type => :feature, :feature => true
25
+ ) do
26
+ it do
27
+ example.metadata[:file_path] = spec_path
28
+ example.metadata[:line_number] = 1
29
+ pending('Not yet implemented')
30
+ end
31
+ end.register
32
+ end
33
+
34
+ nil
35
+ end
36
+ else
37
+ path
38
+ end
39
+ end.compact
40
+
41
+ # Load needed features to RSpecGherkin.features array
42
+ paths.each do |path|
43
+ if RSpecGherkin.feature_spec?(path)
44
+ feature_path = RSpecGherkin.spec_to_feature(path)
45
+
46
+ if File.exists?(feature_path)
47
+ RSpecGherkin.features += RSpecGherkin::Builder.build(feature_path).features
48
+ end
49
+ end
50
+ end
51
+
52
+ super(*paths, &block) if paths.size > 0
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module RSpecGherkin
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,68 @@
1
+ require "rspec-gherkin/builder"
2
+ require "rspec-gherkin/rspec-dsl"
3
+ require "rspec-gherkin/rspec-loader"
4
+ require "rspec-gherkin/version"
5
+
6
+ module RSpecGherkin extend self
7
+
8
+ class << self
9
+ attr_accessor :features
10
+ end
11
+
12
+ class Pending < StandardError; end
13
+ class Malformed < StandardError; end
14
+ class Ambiguous < StandardError; end
15
+
16
+ def feature?(path)
17
+ !!path.match(mask_to_pattern(feature_mask))
18
+ end
19
+
20
+ def feature_spec?(path)
21
+ !!path.match(mask_to_pattern(spec_mask))
22
+ end
23
+
24
+ def feature_to_spec(path, prefix = true)
25
+ path = path.match(mask_to_pattern(feature_mask))[0] unless prefix
26
+ path.sub(mask_to_pattern(feature_mask), mask_to_replacement(spec_mask))
27
+ end
28
+
29
+ def spec_to_feature(path, prefix = true)
30
+ path = path.match(mask_to_pattern(spec_mask))[0] unless prefix
31
+ path.sub(mask_to_pattern(spec_mask), mask_to_replacement(feature_mask))
32
+ end
33
+
34
+ protected
35
+
36
+ def spec_mask
37
+ ::RSpec.configuration.feature_mapping[:spec]
38
+ end
39
+
40
+ def feature_mask
41
+ ::RSpec.configuration.feature_mapping[:feature]
42
+ end
43
+
44
+ def mask_to_pattern(mask)
45
+ Regexp.new("#{Regexp.escape(mask).sub("\\*\\*/\\*", '(.+)')}$")
46
+ end
47
+
48
+ def mask_to_replacement(mask)
49
+ "#{mask.sub('**/*'){ '\\1' }}"
50
+ end
51
+
52
+ end
53
+
54
+ RSpecGherkin.features = []
55
+
56
+ ::RSpec.configure do |config|
57
+ config.extend RSpecGherkin::DSL::Rspec
58
+ config.pattern << ",**/*.feature"
59
+ config.add_setting :feature_mapping
60
+ config.add_setting :feature_metadata
61
+ config.feature_mapping = {
62
+ :feature => 'features/**/*.feature',
63
+ :spec => 'spec/features/**/*_spec.rb'
64
+ }
65
+ config.feature_metadata = { :type => :feature, :feature => :true }
66
+ end
67
+
68
+ ::RSpec::Core::Configuration.send(:include, RSpecGherkin::RSpec::Loader)
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rspec-gherkin/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rspec-gherkin"
7
+ s.version = RSpecGherkin::VERSION
8
+ s.authors = ["Adam Stankiewicz"]
9
+ s.email = ["sheerun@sher.pl"]
10
+ s.homepage = ""
11
+ s.summary = %q{Different approach to Gherkin features in RSpec}
12
+ s.description = %q{Different approach to Gherkin features in RSpec}
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_runtime_dependency "rspec", "~> 2.0"
20
+ s.add_runtime_dependency "gherkin", ">= 2.5"
21
+ s.add_development_dependency "rake"
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpecGherkin::Builder do
4
+ context "with scenario outlines" do
5
+ let(:feature_file) { File.expand_path('../features/scenario_outline.feature', File.dirname(__FILE__)) }
6
+ let(:builder) { RSpecGherkin::Builder.build(feature_file) }
7
+ let(:feature) { builder.features.first }
8
+
9
+ it "extracts scenario" do
10
+ feature.scenarios.map(&:name).should eq([
11
+ 'a simple outline',
12
+ 'a simple outline'
13
+ ])
14
+ end
15
+
16
+ it "add additional arguments to scenarios" do
17
+ feature.scenarios[0].arguments.should eq([ 10.0, 13, "dead", false ])
18
+ feature.scenarios[1].arguments.should eq([ 8.0, 5, "alive", true ])
19
+ end
20
+ end
21
+ 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 'Diferant metadata type', :type => :controller, :feature => false do
19
+ expect(example.metadata[:type]).to eq(:controller)
20
+ expect(example.metadata[:feature]).to eq(false)
21
+ end
22
+
23
+ scenario 'Custom metadata tag', :custom => "foobar" do
24
+ expect(example.metadata[:custom]).to eq("foobar")
25
+ end
26
+ 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,104 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'The CLI', :type => :integration do
4
+ context 'runing features from features directory' do
5
+ it 'ignores --tag ~feature flag when running features' do
6
+ expect(%x(rspec features --tag ~feature 2>&1)).
7
+ to include('9 examples, 1 failure, 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)).
12
+ to include('9 examples, 1 failure, 3 pending')
13
+ end
14
+ end
15
+
16
+ context 'runing features specs on their own' do
17
+ before(:all) do
18
+ @result = %x(rspec --tag feature --format documentation 2>&1)
19
+ end
20
+
21
+ it 'passes all specs' do
22
+ expect(@result).to include('9 examples, 1 failure, 4 pending')
23
+ end
24
+
25
+ it 'prepends features with "Feature: " prefix' do
26
+ expect(@result).to include('Feature: A simple feature')
27
+ end
28
+
29
+ it 'prepends scenarios with "Scenario: " prefix' do
30
+ expect(@result).to include('Scenario: A simple scenario')
31
+ end
32
+
33
+ context 'non-existing scenario' do
34
+ it 'shows name of non-existing scenario' do
35
+ expect(@result).to include(
36
+ "Scenario: Non-existing scenario"
37
+ )
38
+ end
39
+
40
+ it 'shows that spec implements non-existing scenario' do
41
+ expect(@result).to include(
42
+ "No such scenario in 'features/no_scenario.feature'"
43
+ )
44
+ end
45
+
46
+ it 'shows line number where missing scenario is mentioned' do
47
+ expect(@result).to include(
48
+ "./spec/features/no_scenario_spec.rb:2"
49
+ )
50
+ end
51
+ end
52
+
53
+ context 'non-existing feature' do
54
+ it 'shows name of non-existing feature' do
55
+ expect(@result).to include(
56
+ "Feature: Missing feature"
57
+ )
58
+ end
59
+
60
+ it 'shows that spec implements non-existing feature' do
61
+ expect(@result).to include(
62
+ "No such feature in 'features/no_feature.feature'"
63
+ )
64
+ end
65
+
66
+ it 'shows line number where missing scenario is mentioned' do
67
+ expect(@result).to include(
68
+ "./spec/features/no_feature_spec.rb:3"
69
+ )
70
+ end
71
+ end
72
+
73
+ context 'updated features and scenarios' do
74
+ it 'recognizes and notifies when feature is marked as @updated' do
75
+ expect(@result).to include(
76
+ 'Feature has been marked as updated'
77
+ )
78
+ end
79
+
80
+ it 'recognizes and notifies when scenario is marked as @updated' do
81
+ expect(@result).to include(
82
+ 'Scenario has been marked as updated'
83
+ )
84
+ end
85
+ end
86
+ end
87
+
88
+ # it "shows the correct description" do
89
+ # @result.should include('A simple feature')
90
+ # @result.should include('is a simple feature')
91
+ # end
92
+
93
+ # it "prints out failures and successes" do
94
+ # @result.should include('35 examples, 3 failures, 5 pending')
95
+ # end
96
+
97
+ # it "includes features in backtraces" do
98
+ # @result.should include('examples/errors.feature:5:in `raise error')
99
+ # end
100
+
101
+ # it "includes the right step name when steps call steps" do
102
+ # @result.should include("No such step: 'this is an unimplemented step'")
103
+ # end
104
+ end
@@ -0,0 +1,56 @@
1
+ describe RSpecGherkin do
2
+ let(:feature_path) { '/project/features/awesome-def_file.feature' }
3
+ let(:spec_path) { '/project/spec/features/awesome-def_file_spec.rb' }
4
+
5
+ let(:short_feature_path) { 'features/awesome-def_file.feature' }
6
+ let(:short_spec_path) { 'spec/features/awesome-def_file_spec.rb' }
7
+
8
+ context '#feature?' do
9
+ it 'recognizes if path is feature path' do
10
+ expect(RSpecGherkin.feature?(feature_path)).to eq(true)
11
+ end
12
+
13
+ it 'recognizes if path is not feature path' do
14
+ expect(RSpecGherkin.feature?(spec_path)).to eq(false)
15
+ end
16
+ end
17
+
18
+ context '#feature_spec?' do
19
+ it 'recognizes if path is spec path' do
20
+ expect(RSpecGherkin.feature_spec?(spec_path)).to eq(true)
21
+ end
22
+
23
+ it 'recognizes if path is not spec path' do
24
+ expect(RSpecGherkin.feature_spec?(feature_path)).to eq(false)
25
+ end
26
+ end
27
+
28
+ context '#feature_to_spec' do
29
+ it 'properly translates feature file to spec file' do
30
+ expect(RSpecGherkin.feature_to_spec(feature_path)).to eq(spec_path)
31
+ end
32
+
33
+ it 'excludes prefix when requested' do
34
+ expect(RSpecGherkin.feature_to_spec(feature_path, false)).
35
+ to eq(short_spec_path)
36
+ end
37
+ end
38
+
39
+ context '#spec_to_feature' do
40
+ it 'properly translates spec file to feature file' do
41
+ expect(RSpecGherkin.spec_to_feature(spec_path)).
42
+ to eq(feature_path)
43
+ end
44
+
45
+ it 'excludes prefix when requested' do
46
+ expect(RSpecGherkin.spec_to_feature(spec_path, false)).
47
+ to eq(short_feature_path)
48
+ end
49
+ end
50
+
51
+ specify '#spec_to_feature and #feature_to_spec should be idempotent' do
52
+ p1 = RSpecGherkin.feature_to_spec(RSpecGherkin.spec_to_feature(spec_path))
53
+ p2 = RSpecGherkin.feature_to_spec(feature_path)
54
+ expect(p1).to eq(p2)
55
+ end
56
+ end
File without changes
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-gherkin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Stankiewicz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gherkin
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '2.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '2.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Different approach to Gherkin features in RSpec
56
+ email:
57
+ - sheerun@sher.pl
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - .gitignore
63
+ - .rspec
64
+ - .travis.yml
65
+ - Gemfile
66
+ - README.md
67
+ - Rakefile
68
+ - features/no_scenario.feature
69
+ - features/scenario_outline.feature
70
+ - features/simple_feature.feature
71
+ - features/updated_feature.feature
72
+ - features/updated_scenario.feature
73
+ - lib/rspec-gherkin.rb
74
+ - lib/rspec-gherkin/builder.rb
75
+ - lib/rspec-gherkin/rspec-dsl.rb
76
+ - lib/rspec-gherkin/rspec-loader.rb
77
+ - lib/rspec-gherkin/version.rb
78
+ - rspec-gherkin.gemspec
79
+ - spec/builder_spec.rb
80
+ - spec/features/no_feature_spec.rb
81
+ - spec/features/no_scenario_spec.rb
82
+ - spec/features/scenario_outline_spec.rb
83
+ - spec/features/simple_feature_spec.rb
84
+ - spec/features/updated_feature_spec.rb
85
+ - spec/features/updated_scenario_spec.rb
86
+ - spec/integration_spec.rb
87
+ - spec/rspec-gherkin_spec.rb
88
+ - spec/spec_helper.rb
89
+ homepage: ''
90
+ licenses: []
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.0.3
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Different approach to Gherkin features in RSpec
112
+ test_files:
113
+ - features/no_scenario.feature
114
+ - features/scenario_outline.feature
115
+ - features/simple_feature.feature
116
+ - features/updated_feature.feature
117
+ - features/updated_scenario.feature
118
+ - spec/builder_spec.rb
119
+ - spec/features/no_feature_spec.rb
120
+ - spec/features/no_scenario_spec.rb
121
+ - spec/features/scenario_outline_spec.rb
122
+ - spec/features/simple_feature_spec.rb
123
+ - spec/features/updated_feature_spec.rb
124
+ - spec/features/updated_scenario_spec.rb
125
+ - spec/integration_spec.rb
126
+ - spec/rspec-gherkin_spec.rb
127
+ - spec/spec_helper.rb
128
+ has_rdoc: