Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Initial commit

  • Loading branch information...
commit 08ae32369773444ca93641d9e1b2bf5e443ae8f8 0 parents
Jonas Nicklas authored
4 .gitignore
... ... @@ -0,0 +1,4 @@
  1 +*.gem
  2 +.bundle
  3 +Gemfile.lock
  4 +pkg/*
1  .rspec
... ... @@ -0,0 +1 @@
  1 +-r turnip
4 Gemfile
... ... @@ -0,0 +1,4 @@
  1 +source "http://rubygems.org"
  2 +
  3 +# Specify your gem's dependencies in turnip.gemspec
  4 +gemspec
1  Rakefile
... ... @@ -0,0 +1 @@
  1 +require "bundler/gem_tasks"
10 lib/carrot.rb
... ... @@ -0,0 +1,10 @@
  1 +require "gherkin"
  2 +require "gherkin/formatter/tag_count_formatter"
  3 +
  4 +require "carrot/version"
  5 +require "carrot/loader"
  6 +require "carrot/builder"
  7 +require "carrot/run"
  8 +require "carrot/steps"
  9 +require "carrot/dsl"
  10 +require "carrot/rspec"
10 lib/turnip.rb
... ... @@ -0,0 +1,10 @@
  1 +require "gherkin"
  2 +require "gherkin/formatter/tag_count_formatter"
  3 +
  4 +require "turnip/version"
  5 +require "turnip/loader"
  6 +require "turnip/builder"
  7 +require "turnip/run"
  8 +require "turnip/steps"
  9 +require "turnip/dsl"
  10 +require "turnip/rspec"
88 lib/turnip/builder.rb
... ... @@ -0,0 +1,88 @@
  1 +module Turnip
  2 + class Feature
  3 + attr_reader :scenarios, :backgrounds
  4 + def initialize(raw)
  5 + @raw = raw
  6 + @scenarios = []
  7 + @backgrounds = []
  8 + end
  9 +
  10 + def name
  11 + @raw.name
  12 + end
  13 + end
  14 +
  15 + class Background
  16 + attr_reader :steps
  17 + def initialize(raw)
  18 + @raw = raw
  19 + @steps = []
  20 + end
  21 + end
  22 +
  23 + class Scenario
  24 + attr_reader :name, :steps
  25 + def initialize(raw)
  26 + @raw = raw
  27 + @steps = []
  28 + end
  29 +
  30 + def name
  31 + @raw.name
  32 + end
  33 +
  34 + def tags
  35 + @raw.tags.map { |tag| tag.name.sub(/^@/, '').to_sym }
  36 + end
  37 +
  38 + def tags_hash
  39 + Hash[tags.map { |t| [t, true] }]
  40 + end
  41 +
  42 + def metadata_hash
  43 + tags_hash
  44 + end
  45 + end
  46 +
  47 + class Step
  48 + attr_reader :name
  49 + def initialize(raw)
  50 + @raw = raw
  51 + end
  52 +
  53 + def name
  54 + @raw.name
  55 + end
  56 + end
  57 +
  58 + class Builder
  59 + attr_reader :features
  60 +
  61 + def initialize
  62 + @features = []
  63 + end
  64 +
  65 + def background(background)
  66 + @current_step_context = Turnip::Background.new(background)
  67 + @current_feature.backgrounds << @current_step_context
  68 + end
  69 +
  70 + def feature(feature)
  71 + @current_feature = Turnip::Feature.new(feature)
  72 + @features << @current_feature
  73 + end
  74 +
  75 + def scenario(scenario)
  76 + @current_step_context = Turnip::Scenario.new(scenario)
  77 + @current_feature.scenarios << @current_step_context
  78 + end
  79 +
  80 + def step(step)
  81 + @current_step = Turnip::Step.new(step)
  82 + @current_step_context.steps << @current_step
  83 + end
  84 +
  85 + def eof
  86 + end
  87 + end
  88 +end
10 lib/turnip/dsl.rb
... ... @@ -0,0 +1,10 @@
  1 +module Turnip
  2 + module DSL
  3 + def step(description, &block)
  4 + Turnip::Steps.add_step(description, &block)
  5 + end
  6 + end
  7 +end
  8 +
  9 +self.extend Turnip::DSL
  10 +
13 lib/turnip/loader.rb
... ... @@ -0,0 +1,13 @@
  1 +module Turnip
  2 + module Loader
  3 + def load(*a, &b)
  4 + if a.first.end_with?('.feature')
  5 + require 'spec_helper'
  6 + content = File.read(a.first)
  7 + Turnip.run(content)
  8 + else
  9 + super
  10 + end
  11 + end
  12 + end
  13 +end
5 lib/turnip/rspec.rb
... ... @@ -0,0 +1,5 @@
  1 +RSpec::Core::Configuration.send(:include, Turnip::Loader)
  2 +
  3 +RSpec.configure do |config|
  4 + config.pattern << ",**/*.feature"
  5 +end
