Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactored around my fork of lispy (0.1.2)

  • Loading branch information...
commit fe2618bdc93a57affc221a78637f8ff2750b550c 1 parent 1c4c3b9
Evan Light authored
View
3  Rakefile
@@ -2,6 +2,9 @@ require 'rubygems'
require 'rake'
require 'rake/testtask'
+require File.join(File.dirname(__FILE__), 'lib', 'coulda', 'tasks')
+
+
gem 'shoulda'
require 'shoulda'
View
59 lib/coulda.rb
@@ -1,40 +1,33 @@
require 'test/unit'
+require 'lispy'
require File.join(File.dirname(__FILE__), 'coulda', 'world')
-require File.join(File.dirname(__FILE__), 'coulda', 'feature')
-require File.join(File.dirname(__FILE__), 'coulda', 'scenario')
require File.join(File.dirname(__FILE__), 'coulda', 'pending')
require File.join(File.dirname(__FILE__), 'coulda', 'vendor', 'constantize')
require File.join(File.dirname(__FILE__), 'coulda', 'vendor', 'underscore')
require File.join(File.dirname(__FILE__), 'coulda', 'tasks')
module Coulda
- SyntaxError = Class.new(StandardError)
+ PROC_KEYWORDS = [:Given, :When, :Then, :And]
+ KEYWORDS = [:Scenario, :Tag, :in_order_to, :as_a, :i_want_to] + PROC_KEYWORDS
- def Tag(name)
- @feature_tags ||= []
- @feature_tags << name.to_s
- end
+ SyntaxError = Class.new(StandardError)
# Factory method for Test::Unit::TestCase subclasses
def Feature(name, opts = {}, &block)
- process_command_line_tags
-
- if @requested_tags && !@requested_tags.empty?
- if @feature_tags.nil? || !@feature_tags.any? { |f_tag| @requested_tags.include? f_tag}
- @feature_tags = nil
- return
- end
- end
- @feature_tags = nil
-
test_class = Class.new(opts[:testcase_class] || Coulda.default_testcase_class || Test::Unit::TestCase)
- World.register_feature(test_class, name)
- Coulda::assign_class_to_const test_class, name
+ assign_class_to_const test_class, name
+ test_class.send(:extend, Lispy)
+ test_class.instance_eval do
+ extend Lispy
+ acts_lispy :only => Coulda::KEYWORDS, :retain_blocks_for => Coulda::PROC_KEYWORDS
+ end
test_class.class_eval &block if block_given?
- test_class.assert_presence_of_intent
+ World.register_feature(name, test_class.output)
+
+ generate_test_methods_from test_class
test_class
end
@@ -50,6 +43,8 @@ def self.default_testcase_class
@class
end
+ private
+
def assign_class_to_const(test_class, potential_const)
base_name = potential_const
if potential_const !~ /^[a-zA-Z]/
@@ -59,11 +54,25 @@ def assign_class_to_const(test_class, potential_const)
Object.const_set(titleized_underscored_name, test_class)
end
- def process_command_line_tags
- unless @processed_cmd_line_args
- @processed_cmd_line_args = true
- tags = ARGV.inject([]) { |m, a| m << a if a =~ /^tags=/; m }
- @requested_tags = tags.map { |t| t.split("=")[1].split(",") }.flatten
+ def generate_test_methods_from(test_class)
+ file_name = test_class.output.first
+ test_class.output.each do |sexp|
+ next if sexp.is_a? String
+ next unless sexp[1] == :Scenario
+
+ test_class.send(:define_method,"test_#{sexp[2].downcase.super_custom_underscore}") do
+ if sexp.length == 3
+ coulda_pending "Scenario '#{sexp[2]}' in #{file_name}:#{sexp[0]}"
+ else
+ sexp[3].each do |step_sexp|
+ if step_sexp.length == 3
+ coulda_pending "Scenario '#{sexp[2]}': #{step_sexp[1]} '#{step_sexp[2]} in #{file_name}:#{step_sexp[0]}"
+ else
+ instance_eval &step_sexp[3]
+ end
+ end
+ end
+ end
end
end
end
View
65 lib/coulda/feature.rb
@@ -1,65 +0,0 @@
-module Test
- module Unit
- class TestCase
- include Coulda
-
- def self.scenarios
- @scenarios ||= []
- @scenarios
- end
-
- def self.current_scenario=(scenario)
- @current_scenario = scenario
- end
-
- def self.current_scenario
- @current_scenario
- end
-
- %w[in_order_to as_a i_want_to].each do |intent|
- eval <<-HERE
- # An intent specifier
- def self.#{intent}(val = nil)
- val ? @#{intent} = val : @#{intent}
- end
- HERE
- end
-
- %w[Given When Then And].each do |stmt|
- eval <<-HERE
- # Specifies a prereqisite, event, or expectation. May be used in any order within the spec
- def self.#{stmt}(text, &block)
- step = nil
- if block_given?
- step = block
- end
- caller[0] =~ (/(.*):(.*)(:in)?/)
- stmt = { :type => :#{stmt}, :text => text, :block => step, :file => $1, :line => $2 }
- if text.is_a? Symbol
- stmt[:method] = text
- end
- current_scenario.statements << stmt
- end
- HERE
- end
-
- def Tag(name)
- end
-
- # Creates a Scenario instance and adds it to the Feature
- def self.Scenario(scenario_name, &block)
- @scenarios ||=[]
- @scenarios << scenario = Scenario.new(scenario_name, self, &block)
- scenario
- end
-
- # Raises an error if only some of the intent is captured (i.e., in_order_to and as_a without i_want_to)
- def self.assert_presence_of_intent
- presence = %w[in_order_to as_a i_want_to].map { |intent| instance_variable_get("@#{intent}") }
- if presence.any? { |p| p } && !presence.all? { |p| p }
- raise SyntaxError.new("Must have all or none of in_order, as_a, and i_want_to called in a Feature")
- end
- end
- end
- end
-end
View
61 lib/coulda/scenario.rb
@@ -1,61 +0,0 @@
-module Coulda
- # A factory for Test::Unit::TestCase test methods
- class Scenario
- attr_reader :name, :test_class
- attr_accessor :statements
-
- def initialize(name, my_feature, &block)
- raise Exception.new("Scenario must have a name") unless name
- @name = name
- @statements = []
- @my_feature = my_feature
- create_and_provision_test_method_using &block
- end
-
- # Predicate indicating if the Scenario was provided with an example
- def pending?
- statements.empty? || has_pending_statements?
- end
-
- private
-
- def create_and_provision_test_method_using(&block)
- collect_scenario_statements_from &block
- define_test_method_using do
- self.class.current_scenario.statements.each do |stmt|
- if stmt[:method]
- if stmt[:block]
- raise Exception.new "Passing a block to a method called-by-name is currently unhandle"
- else
- self.class.__send__(stmt[:method])
- end
- elsif stmt[:block]
- self.instance_eval &(stmt[:block])
- else
- coulda_pending "#{stmt[:file]}:#{stmt[:line]}: Scenario '#{scenario.name}': #{stmt[:type]} '#{stmt[:text]}'"
- break
- end
- end
- end
- end
-
- def collect_scenario_statements_from(&block)
- @my_feature.current_scenario = self
- if block_given?
- @my_feature.instance_eval &block
- end
- end
-
- def define_test_method_using(&block)
- scenario = self
- @my_feature.send(:define_method, "test_#{@name.downcase.super_custom_underscore}") do
- self.class.current_scenario = scenario
- self.instance_eval &block if block
- end
- end
-
- def has_pending_statements?
- statements.find { |s| s[:block].nil? && s[:method].nil? }
- end
- end
-end
View
4 lib/coulda/world.rb
@@ -1,7 +1,7 @@
module Coulda
class World
- def self.register_feature(feature, name)
- (@features ||= []) << [feature, name]
+ def self.register_feature(feature, sexp)
+ (@features ||= []) << [feature, sexp]
end
def self.features
View
40 lib/tasks/print_features.rake
@@ -9,32 +9,40 @@ namespace :coulda do
require 'test/unit'
# bug in test unit. Set to true to stop from running.
- Test::Unit.run = true
+ unless RUBY_VERSION =~ /^1.9/
+ Test::Unit.run = true
+ end
- require 'coulda'
test_files = Dir.glob(File.join('test', '**', '*_test.rb'))
test_files.each do |file|
load file
end
- Coulda::World.features.each do |feature, name|
+ Coulda::World.features.each do |name, sexps|
puts "Feature: #{name}"
- puts " In order to #{feature.in_order_to}" if feature.in_order_to
- puts " As a #{feature.as_a}" if feature.as_a
- puts " I want to #{feature.i_want_to}" if feature.i_want_to
- feature.scenarios.each do |scenario|
- puts
- print " "
- print "(**PENDING**) " if scenario.pending?
- puts "Scenario: #{scenario.name}"
- scenario.statements.each do |stmt|
- print " "
- print "(**PENDING**) " unless stmt[:block]
- puts "#{stmt[:type].to_s} #{stmt[:text]}"
+ sexps.each do |sexp|
+ next if sexp.is_a? String
+ case sexp[1]
+ when :in_order_to
+ puts " In order to #{sexp[1]}"
+ when :as_a
+ puts " As a #{sexp[1]}"
+ when :i_want_to
+ puts " I want to #{sexp[1]}"
+ when :Scenario
+ puts
+ print " "
+ print "(**PENDING**) " if sexp.length < 4 || sexp[3].any? { |s| s.length < 4 }
+ puts "Scenario: #{sexp[2]}"
+ sexp[3].each do |step|
+ print " "
+ print "(**PENDING**) " unless step.length == 4
+ puts "#{step[1]} #{step[2]}"
+ end
+ puts
end
end
- puts
end
end
end
View
84 test/feature_test.rb
@@ -1,7 +1,6 @@
require 'test_helper'
class FeatureTest < Test::Unit::TestCase
-
should "be able to specify a default TestCase class to subclass for all Features" do
MyTestCase = Class.new(Test::Unit::TestCase)
Coulda.default_testcase_class = MyTestCase
@@ -25,7 +24,7 @@ class FeatureTest < Test::Unit::TestCase
@@counter = 1
setup do
@feature = Feature "foobarblech#{@@counter}" do
- Scenario "" do
+ Scenario "ohai" do
Given "" do; end
Then "" do; end
end
@@ -37,55 +36,8 @@ class FeatureTest < Test::Unit::TestCase
assert @feature.ancestors.include? Test::Unit::TestCase
end
- %w[Given When Then And].each do |condition|
- should "have a method called '#{condition}'" do
- assert(@feature.respond_to?(condition))
- end
- end
-
- context "that calls in_order_to, as_a, and i_want_to" do
- should "not raise syntax error" do
- assert_nothing_raised do
- Feature "one" do
- in_order_to "foo"
- as_a "bar"
- i_want_to "blech"
- end
- end
- end
- end
-
- context "that calls as_a and i_want_to" do
- should "raise syntax error because in_order_to was not called once" do
- assert_raise Coulda::SyntaxError do
- Feature "two" do
- as_a "bar"
- i_want_to "blech"
- end
- end
- end
- end
-
- context "that calls in_order_to and i_want_to" do
- should "raise syntax error because as_a was not called once" do
- assert_raise Coulda::SyntaxError do
- Feature "three" do
- in_order_to "foo"
- i_want_to "blech"
- end
- end
- end
- end
-
- context "that calls in_order_to and as_a" do
- should "raise syntax error because i_want_to was not called once" do
- assert_raise Coulda::SyntaxError do
- Feature "four" do
- in_order_to "foo"
- as_a "bar"
- end
- end
- end
+ should "have a method test_ohai" do
+ assert @feature.instance_methods.include? :test_ohai
end
context "without scenarios" do
@@ -101,35 +53,5 @@ class FeatureTest < Test::Unit::TestCase
assert @feature_without_scenarios.instance_methods.grep(/^test_/).empty?
end
end
-
- context "that does not have any errors" do
- setup do
- @feature_without_errors = Feature @@counter.to_s do
- in_order_to "foo"
- as_a "bar"
- i_want_to "blech"
- end
- end
-
- ### Integration tests
-
- context "with a block containing a scenario" do
- should "create a Feature instance method named 'test_<underscored_feature_name>_<underscored_scenario_name>'" do
- @feature_without_errors.Scenario("pending scenario") {}
- test_name = "test_pending_scenario"
- test_name = test_name.to_sym if RUBY_VERSION =~ /^1.9/
- assert(@feature_without_errors.instance_methods.include?(test_name), "Test is missing test method from scenario")
- end
-
- should "create a Scenario" do
- @feature_without_errors.Scenario "pending scenario"
- end
-
- should "include the created Scenario in the return value of the 'scenarios' method" do
- scenario = @feature_without_errors.Scenario "pending scenario"
- assert(@feature_without_errors.scenarios.include?(scenario), "feature.scenarios doesn't contain the expected Scenario object")
- end
- end
- end
end
end
View
42 test/integration/tagged_features_and_scenarios_test.rb
@@ -1,42 +0,0 @@
-require "test_helper"
-require "open3"
-
-Feature "Running only Features and Scenarios with a specific tag" do
- in_order_to "focus on a subset of a problem"
- as_a "developer using coulda"
- i_want_to "run only the Scenarios that are relevant to the problem at hand"
-
- Scenario "Tagged Feature" do
- When "I execute Coulda requesting only a tagged feature run" do
- @out = `cd tag_test; rake 'coulda:tagged_tests[tagged_feature]'`
- end
-
- Then "I should only execute the Scenarios in that tagged Feature" do
- # I'm forcing all of the executed scenarios to fail so I can just check the output
- assert_equal 1, @out.scan(/RuntimeError/).count
- assert_equal 1, @out.scan(/Test_tagged_feature/).count
- end
- end
-
- Scenario "Tagged Scenarios" do
- When "I execute Coulda requesting only a tagged feature run" do
- @out = `cd tag_test; rake 'coulda:tagged_tests[tagged_scenario]'`
- end
-
- Then "I should only execute the Scenarios matching that tag" do
- assert_equal 2, @out.scan(/RuntimeError/).count
- assert_equal 2, @out.scan(/Test_tagged_scenario/).count
- end
- end
-
- Scenario "Tagged Scenarios should inherit tags from their container tagged Feature" do
- When "I execute Coulda requesting only a tagged feature run" do
- @out = `cd tag_test; rake 'coulda:tagged_tests[tagged_feature_with_tagged_scenarios]'`
- end
-
- Then "I should only execute the Scenarios matching that Feature's tag" do
- assert_equal 3, @out.scan(/RuntimeError/).count
- assert_equal 3, @out.scan(/Test_tagged_feature_with_differently_tagged_scenarios/).count
- end
- end
-end
View
4 test/integration/using_coulda_test.rb
@@ -44,8 +44,4 @@ def prove_methods_from_then_invokes_method_on_feature
Then "something else" do; end
And "should pass" do; end
end
-
- Scenario "A scenario that invokes a method by name" do
- When :some_method
- end
end
View
22 test/scenario_test.rb
@@ -1,22 +0,0 @@
-require "test_helper"
-
-class ScenarioTest < Test::Unit::TestCase
- context "A Scenario" do
- setup do
- @scenario = Scenario.new("foobar", Feature("something_or_other")) {}
- end
-
- context "when instantiated" do
- context "with only a String" do
- setup do
- @scenario = Scenario.new("foobar", Feature("another"))
- end
-
- should "be pending" do
- assert(@scenario.pending?)
- end
- end
- end
- end
-end
-
View
2  test/test_helper.rb
@@ -2,7 +2,7 @@
require 'rubygems' if RUBY_VERSION != "1.9.1"
require 'shoulda'
-require 'coulda'
+require File.join(File.dirname(__FILE__), '..', 'lib', 'coulda')
include Coulda
Please sign in to comment.
Something went wrong with that request. Please try again.