Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 08ae32369773444ca93641d9e1b2bf5e443ae8f8 @jnicklas committed Oct 21, 2011
@@ -0,0 +1,4 @@
+*.gem
+.bundle
+Gemfile.lock
+pkg/*
@@ -0,0 +1 @@
+-r turnip
@@ -0,0 +1,4 @@
+source "http://rubygems.org"
+
+# Specify your gem's dependencies in turnip.gemspec
+gemspec
@@ -0,0 +1 @@
+require "bundler/gem_tasks"
@@ -0,0 +1,10 @@
+require "gherkin"
+require "gherkin/formatter/tag_count_formatter"
+
+require "carrot/version"
+require "carrot/loader"
+require "carrot/builder"
+require "carrot/run"
+require "carrot/steps"
+require "carrot/dsl"
+require "carrot/rspec"
@@ -0,0 +1,10 @@
+require "gherkin"
+require "gherkin/formatter/tag_count_formatter"
+
+require "turnip/version"
+require "turnip/loader"
+require "turnip/builder"
+require "turnip/run"
+require "turnip/steps"
+require "turnip/dsl"
+require "turnip/rspec"
@@ -0,0 +1,88 @@
+module Turnip
+ class Feature
+ attr_reader :scenarios, :backgrounds
+ def initialize(raw)
+ @raw = raw
+ @scenarios = []
+ @backgrounds = []
+ end
+
+ def name
+ @raw.name
+ end
+ end
+
+ class Background
+ attr_reader :steps
+ def initialize(raw)
+ @raw = raw
+ @steps = []
+ end
+ end
+
+ class Scenario
+ attr_reader :name, :steps
+ def initialize(raw)
+ @raw = raw
+ @steps = []
+ end
+
+ def name
+ @raw.name
+ end
+
+ def tags
+ @raw.tags.map { |tag| tag.name.sub(/^@/, '').to_sym }
+ end
+
+ def tags_hash
+ Hash[tags.map { |t| [t, true] }]
+ end
+
+ def metadata_hash
+ tags_hash
+ end
+ end
+
+ class Step
+ attr_reader :name
+ def initialize(raw)
+ @raw = raw
+ end
+
+ def name
+ @raw.name
+ end
+ end
+
+ class Builder
+ attr_reader :features
+
+ def initialize
+ @features = []
+ end
+
+ def background(background)
+ @current_step_context = Turnip::Background.new(background)
+ @current_feature.backgrounds << @current_step_context
+ end
+
+ def feature(feature)
+ @current_feature = Turnip::Feature.new(feature)
+ @features << @current_feature
+ end
+
+ def scenario(scenario)
+ @current_step_context = Turnip::Scenario.new(scenario)
+ @current_feature.scenarios << @current_step_context
+ end
+
+ def step(step)
+ @current_step = Turnip::Step.new(step)
+ @current_step_context.steps << @current_step
+ end
+
+ def eof
+ end
+ end
+end
@@ -0,0 +1,10 @@
+module Turnip
+ module DSL
+ def step(description, &block)
+ Turnip::Steps.add_step(description, &block)
+ end
+ end
+end
+
+self.extend Turnip::DSL
+
@@ -0,0 +1,13 @@
+module Turnip
+ module Loader
+ def load(*a, &b)
+ if a.first.end_with?('.feature')
+ require 'spec_helper'
+ content = File.read(a.first)
+ Turnip.run(content)
+ else
+ super
+ end
+ end
+ end
+end
@@ -0,0 +1,5 @@
+RSpec::Core::Configuration.send(:include, Turnip::Loader)
+
+RSpec.configure do |config|
+ config.pattern << ",**/*.feature"
+end
@@ -0,0 +1,27 @@
+module Turnip
+ def self.run(content)
+ builder = Turnip::Builder.new
+ formatter = Gherkin::Formatter::TagCountFormatter.new(builder, {})
+ parser = Gherkin::Parser::Parser.new(formatter, true, "root", false)
+ parser.parse(content, nil, 0)
+
+ builder.features.each do |feature|
+ describe feature.name do
+ feature.backgrounds.each do |background|
+ before do
+ background.steps.each do |step|
+ Turnip::Steps.execute_step(self, step.name)
+ end
+ end
+ end
+ feature.scenarios.each do |scenario|
+ it scenario.name, scenario.metadata_hash do
+ scenario.steps.each do |step|
+ Turnip::Steps.execute_step(self, step.name)
+ end
+ end
+ end
+ end
+ end
+ end
+end
@@ -0,0 +1,31 @@
+module Turnip
+ module Steps
+ class Pending < StandardError; end
+ class Ambiguous < StandardError; end
+
+ extend self
+
+ def execute_step(context, description)
+ context.instance_eval(&find_step(description))
+ rescue Pending
+ context.pending "the step '#{description}' is not implemented"
+ end
+
+ def add_step(description, &block)
+ steps << [description, block]
+ end
+
+ def find_step(description)
+ found = steps.select do |step|
+ step.first == description
+ end
+ raise Pending, description if found.length == 0
+ raise Ambiguous, description if found.length > 1
+ found[0][1]
+ end
+
+ def steps
+ @steps ||= []
+ end
+ end
+end
@@ -0,0 +1,3 @@
+module Turnip
+ VERSION = "0.1.0"
+end
@@ -0,0 +1,3 @@
+Feature: Ambiguous
+ Scenario: This is an ambiguous feature
+ Given this is ambiguous
@@ -0,0 +1,6 @@
+Feature: Feature with background
+ Background:
+ Given there is a monster
+ Scenario: simple scenario
+ When I attack it
+ Then it should die
@@ -0,0 +1,3 @@
+Feature: Pending
+ Scenario: This is a pending feature
+ Given there is an unimplemented step
@@ -0,0 +1,5 @@
+Feature: A simple feature
+ Scenario: This is a simple feature
+ Given there is a monster
+ When I attack it
+ Then it should die
@@ -0,0 +1,14 @@
+@awesome
+Feature: With tags
+ @cool
+ Scenario: Attack a monster with cool tag
+ Given there is a monster
+ When I attack it
+ Then it should die
+
+ @stealthy @wicked
+ Scenario: With multiple tags
+ Given there is a strong monster
+ When I attack it
+ And I attack it
+ Then it should die
@@ -0,0 +1,21 @@
+step "there is a monster" do
+ @monster = 1
+end
+
+step "there is a strong monster" do
+ @monster = 2
+end
+
+step "I attack it" do
+ @monster -= 1
+end
+
+step "it should die" do
+ @monster.should eq(0)
+end
+
+step "this is ambiguous" do
+end
+
+step "this is ambiguous" do
+end
@@ -0,0 +1,23 @@
+# -*- encoding: utf-8 -*-
+$:.push File.expand_path("../lib", __FILE__)
+require "turnip/version"
+
+Gem::Specification.new do |s|
+ s.name = "turnip"
+ s.version = Turnip::VERSION
+ s.authors = ["Jonas Nicklas"]
+ s.email = ["jonas.nicklas@gmail.com"]
+ s.homepage = ""
+ s.summary = %q{Gherkin extension for RSpec}
+ s.description = %q{Provides the ability to define steps and run Gherkin files from with RSpec}
+
+ s.rubyforge_project = "turnip"
+
+ s.files = `git ls-files`.split("\n")
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
+ s.require_paths = ["lib"]
+
+ s.add_runtime_dependency "rspec", "~>2.0"
+ s.add_runtime_dependency "gherkin"
+end

0 comments on commit 08ae323

Please sign in to comment.