27 lib/turnip/run.rb
... ... @@ -0,0 +1,27 @@
  1 +module Turnip
  2 + def self.run(content)
  3 + builder = Turnip::Builder.new
  4 + formatter = Gherkin::Formatter::TagCountFormatter.new(builder, {})
  5 + parser = Gherkin::Parser::Parser.new(formatter, true, "root", false)
  6 + parser.parse(content, nil, 0)
  7 +
  8 + builder.features.each do |feature|
  9 + describe feature.name do
  10 + feature.backgrounds.each do |background|
  11 + before do
  12 + background.steps.each do |step|
  13 + Turnip::Steps.execute_step(self, step.name)
  14 + end
  15 + end
  16 + end
  17 + feature.scenarios.each do |scenario|
  18 + it scenario.name, scenario.metadata_hash do
  19 + scenario.steps.each do |step|
  20 + Turnip::Steps.execute_step(self, step.name)
  21 + end
  22 + end
  23 + end
  24 + end
  25 + end
  26 + end
  27 +end
31 lib/turnip/steps.rb
... ... @@ -0,0 +1,31 @@
  1 +module Turnip
  2 + module Steps
  3 + class Pending < StandardError; end
  4 + class Ambiguous < StandardError; end
  5 +
  6 + extend self
  7 +
  8 + def execute_step(context, description)
  9 + context.instance_eval(&find_step(description))
  10 + rescue Pending
  11 + context.pending "the step '#{description}' is not implemented"
  12 + end
  13 +
  14 + def add_step(description, &block)
  15 + steps << [description, block]
  16 + end
  17 +
  18 + def find_step(description)
  19 + found = steps.select do |step|
  20 + step.first == description
  21 + end
  22 + raise Pending, description if found.length == 0
  23 + raise Ambiguous, description if found.length > 1
  24 + found[0][1]
  25 + end
  26 +
  27 + def steps
  28 + @steps ||= []
  29 + end
  30 + end
  31 +end
3  lib/turnip/version.rb
... ... @@ -0,0 +1,3 @@
  1 +module Turnip
  2 + VERSION = "0.1.0"
  3 +end
3  spec/fixture/ambiguous.feature
... ... @@ -0,0 +1,3 @@
  1 +Feature: Ambiguous
  2 + Scenario: This is an ambiguous feature
  3 + Given this is ambiguous
6 spec/fixture/backgrounds.feature
... ... @@ -0,0 +1,6 @@
  1 +Feature: Feature with background
  2 + Background:
  3 + Given there is a monster
  4 + Scenario: simple scenario
  5 + When I attack it
  6 + Then it should die
3  spec/fixture/pending.feature
... ... @@ -0,0 +1,3 @@
  1 +Feature: Pending
  2 + Scenario: This is a pending feature
  3 + Given there is an unimplemented step
5 spec/fixture/simple_feature.feature
... ... @@ -0,0 +1,5 @@
  1 +Feature: A simple feature
  2 + Scenario: This is a simple feature
  3 + Given there is a monster
  4 + When I attack it
  5 + Then it should die
14 spec/fixture/tags.feature
... ... @@ -0,0 +1,14 @@
  1 +@awesome
  2 +Feature: With tags
  3 + @cool
  4 + Scenario: Attack a monster with cool tag
  5 + Given there is a monster
  6 + When I attack it
  7 + Then it should die
  8 +
  9 + @stealthy @wicked
  10 + Scenario: With multiple tags
  11 + Given there is a strong monster
  12 + When I attack it
  13 + And I attack it
  14 + Then it should die
21 spec/spec_helper.rb
... ... @@ -0,0 +1,21 @@
  1 +step "there is a monster" do
  2 + @monster = 1
  3 +end
  4 +
  5 +step "there is a strong monster" do
  6 + @monster = 2
  7 +end
  8 +
  9 +step "I attack it" do
  10 + @monster -= 1
  11 +end
  12 +
  13 +step "it should die" do
  14 + @monster.should eq(0)
  15 +end
  16 +
  17 +step "this is ambiguous" do
  18 +end
  19 +
  20 +step "this is ambiguous" do
  21 +end
23 turnip.gemspec
... ... @@ -0,0 +1,23 @@
  1 +# -*- encoding: utf-8 -*-
  2 +$:.push File.expand_path("../lib", __FILE__)
  3 +require "turnip/version"
  4 +
  5 +Gem::Specification.new do |s|
  6 + s.name = "turnip"
  7 + s.version = Turnip::VERSION
  8 + s.authors = ["Jonas Nicklas"]
  9 + s.email = ["jonas.nicklas@gmail.com"]
  10 + s.homepage = ""
  11 + s.summary = %q{Gherkin extension for RSpec}
  12 + s.description = %q{Provides the ability to define steps and run Gherkin files from with RSpec}
  13 +
  14 + s.rubyforge_project = "turnip"
  15 +
  16 + s.files = `git ls-files`.split("\n")
  17 + s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
  18 + s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
  19 + s.require_paths = ["lib"]
  20 +
  21 + s.add_runtime_dependency "rspec", "~>2.0"
  22 + s.add_runtime_dependency "gherkin"
  23 +end

0 comments on commit 08ae323

Please sign in to comment.
Something went wrong with that request. Please try again.