Added Rspec and Webrat plugins and started porting Selenium on Rails tests to Rspec Plain Text Stories driving Webrat driving Selenium.

This commit is contained in:
Luke Melia 2008-06-18 02:57:57 -04:00
parent 0600756bbf
commit 0f7d6f7a1d
602 changed files with 47788 additions and 29 deletions

3
vendor/plugins/rspec/.autotest vendored Normal file
View file

@ -0,0 +1,3 @@
Autotest.add_hook :initialize do |at|
at.add_exception("spec/interop/test/unit/resources")
end

7
vendor/plugins/rspec/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
pkg
doc
tmtags
story_server/prototype/rspec_stories.html
.DS_Store
.emacs-project
*~

1094
vendor/plugins/rspec/CHANGES vendored Normal file

File diff suppressed because it is too large Load diff

20
vendor/plugins/rspec/MIT-LICENSE vendored Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2005-2008 The RSpec Development Team
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

36
vendor/plugins/rspec/README vendored Normal file
View file

@ -0,0 +1,36 @@
== RSpec
RSpec is a Behaviour Driven Development framework with tools to express User Stories
with Executable Scenarios and Executable Examples at the code level.
RSpec ships with several modules:
Spec::Story provides a framework for expressing User Stories and Scenarios
Spec::Example provides a framework for expressing Isolated Examples
Spec::Matchers provides Expression Matchers for use with Spec::Expectations
and Spec::Mocks.
Spec::Expectations supports setting expectations on your objects so you
can do things like:
result.should equal(expected_result)
Spec::Mocks supports creating Mock Objects, Stubs, and adding Mock/Stub
behaviour to your existing objects.
== Installation
The simplest approach is to install the gem (as root in some environments):
gem install -r rspec
== Building the RSpec gem
If you prefer to build the gem locally:
git clone git://github.com/dchelimsky/rspec.git
cd rspec
rake gem
gem install pkg/rspec-0.x.x.gem #as root

262
vendor/plugins/rspec/Rakefile vendored Normal file
View file

@ -0,0 +1,262 @@
$:.unshift('lib')
require 'rubygems'
require 'rake/gempackagetask'
require 'rake/contrib/rubyforgepublisher'
require 'rake/clean'
require 'rake/rdoctask'
require 'rake/testtask'
require 'spec/version'
dir = File.dirname(__FILE__)
# Some of the tasks are in separate files since they are also part of the website documentation
load File.dirname(__FILE__) + '/rake_tasks/examples.rake'
load File.dirname(__FILE__) + '/rake_tasks/examples_with_rcov.rake'
load File.dirname(__FILE__) + '/rake_tasks/failing_examples_with_html.rake'
load File.dirname(__FILE__) + '/rake_tasks/verify_rcov.rake'
PKG_NAME = "rspec"
PKG_VERSION = Spec::VERSION::STRING
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
PKG_FILES = FileList[
'[A-Z]*',
'lib/**/*.rb',
'spec/**/*',
'examples/**/*',
'failing_examples/**/*',
'plugins/**/*',
'stories/**/*',
'rake_tasks/**/*'
]
task :default => [:verify_rcov]
task :verify_rcov => [:spec, :stories]
desc "Run all specs"
Spec::Rake::SpecTask.new do |t|
t.spec_files = FileList['spec/**/*_spec.rb']
t.spec_opts = ['--options', 'spec/spec.opts']
unless ENV['NO_RCOV']
t.rcov = true
t.rcov_dir = '../doc/output/coverage'
t.rcov_opts = ['--exclude', 'lib/spec.rb,lib/spec/runner.rb,spec\/spec,bin\/spec,examples,\/var\/lib\/gems,\/Library\/Ruby,\.autotest']
end
end
desc "Run all stories"
task :stories do
html = 'story_server/prototype/rspec_stories.html'
ruby "stories/all.rb --colour --format plain --format html:#{html}"
unless IO.read(html) =~ /<span class="param">/m
raise 'highlighted parameters are broken in story HTML'
end
end
desc "Run all specs and store html output in doc/output/report.html"
Spec::Rake::SpecTask.new('spec_html') do |t|
t.spec_files = FileList['spec/**/*_spec.rb']
t.spec_opts = ['--format html:../../../../doc/output/report.html', '--format progress','--backtrace']
end
desc "Run all failing examples"
Spec::Rake::SpecTask.new('failing_examples') do |t|
t.spec_files = FileList['failing_examples/**/*_spec.rb']
end
desc 'Generate RDoc'
rd = Rake::RDocTask.new do |rdoc|
rdoc.rdoc_dir = '../doc/output/rdoc'
rdoc.options << '--title' << 'RSpec' << '--line-numbers' << '--inline-source' << '--main' << 'README'
rdoc.rdoc_files.include('README', 'CHANGES', 'MIT-LICENSE', 'UPGRADE', 'lib/**/*.rb')
end
spec = Gem::Specification.new do |s|
s.name = PKG_NAME
s.version = PKG_VERSION
s.summary = Spec::VERSION::DESCRIPTION
s.description = <<-EOF
RSpec is a behaviour driven development (BDD) framework for Ruby. RSpec was
created in response to Dave Astels' article _A New Look at Test Driven Development_
which can be read at: http://daveastels.com/index.php?p=5 RSpec is intended to
provide the features discussed in Dave's article.
EOF
s.files = PKG_FILES.to_a
s.require_path = 'lib'
s.has_rdoc = true
s.rdoc_options = rd.options
s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$|^EXAMPLES.rd$/ }.to_a
s.bindir = 'bin'
s.executables = ['spec', 'spec_translator']
s.default_executable = 'spec'
s.author = "RSpec Development Team"
s.email = "rspec-devel@rubyforge.org"
s.homepage = "http://rspec.rubyforge.org"
s.platform = Gem::Platform::RUBY
s.rubyforge_project = "rspec"
end
Rake::GemPackageTask.new(spec) do |pkg|
pkg.need_zip = true
pkg.need_tar = true
end
def egrep(pattern)
Dir['**/*.rb'].each do |fn|
count = 0
open(fn) do |f|
while line = f.gets
count += 1
if line =~ pattern
puts "#{fn}:#{count}:#{line}"
end
end
end
end
end
desc "Look for TODO and FIXME tags in the code"
task :todo do
egrep /(FIXME|TODO|TBD)/
end
task :release => [:verify_committed, :verify_user, :spec, :publish_packages, :tag, :publish_news]
desc "Verifies that there is no uncommitted code"
task :verify_committed do
IO.popen('git status') do |io|
io.each_line do |line|
raise "\n!!! Do a git commit first !!!\n\n" if line =~ /^#\s*modified:/
end
end
end
desc "Creates a tag in svn"
task :tag do
# from = `svn info #{File.dirname(__FILE__)}`.match(/URL: (.*)\/rspec/n)[1]
# to = from.gsub(/trunk/, "tags/#{Spec::VERSION::TAG}")
# current = from.gsub(/trunk/, "tags/CURRENT")
#
# puts "Creating tag in SVN"
# tag_cmd = "svn cp #{from} #{to} -m \"Tag release #{Spec::VERSION::FULL_VERSION}\""
# `#{tag_cmd}` ; raise "ERROR: #{tag_cmd}" unless $? == 0
#
# puts "Removing CURRENT"
# remove_current_cmd = "svn rm #{current} -m \"Remove tags/CURRENT\""
# `#{remove_current_cmd}` ; raise "ERROR: #{remove_current_cmd}" unless $? == 0
#
# puts "Re-Creating CURRENT"
# create_current_cmd = "svn cp #{to} #{current} -m \"Copy #{Spec::VERSION::TAG} to tags/CURRENT\""
# `#{create_current_cmd}` ; "ERROR: #{create_current_cmd}" unless $? == 0
end
task :verify_user do
raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
end
desc "Upload Website to RubyForge"
task :publish_website => [:verify_user, :website] do
unless Spec::VERSION::RELEASE_CANDIDATE
publisher = Rake::SshDirPublisher.new(
"rspec-website@rubyforge.org",
"/var/www/gforge-projects/#{PKG_NAME}",
"../doc/output"
)
publisher.upload
else
puts "** Not publishing packages to RubyForge - this is a prerelease"
end
end
desc "Upload Website archive to RubyForge"
task :archive_website => [:verify_user, :website] do
publisher = Rake::SshDirPublisher.new(
"rspec-website@rubyforge.org",
"/var/www/gforge-projects/#{PKG_NAME}/#{Spec::VERSION::TAG}",
"../doc/output"
)
publisher.upload
end
desc "Package the Rails plugin"
task :package_rspec_on_rails do
mkdir 'pkg' rescue nil
rm_rf "pkg/rspec-rails-#{PKG_VERSION}" rescue nil
`git clone ../rspec-rails pkg/rspec-rails-#{PKG_VERSION}`
rm_rf "pkg/rspec-rails-#{PKG_VERSION}/.git"
Dir.chdir 'pkg' do
`tar cvzf rspec-rails-#{PKG_VERSION}.tgz rspec-rails-#{PKG_VERSION}`
end
end
task :pkg => :package_rspec_on_rails
desc "Package the RSpec.tmbundle"
task :package_tmbundle do
mkdir 'pkg' rescue nil
rm_rf "pkg/RSpec-#{PKG_VERSION}.tmbundle" rescue nil
`git clone ../../../../RSpec.tmbundle pkg/RSpec-#{PKG_VERSION}.tmbundle`
rm_rf "pkg/RSpec-#{PKG_VERSION}.tmbundle/.git"
Dir.chdir 'pkg' do
`tar cvzf RSpec-#{PKG_VERSION}.tmbundle.tgz RSpec-#{PKG_VERSION}.tmbundle`
end
end
task :pkg => :package_tmbundle
desc "Publish gem+tgz+zip on RubyForge. You must make sure lib/version.rb is aligned with the CHANGELOG file"
task :publish_packages => [:verify_user, :package, :pkg] do
release_files = FileList[
"pkg/#{PKG_FILE_NAME}.gem",
"pkg/#{PKG_FILE_NAME}.tgz",
"pkg/rspec-rails-#{PKG_VERSION}.tgz",
"pkg/#{PKG_FILE_NAME}.zip",
"pkg/RSpec-#{PKG_VERSION}.tmbundle.tgz"
]
unless Spec::VERSION::RELEASE_CANDIDATE
require 'meta_project'
require 'rake/contrib/xforge'
Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(PKG_NAME)) do |xf|
# Never hardcode user name and password in the Rakefile!
xf.user_name = ENV['RUBYFORGE_USER']
xf.files = release_files.to_a
xf.release_name = "RSpec #{PKG_VERSION}"
end
else
puts "SINCE THIS IS A PRERELEASE, FILES ARE UPLOADED WITH SSH, NOT TO THE RUBYFORGE FILE SECTION"
puts "YOU MUST TYPE THE PASSWORD #{release_files.length} TIMES..."
host = "rspec-website@rubyforge.org"
remote_dir = "/var/www/gforge-projects/#{PKG_NAME}"
publisher = Rake::SshFilePublisher.new(
host,
remote_dir,
File.dirname(__FILE__),
*release_files
)
publisher.upload
puts "UPLADED THE FOLLOWING FILES:"
release_files.each do |file|
name = file.match(/pkg\/(.*)/)[1]
puts "* http://rspec.rubyforge.org/#{name}"
end
puts "They are not linked to anywhere, so don't forget to tell people!"
end
end
desc "Publish news on RubyForge"
task :publish_news => [:verify_user] do
unless Spec::VERSION::RELEASE_CANDIDATE
require 'meta_project'
require 'rake/contrib/xforge'
Rake::XForge::NewsPublisher.new(MetaProject::Project::XForge::RubyForge.new(PKG_NAME)) do |news|
# Never hardcode user name and password in the Rakefile!
news.user_name = ENV['RUBYFORGE_USER']
end
else
puts "** Not publishing news to RubyForge - this is a prerelease"
end
end

1
vendor/plugins/rspec/TODO vendored Normal file
View file

@ -0,0 +1 @@

7
vendor/plugins/rspec/UPGRADE vendored Normal file
View file

@ -0,0 +1,7 @@
== Spec::Rails
script/generate rspec
Or modify spec_helper.rb based on the template, which can be found at:
vendor/plugins/rspec_on_rails/generators/rspec/templates/spec_helper.rb

4
vendor/plugins/rspec/bin/spec vendored Executable file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env ruby
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
require 'spec'
exit ::Spec::Runner::CommandLine.run(rspec_options)

8
vendor/plugins/rspec/bin/spec_translator vendored Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env ruby
raise "\n\nUsage: spec_translator from_dir to_dir\n\n" if ARGV.size != 2
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
require 'spec/translator'
t = ::Spec::Translator.new
from = ARGV[0]
to = ARGV[1]
t.translate(from, to)

View file

@ -0,0 +1,19 @@
require File.dirname(__FILE__) + '/spec_helper'
# Run spec w/ -fs to see the output of this file
describe "Examples with no descriptions" do
# description is auto-generated as "should equal(5)" based on the last #should
it do
3.should equal(3)
5.should equal(5)
end
it { 3.should be < 5 }
it { ["a"].should include("a") }
it { [1,2,3].should respond_to(:size) }
end

View file

@ -0,0 +1,40 @@
require File.dirname(__FILE__) + '/spec_helper'
$global = 0
describe "State created in before(:all)" do
before :all do
@sideeffect = 1
$global +=1
end
before :each do
@isolated = 1
end
it "should be accessible from example" do
@sideeffect.should == 1
$global.should == 1
@isolated.should == 1
@sideeffect += 1
@isolated += 1
end
it "should not have sideffects" do
@sideeffect.should == 1
$global.should == 2
@isolated.should == 1
@sideeffect += 1
@isolated += 1
end
after :each do
$global += 1
end
after :all do
$global.should == 3
$global = 0
end
end

View file

@ -0,0 +1,45 @@
require File.dirname(__FILE__) + '/spec_helper'
def behave_as_electric_musician
respond_to(:read_notes, :turn_down_amp)
end
def behave_as_musician
respond_to(:read_notes)
end
module BehaveAsExample
class BluesGuitarist
def read_notes; end
def turn_down_amp; end
end
class RockGuitarist
def read_notes; end
def turn_down_amp; end
end
class ClassicGuitarist
def read_notes; end
end
describe BluesGuitarist do
it "should behave as guitarist" do
BluesGuitarist.new.should behave_as_electric_musician
end
end
describe RockGuitarist do
it "should behave as guitarist" do
RockGuitarist.new.should behave_as_electric_musician
end
end
describe ClassicGuitarist do
it "should not behave as guitarist" do
ClassicGuitarist.new.should behave_as_musician
end
end
end

View file

@ -0,0 +1,54 @@
module AnimalSpecHelper
class Eat
def initialize(food)
@food = food
end
def matches?(animal)
@animal = animal
@animal.eats?(@food)
end
def failure_message
"expected #{@animal} to eat #{@food}, but it does not"
end
def negative_failure_message
"expected #{@animal} not to eat #{@food}, but it does"
end
end
def eat(food)
Eat.new(food)
end
end
module Animals
class Animal
def eats?(food)
return foods_i_eat.include?(food)
end
end
class Mouse < Animal
def foods_i_eat
[:cheese]
end
end
describe Mouse do
include AnimalSpecHelper
before(:each) do
@mouse = Animals::Mouse.new
end
it "should eat cheese" do
@mouse.should eat(:cheese)
end
it "should not eat cat" do
@mouse.should_not eat(:cat)
end
end
end

View file

@ -0,0 +1,12 @@
require File.dirname(__FILE__) + '/spec_helper'
require 'spec/runner/formatter/progress_bar_formatter'
# Example of a formatter with custom bactrace printing. Run me with:
# ruby bin/spec failing_examples -r examples/custom_formatter.rb -f CustomFormatter
class CustomFormatter < Spec::Runner::Formatter::ProgressBarFormatter
def backtrace_line(line)
line.gsub(/([^:]*\.rb):(\d*)/) do
"<a href=\"file://#{File.expand_path($1)}\">#{$1}:#{$2}</a> "
end
end
end

View file

@ -0,0 +1,9 @@
require File.dirname(__FILE__) + '/spec_helper'
describe "Some integers" do
(1..10).each do |n|
it "The root of #{n} square should be #{n}" do
Math.sqrt(n*n).should == n
end
end
end

View file

@ -0,0 +1,19 @@
require File.dirname(__FILE__) + '/spec_helper'
class FileAccessor
def open_and_handle_with(pathname, processor)
pathname.open do |io|
processor.process(io)
end
end
end
if __FILE__ == $0
require File.dirname(__FILE__) + '/io_processor'
require 'pathname'
accessor = FileAccessor.new
io_processor = IoProcessor.new
file = Pathname.new ARGV[0]
accessor.open_and_handle_with(file, io_processor)
end

View file

@ -0,0 +1,38 @@
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/file_accessor'
require 'stringio'
describe "A FileAccessor" do
# This sequence diagram illustrates what this spec specifies.
#
# +--------------+ +----------+ +-------------+
# | FileAccessor | | Pathname | | IoProcessor |
# +--------------+ +----------+ +-------------+
# | | |
# open_and_handle_with | | |
# -------------------->| | open | |
# | |--------------->| | |
# | | io | | |
# | |<...............| | |
# | | | process(io) |
# | |---------------------------------->| |
# | | | | |
# | |<..................................| |
# | | |
#
it "should open a file and pass it to the processor's process method" do
# This is the primary actor
accessor = FileAccessor.new
# These are the primary actor's neighbours, which we mock.
file = mock "Pathname"
io_processor = mock "IoProcessor"
io = StringIO.new "whatever"
file.should_receive(:open).and_yield io
io_processor.should_receive(:process).with(io)
accessor.open_and_handle_with(file, io_processor)
end
end

View file

@ -0,0 +1,31 @@
require File.dirname(__FILE__) + '/spec_helper'
# greeter.rb
#
# Based on http://glu.ttono.us/articles/2006/12/19/tormenting-your-tests-with-heckle
#
# Run with:
#
# spec greeter_spec.rb --heckle Greeter
#
class Greeter
def initialize(person = nil)
@person = person
end
def greet
@person.nil? ? "Hi there!" : "Hi #{@person}!"
end
end
describe "Greeter" do
it "should say Hi to person" do
greeter = Greeter.new("Kevin")
greeter.greet.should == "Hi Kevin!"
end
it "should say Hi to nobody" do
greeter = Greeter.new
# Uncomment the next line to make Heckle happy
#greeter.greet.should == "Hi there!"
end
end

View file

@ -0,0 +1,14 @@
require File.dirname(__FILE__) + '/spec_helper'
module HelperMethodExample
describe "an example group with helper a method" do
def helper_method
"received call"
end
it "should make that method available to specs" do
helper_method.should == "received call"
end
end
end

View file

@ -0,0 +1,8 @@
class DataTooShort < StandardError; end
class IoProcessor
# Does some fancy stuff unless the length of +io+ is shorter than 32
def process(io)
raise DataTooShort if io.read.length < 32
end
end

View file

@ -0,0 +1,21 @@
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/io_processor'
require 'stringio'
describe "An IoProcessor" do
before(:each) do
@processor = IoProcessor.new
end
it "should raise nothing when the file is exactly 32 bytes" do
lambda {
@processor.process(StringIO.new("z"*32))
}.should_not raise_error
end
it "should raise an exception when the file length is less than 32 bytes" do
lambda {
@processor.process(StringIO.new("z"*31))
}.should raise_error(DataTooShort)
end
end

View file

@ -0,0 +1,11 @@
require File.dirname(__FILE__) + '/spec_helper'
context "A legacy spec" do
setup do
end
specify "should work fine" do
end
teardown do
end
end

View file

@ -0,0 +1,27 @@
require File.dirname(__FILE__) + '/spec_helper'
describe "A consumer of a mock" do
it "should be able to send messages to the mock" do
mock = mock("poke me")
mock.should_receive(:poke)
mock.poke
end
end
describe "a mock" do
it "should be able to mock the same message twice w/ different args" do
mock = mock("mock")
mock.should_receive(:msg).with(:arg1).and_return(:val1)
mock.should_receive(:msg).with(:arg2).and_return(:val2)
mock.msg(:arg1).should eql(:val1)
mock.msg(:arg2).should eql(:val2)
end
it "should be able to mock the same message twice w/ different args in reverse order" do
mock = mock("mock")
mock.should_receive(:msg).with(:arg1).and_return(:val1)
mock.should_receive(:msg).with(:arg2).and_return(:val2)
mock.msg(:arg2).should eql(:val2)
mock.msg(:arg1).should eql(:val1)
end
end

View file

@ -0,0 +1,28 @@
class MultiThreadedExampleGroupRunner < Spec::Runner::ExampleGroupRunner
def initialize(options, arg)
super(options)
# configure these
@thread_count = 4
@thread_wait = 0
end
def run
@threads = []
q = Queue.new
example_groups.each { |b| q << b}
success = true
@thread_count.times do
@threads << Thread.new(q) do |queue|
while not queue.empty?
example_group = queue.pop
success &= example_group.suite.run(nil)
end
end
sleep @thread_wait
end
@threads.each {|t| t.join}
success
end
end
MultiThreadedBehaviourRunner = MultiThreadedExampleGroupRunner

View file

@ -0,0 +1,36 @@
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/stack'
class StackExamples < Spec::ExampleGroup
describe(Stack)
before(:each) do
@stack = Stack.new
end
end
class EmptyStackExamples < StackExamples
describe("when empty")
it "should be empty" do
@stack.should be_empty
end
end
class AlmostFullStackExamples < StackExamples
describe("when almost full")
before(:each) do
(1..9).each {|n| @stack.push n}
end
it "should be full" do
@stack.should_not be_full
end
end
class FullStackExamples < StackExamples
describe("when full")
before(:each) do
(1..10).each {|n| @stack.push n}
end
it "should be full" do
@stack.should be_full
end
end

View file

@ -0,0 +1,29 @@
require File.dirname(__FILE__) + '/spec_helper'
class MockableClass
def self.find id
return :original_return
end
end
describe "A partial mock" do
it "should work at the class level" do
MockableClass.should_receive(:find).with(1).and_return {:stub_return}
MockableClass.find(1).should equal(:stub_return)
end
it "should revert to the original after each spec" do
MockableClass.find(1).should equal(:original_return)
end
it "can be mocked w/ ordering" do
MockableClass.should_receive(:msg_1).ordered
MockableClass.should_receive(:msg_2).ordered
MockableClass.should_receive(:msg_3).ordered
MockableClass.msg_1
MockableClass.msg_2
MockableClass.msg_3
end
end

View file

@ -0,0 +1,20 @@
require File.dirname(__FILE__) + '/spec_helper'
describe "pending example (using pending method)" do
it %Q|should be reported as "PENDING: for some reason"| do
pending("for some reason")
end
end
describe "pending example (with no block)" do
it %Q|should be reported as "PENDING: Not Yet Implemented"|
end
describe "pending example (with block for pending)" do
it %Q|should have a failing block, passed to pending, reported as "PENDING: for some reason"| do
pending("for some reason") do
raise "some reason"
end
end
end

View file

@ -0,0 +1,27 @@
require File.dirname(__FILE__) + '/spec_helper'
class BddFramework
def intuitive?
true
end
def adopted_quickly?
true
end
end
describe "BDD framework" do
before(:each) do
@bdd_framework = BddFramework.new
end
it "should be adopted quickly" do
@bdd_framework.should be_adopted_quickly
end
it "should be intuitive" do
@bdd_framework.should be_intuitive
end
end

View file

@ -0,0 +1 @@
examples/custom_expectation_matchers.rb

View file

@ -0,0 +1,81 @@
require File.dirname(__FILE__) + '/spec_helper'
module SharedExampleGroupExample
class OneThing
def what_things_do
"stuff"
end
end
class AnotherThing
def what_things_do
"stuff"
end
end
class YetAnotherThing
def what_things_do
"stuff"
end
end
# A SharedExampleGroup is an example group that doesn't get run.
# You can create one like this:
share_examples_for "most things" do
def helper_method
"helper method"
end
it "should do what things do" do
@thing.what_things_do.should == "stuff"
end
end
# A SharedExampleGroup is also module. If you create one like this
# it gets assigned to the constant AllThings
share_as :MostThings do
def helper_method
"helper method"
end
it "should do what things do" do
@thing.what_things_do.should == "stuff"
end
end
describe OneThing do
# Now you can include the shared example group like this, which
# feels more like what you might say ...
it_should_behave_like "most things"
before(:each) { @thing = OneThing.new }
it "should have access to helper methods defined in the shared example group" do
helper_method.should == "helper method"
end
end
describe AnotherThing do
# ... or you can include the example group like this, which
# feels more like the programming language we love.
it_should_behave_like MostThings
before(:each) { @thing = AnotherThing.new }
it "should have access to helper methods defined in the shared example group" do
helper_method.should == "helper method"
end
end
describe YetAnotherThing do
# ... or you can include the example group like this, which
# feels more like the programming language we love.
include MostThings
before(:each) { @thing = AnotherThing.new }
it "should have access to helper methods defined in the shared example group" do
helper_method.should == "helper method"
end
end
end

View file

@ -0,0 +1,38 @@
require File.join(File.dirname(__FILE__), *%w[spec_helper])
shared_examples_for "non-empty Stack" do
it { @stack.should_not be_empty }
it "should return the top item when sent #peek" do
@stack.peek.should == @last_item_added
end
it "should NOT remove the top item when sent #peek" do
@stack.peek.should == @last_item_added
@stack.peek.should == @last_item_added
end
it "should return the top item when sent #pop" do
@stack.pop.should == @last_item_added
end
it "should remove the top item when sent #pop" do
@stack.pop.should == @last_item_added
unless @stack.empty?
@stack.pop.should_not == @last_item_added
end
end
end
shared_examples_for "non-full Stack" do
it { @stack.should_not be_full }
it "should add to the top when sent #push" do
@stack.push "newly added top item"
@stack.peek.should == "newly added top item"
end
end

View file

@ -0,0 +1,3 @@
lib_path = File.expand_path("#{File.dirname(__FILE__)}/../../lib")
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
require 'spec'

View file

@ -0,0 +1,36 @@
class StackUnderflowError < RuntimeError
end
class StackOverflowError < RuntimeError
end
class Stack
def initialize
@items = []
end
def push object
raise StackOverflowError if @items.length == 10
@items.push object
end
def pop
raise StackUnderflowError if @items.empty?
@items.delete @items.last
end
def peek
raise StackUnderflowError if @items.empty?
@items.last
end
def empty?
@items.empty?
end
def full?
@items.length == 10
end
end

View file

@ -0,0 +1,63 @@
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + "/stack"
require File.dirname(__FILE__) + '/shared_stack_examples'
describe Stack, " (empty)" do
before(:each) do
@stack = Stack.new
end
# NOTE that this one auto-generates the description "should be empty"
it { @stack.should be_empty }
it_should_behave_like "non-full Stack"
it "should complain when sent #peek" do
lambda { @stack.peek }.should raise_error(StackUnderflowError)
end
it "should complain when sent #pop" do
lambda { @stack.pop }.should raise_error(StackUnderflowError)
end
end
describe Stack, " (with one item)" do
before(:each) do
@stack = Stack.new
@stack.push 3
@last_item_added = 3
end
it_should_behave_like "non-empty Stack"
it_should_behave_like "non-full Stack"
end
describe Stack, " (with one item less than capacity)" do
before(:each) do
@stack = Stack.new
(1..9).each { |i| @stack.push i }
@last_item_added = 9
end
it_should_behave_like "non-empty Stack"
it_should_behave_like "non-full Stack"
end
describe Stack, " (full)" do
before(:each) do
@stack = Stack.new
(1..10).each { |i| @stack.push i }
@last_item_added = 10
end
# NOTE that this one auto-generates the description "should be full"
it { @stack.should be_full }
it_should_behave_like "non-empty Stack"
it "should complain on #push" do
lambda { @stack.push Object.new }.should raise_error(StackOverflowError)
end
end

View file

@ -0,0 +1,67 @@
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/stack'
require File.dirname(__FILE__) + '/shared_stack_examples'
describe Stack do
before(:each) do
@stack = Stack.new
end
describe "(empty)" do
it { @stack.should be_empty }
it_should_behave_like "non-full Stack"
it "should complain when sent #peek" do
lambda { @stack.peek }.should raise_error(StackUnderflowError)
end
it "should complain when sent #pop" do
lambda { @stack.pop }.should raise_error(StackUnderflowError)
end
end
describe "(with one item)" do
before(:each) do
@stack.push 3
@last_item_added = 3
end
it_should_behave_like "non-empty Stack"
it_should_behave_like "non-full Stack"
end
describe "(with one item less than capacity)" do
before(:each) do
(1..9).each { |i| @stack.push i }
@last_item_added = 9
end
it_should_behave_like "non-empty Stack"
it_should_behave_like "non-full Stack"
end
describe "(full)" do
before(:each) do
(1..10).each { |i| @stack.push i }
@last_item_added = 10
end
it { @stack.should be_full }
it_should_behave_like "non-empty Stack"
it "should complain on #push" do
lambda { @stack.push Object.new }.should raise_error(StackOverflowError)
end
end
end

View file

@ -0,0 +1,69 @@
require File.dirname(__FILE__) + '/spec_helper'
describe "A consumer of a stub" do
it "should be able to stub methods on any Object" do
obj = Object.new
obj.stub!(:foobar).and_return {:return_value}
obj.foobar.should equal(:return_value)
end
end
class StubbableClass
def self.find id
return :original_return
end
end
describe "A stubbed method on a class" do
it "should return the stubbed value" do
StubbableClass.stub!(:find).and_return(:stub_return)
StubbableClass.find(1).should equal(:stub_return)
end
it "should revert to the original method after each spec" do
StubbableClass.find(1).should equal(:original_return)
end
it "can stub! and mock the same message" do
StubbableClass.stub!(:msg).and_return(:stub_value)
StubbableClass.should_receive(:msg).with(:arg).and_return(:mock_value)
StubbableClass.msg.should equal(:stub_value)
StubbableClass.msg(:other_arg).should equal(:stub_value)
StubbableClass.msg(:arg).should equal(:mock_value)
StubbableClass.msg(:another_arg).should equal(:stub_value)
StubbableClass.msg(:yet_another_arg).should equal(:stub_value)
StubbableClass.msg.should equal(:stub_value)
end
end
describe "A mock" do
it "can stub!" do
mock = mock("stubbing mock")
mock.stub!(:msg).and_return(:value)
(1..10).each {mock.msg.should equal(:value)}
end
it "can stub! and mock" do
mock = mock("stubbing mock")
mock.stub!(:stub_message).and_return(:stub_value)
mock.should_receive(:mock_message).once.and_return(:mock_value)
(1..10).each {mock.stub_message.should equal(:stub_value)}
mock.mock_message.should equal(:mock_value)
(1..10).each {mock.stub_message.should equal(:stub_value)}
end
it "can stub! and mock the same message" do
mock = mock("stubbing mock")
mock.stub!(:msg).and_return(:stub_value)
mock.should_receive(:msg).with(:arg).and_return(:mock_value)
mock.msg.should equal(:stub_value)
mock.msg(:other_arg).should equal(:stub_value)
mock.msg(:arg).should equal(:mock_value)
mock.msg(:another_arg).should equal(:stub_value)
mock.msg(:yet_another_arg).should equal(:stub_value)
mock.msg.should equal(:stub_value)
end
end

View file

@ -0,0 +1,13 @@
class Adder
def initialize
@addends = []
end
def <<(val)
@addends << val
end
def sum
@addends.inject(0) { |sum_so_far, val| sum_so_far + val }
end
end

View file

@ -0,0 +1,34 @@
This is a story about a calculator. The text up here above the Story: declaration
won't be processed, so you can write whatever you wish!
Story: simple addition
As an accountant
I want to add numbers
So that I can count beans
Scenario: add one plus one
Given an addend of 1
And an addend of 1
When the addends are addeds
Then the sum should be 3
And the corks should be popped
Scenario: add two plus five
Given an addend of 2
And an addend of 5
When the addends are added
Then the sum should be 7
Then it should snow
Scenario: add three more
GivenScenario add two plus five
And an addend of 3
When the addends are added
Then the sum should be 10

View file

@ -0,0 +1,9 @@
require File.join(File.dirname(__FILE__), "helper")
require File.join(File.dirname(__FILE__), "adder")
# with_steps_for :addition, :more_addition do
with_steps_for :addition, :more_addition do
# Then("the corks should be popped") { }
run File.expand_path(__FILE__).gsub(".rb","")
end

View file

@ -0,0 +1,65 @@
$:.push File.join(File.dirname(__FILE__), *%w[.. .. lib])
require 'spec'
class AdditionMatchers < Spec::Story::StepGroup
steps do |add|
add.given("an addend of $addend") do |addend|
@adder ||= Adder.new
@adder << addend.to_i
end
end
end
steps = AdditionMatchers.new do |add|
add.then("the sum should be $sum") do |sum|
@sum.should == sum.to_i
end
end
steps.when("they are added") do
@sum = @adder.sum
end
# This Story uses steps (see above) instead of blocks
# passed to Given, When and Then
Story "addition", %{
As an accountant
I want to add numbers
So that I can count some beans
}, :steps_for => steps do
Scenario "2 + 3" do
Given "an addend of 2"
And "an addend of 3"
When "they are added"
Then "the sum should be 5"
end
# This scenario uses GivenScenario, which silently runs
# all the steps in a previous scenario.
Scenario "add 4 more" do
GivenScenario "2 + 3"
Given "an addend of 4"
When "they are added"
Then "the sum should be 9"
end
end
# And the class that makes the story pass
class Adder
def << addend
addends << addend
end
def sum
@addends.inject(0) do |result, addend|
result + addend.to_i
end
end
def addends
@addends ||= []
end
end

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<loadpath>
<pathentry path="" type="src"/>
<pathentry path="org.rubypeople.rdt.launching.RUBY_CONTAINER" type="con"/>
</loadpath>

View file

@ -0,0 +1,21 @@
John Conway's Game of Life
The Rules
---------
The Game of Life was invented by John Conway (as you might have gathered).
The game is played on a field of cells, each of which has eight neighbors (adjacent cells).
A cell is either occupied (by an organism) or not.
The rules for deriving a generation from the previous one are these:
Survival
--------
If an occupied cell has 2 or 3 neighbors, the organism survives to the next generation.
Death
-----
If an occupied cell has 0, 1, 4, 5, 6, 7, or 8 occupied neighbors, the organism dies
(0, 1: of loneliness; 4 thru 8: of overcrowding).
Birth
-----
If an unoccupied cell has 3 occupied neighbors, it becomes occupied.

View file

@ -0,0 +1,6 @@
$:.unshift File.join(File.dirname(__FILE__), '..', '..', '..', 'lib')
$:.unshift File.join(File.dirname(__FILE__), '..')
require 'spec'
require 'behaviour/examples/examples'
require 'behaviour/stories/stories'

View file

@ -0,0 +1,3 @@
require 'spec'
require 'behaviour/examples/game_behaviour'
require 'behaviour/examples/grid_behaviour'

View file

@ -0,0 +1,35 @@
require 'life'
describe Game do
it 'should have a grid' do
# given
game = Game.new(5, 5)
# then
game.grid.should be_kind_of(Grid)
end
it 'should create a cell' do
# given
game = Game.new(2, 2)
expected_grid = Grid.from_string( 'X. ..' )
# when
game.create_at(0, 0)
# then
game.grid.should == expected_grid
end
it 'should destroy a cell' do
# given
game = Game.new(2,2)
game.grid = Grid.from_string('X. ..')
# when
game.destroy_at(0,0)
# then
game.grid.should == Grid.from_string('.. ..')
end
end

View file

@ -0,0 +1,66 @@
describe Grid do
it 'should be empty when created' do
# given
expected_contents = [
[0, 0, 0],
[0, 0, 0]
]
grid = Grid.new(2, 3)
# when
contents = grid.contents
# then
contents.should == expected_contents
end
it 'should compare equal based on its contents' do
# given
grid1 = Grid.new(2, 3)
grid2 = Grid.new(2, 3)
# then
grid1.should == grid2
end
it 'should be able to replace its contents' do
# given
grid = Grid.new(2,2)
new_contents = [[0,1,0], [1,0,1]]
# when
grid.contents = new_contents
# then
grid.contents.should == new_contents
grid.rows.should == 2
grid.columns.should == 3
end
it 'should add an organism' do
# given
grid = Grid.new(2, 2)
expected = Grid.new(2, 2)
expected.contents = [[1,0],[0,0]]
# when
grid.create_at(0,0)
# then
grid.should == expected
end
it 'should create itself from a string' do
# given
expected = Grid.new 3, 3
expected.create_at(0,0)
expected.create_at(1,0)
expected.create_at(2,2)
# when
actual = Grid.from_string "X.. X.. ..X"
# then
actual.should == expected
end
end

View file

@ -0,0 +1,21 @@
Story: cells with less than two neighbours die
As a game producer
I want cells with less than two neighbours to die
So that I can illustrate how the game works to people with money
Scenario: cells with zero or one neighbour die
Given the grid looks like
........
.XX.XX..
.XX.....
....X...
........
When the next step occurs
Then the grid should look like
........
.XX.....
.XX.....
........
........

View file

@ -0,0 +1,21 @@
Story: cells with more than three neighbours die
As a game producer
I want cells with more than three neighbours to die
So that I can show the people with money how we are getting on
Scenario: blink
Given the grid looks like
.....
...XX
...XX
.XX..
.XX..
When the next step occurs
Then the grid should look like
.....
...XX
....X
.X...
.XX..

View file

@ -0,0 +1,42 @@
Story: Empty spaces with three neighbours create a cell
As a game producer
I want empty cells with three neighbours to die
So that I have a minimum feature set to ship
Scenario: the glider
Given the grid looks like
...X..
..X...
..XXX.
......
......
When the next step occurs
Then the grid should look like
......
..X.X.
..XX..
...X..
......
When the next step occurs
Then the grid should look like
......
..X...
..X.X.
..XX..
......
When the next step occurs
Then the grid should look like
......
...X..
.XX...
..XX..
......
When the next step occurs
Then the grid should look like
......
..X...
.X....
.XXX..
......

View file

@ -0,0 +1,42 @@
Story: I can create a cell
As a game producer
I want to create a cell
So that I can show the grid to people
Scenario: nothing to see here
Given a 3 x 3 game
Then the grid should look like
...
...
...
Scenario: all on its lonesome
Given a 3 x 3 game
When I create a cell at 1, 1
Then the grid should look like
...
.X.
...
Scenario: the grid has three cells
Given a 3 x 3 game
When I create a cell at 0, 0
and I create a cell at 0, 1
and I create a cell at 2, 2
Then the grid should look like
XX.
...
..X
Scenario: more cells more more
Given the grid has three cells
When I create a celll at 3, 1
Then the grid should look like
XX.
..X
..X

View file

@ -0,0 +1,17 @@
Story: I can kill a cell
As a game producer
I want to kill a cell
So that when I make a mistake I dont have to start again
Scenario: bang youre dead
Given the grid looks like
XX.
.X.
..X
When I destroy the cell at 0, 1
Then the grid should look like
X..
.X.
..X

View file

@ -0,0 +1,53 @@
Story: The grid wraps
As a game player
I want the grid to wrap
So that untidy stuff at the edges is avoided
Scenario: crowded in the corners
Given the grid looks like
X.X
...
X.X
When the next step is taken
Then the grid should look like
X.X
...
X.X
Scenario: the glider returns
Given the glider
......
..X...
.X....
.XXX..
......
When the next step is taken
and the next step is taken
and the next step is taken
and the next step is taken
Then the grid should look like
......
......
.X....
X.....
XXX...
When the next step is taken
Then the grid should look like
.X....
......
......
X.X...
XX....
When the next step is taken
Then the grid should look like
XX....
......
......
X.....
X.X...

View file

@ -0,0 +1,52 @@
require File.join(File.dirname(__FILE__), *%w[helper])
Story "I can create a cell",
%(As a game producer
I want to create a cell
So that I can show the grid to people), :steps_for => :life do
Scenario "nothing to see here" do
Given "a game with dimensions", 3, 3 do |rows,cols|
@game = Game.new(rows,cols)
end
Then "the grid should look like", %(
...
...
...
)
end
Scenario "all on its lonesome" do
Given "a game with dimensions", 2, 2
When "I create a cell at", 1, 1 do |row,col|
@game.create_at(row,col)
end
Then "the grid should look like", %(
..
.X
)
end
Scenario "the grid has three cells" do
Given "a game with dimensions", 3, 3
When "I create a cell at", 0, 0
When "I create a cell at", 0, 1
When "I create a cell at", 2, 2
Then "the grid should look like", %(
XX.
...
..X
)
end
Scenario "more cells more more" do
GivenScenario "the grid has three cells"
When "I create a cell at", 2, 0
Then "the grid should look like", %(
XX.
...
X.X
)
end
end

View file

@ -0,0 +1,6 @@
dir = File.dirname(__FILE__)
$LOAD_PATH.unshift(File.expand_path("#{dir}/../../../../../../rspec/lib"))
require 'spec'
$LOAD_PATH.unshift(File.expand_path("#{dir}/../../"))
require "#{dir}/../../life"
require File.join(File.dirname(__FILE__), *%w[steps])

View file

@ -0,0 +1,26 @@
require File.join(File.dirname(__FILE__), *%w[helper])
Story 'I can kill a cell',
%(As a game producer
I want to kill a cell
So that when I make a mistake I don't have to start again), :steps_for => :life do
Scenario "bang, you're dead" do
Given 'a game that looks like', %(
XX.
.X.
..X
) do |dots|
@game = Game.from_string dots
end
When 'I destroy the cell at', 0, 1 do |row,col|
@game.destroy_at(row,col)
end
Then 'the grid should look like', %(
X..
.X.
..X
)
end
end

View file

@ -0,0 +1,5 @@
steps_for :life do
Then "the grid should look like" do |dots|
@game.grid.should == Grid.from_string(dots)
end
end

View file

@ -0,0 +1,3 @@
require File.join(File.dirname(__FILE__), *%w[helper])
require 'behaviour/stories/create_a_cell'
require 'behaviour/stories/kill_a_cell'

View file

@ -0,0 +1,22 @@
Story: Show the game field
As a game player
I want to see the field
so that I can observe the progress of the organisms
Scenario: an empty field
Given a new game starts
When the game displays the field
Then the field should be empty
StoryBuilder story = stories.createStory().called("a story")
.asA("person")
.iWant("to do something")
.soThat("I can rule the world");
story.addScenario().called("happy path").as()
.given("some context")
.when("some event happens")
.then("expect some outcome");

View file

@ -0,0 +1,3 @@
$: << File.dirname(__FILE__)
require 'life/game'
require 'life/grid'

View file

@ -0,0 +1,23 @@
class Game
attr_accessor :grid
def initialize(rows,cols)
@grid = Grid.new(rows, cols)
end
def create_at(row,col)
@grid.create_at(row,col)
end
def destroy_at(row,col)
@grid.destroy_at(row, col)
end
def self.from_string(dots)
grid = Grid.from_string(dots)
game = new(grid.rows, grid.columns)
game.instance_eval do
@grid = grid
end
return game
end
end

View file

@ -0,0 +1,43 @@
class Grid
attr_accessor :contents
def initialize(rows, cols)
@contents = []
rows.times do @contents << [0] * cols end
end
def rows
@contents.size
end
def columns
@contents[0].size
end
def ==(other)
self.contents == other.contents
end
def create_at(row,col)
@contents[row][col] = 1
end
def destroy_at(row,col)
@contents[row][col] = 0
end
def self.from_string(str)
row_strings = str.split(' ')
grid = new(row_strings.size, row_strings[0].size)
row_strings.each_with_index do |row, row_index|
row_chars = row.split(//)
row_chars.each_with_index do |col_char, col_index|
grid.create_at(row_index, col_index) if col_char == 'X'
end
end
return grid
end
end

View file

@ -0,0 +1,9 @@
$:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
require 'spec/story'
# won't have to do this once plain_text_story_runner is moved into the library
# require File.join(File.dirname(__FILE__), "plain_text_story_runner")
Dir[File.join(File.dirname(__FILE__), "steps/*.rb")].each do |file|
require file
end

View file

@ -0,0 +1,18 @@
require File.expand_path("#{File.dirname(__FILE__)}/../helper")
# This creates steps for :addition
steps_for(:addition) do
Given("an addend of $addend") do |addend|
@adder ||= Adder.new
@adder << addend.to_i
end
end
# This appends to them
steps_for(:addition) do
When("the addends are added") { @sum = @adder.sum }
end
steps_for(:more_addition) do
Then("the sum should be $sum") { |sum| @sum.should == sum.to_i }
end

View file

@ -0,0 +1,7 @@
"Why have failing examples?", you might ask.
They allow us to see failure messages. RSpec wants to provide meaningful and helpful failure messages. The failures in this directory not only provide you a way of seeing the failure messages, but they provide RSpec's own specs a way of describing what they should look like and ensuring they stay correct.
To see the types of messages you can expect, stand in this directory and run:
../bin/spec ./*.rb

View file

@ -0,0 +1,36 @@
describe "Running specs with --diff" do
it "should print diff of different strings" do
uk = <<-EOF
RSpec is a
behaviour driven development
framework for Ruby
EOF
usa = <<-EOF
RSpec is a
behavior driven development
framework for Ruby
EOF
usa.should == uk
end
class Animal
def initialize(name,species)
@name,@species = name,species
end
def inspect
<<-EOA
<Animal
name=#{@name},
species=#{@species}
>
EOA
end
end
it "should print diff of different objects' pretty representation" do
expected = Animal.new "bob", "giraffe"
actual = Animal.new "bob", "tortoise"
expected.should eql(actual)
end
end

View file

@ -0,0 +1,19 @@
require File.dirname(__FILE__) + '/spec_helper'
# Run spec w/ -fs to see the output of this file
describe "Failing examples with no descriptions" do
# description is auto-generated as "should equal(5)" based on the last #should
it do
3.should equal(2)
5.should equal(5)
end
it { 3.should be > 5 }
it { ["a"].should include("b") }
it { [1,2,3].should_not respond_to(:size) }
end

View file

@ -0,0 +1,10 @@
describe "This example" do
before(:each) do
NonExistentClass.new
end
it "should be listed as failing in setup" do
end
end

View file

@ -0,0 +1,10 @@
describe "This example" do
it "should be listed as failing in teardown" do
end
after(:each) do
NonExistentClass.new
end
end

View file

@ -0,0 +1,40 @@
require File.dirname(__FILE__) + '/spec_helper'
describe "Mocker" do
it "should be able to call mock()" do
mock = mock("poke me")
mock.should_receive(:poke)
mock.poke
end
it "should fail when expected message not received" do
mock = mock("poke me")
mock.should_receive(:poke)
end
it "should fail when messages are received out of order" do
mock = mock("one two three")
mock.should_receive(:one).ordered
mock.should_receive(:two).ordered
mock.should_receive(:three).ordered
mock.one
mock.three
mock.two
end
it "should get yelled at when sending unexpected messages" do
mock = mock("don't talk to me")
mock.should_not_receive(:any_message_at_all)
mock.any_message_at_all
end
it "has a bug we need to fix" do
pending "here is the bug" do
# Actually, no. It's fixed. This will fail because it passes :-)
mock = mock("Bug")
mock.should_receive(:hello)
mock.hello
end
end
end

View file

@ -0,0 +1,26 @@
# stub frameworks like to gum up Object, so this is deliberately
# set NOT to run so that you don't accidentally run it when you
# run this dir.
# To run it, stand in this directory and say:
#
# RUN_FLEXMOCK_EXAMPLE=true ruby ../bin/spec mocking_with_flexmock.rb
if ENV['RUN_FLEXMOCK_EXAMPLE']
Spec::Runner.configure do |config|
config.mock_with :flexmock
end
describe "Flexmocks" do
it "should fail when the expected message is received with wrong arguments" do
m = flexmock("now flex!")
m.should_receive(:msg).with("arg").once
m.msg("other arg")
end
it "should fail when the expected message is not received at all" do
m = flexmock("now flex!")
m.should_receive(:msg).with("arg").once
end
end
end

View file

@ -0,0 +1,25 @@
# stub frameworks like to gum up Object, so this is deliberately
# set NOT to run so that you don't accidentally run it when you
# run this dir.
# To run it, stand in this directory and say:
#
# RUN_MOCHA_EXAMPLE=true ruby ../bin/spec mocking_with_mocha.rb
if ENV['RUN_MOCHA_EXAMPLE']
Spec::Runner.configure do |config|
config.mock_with :mocha
end
describe "Mocha framework" do
it "should should be made available by saying config.mock_with :mocha" do
m = mock()
m.expects(:msg).with("arg")
m.msg
end
it "should should be made available by saying config.mock_with :mocha" do
o = Object.new
o.expects(:msg).with("arg")
o.msg
end
end
end

View file

@ -0,0 +1,27 @@
# stub frameworks like to gum up Object, so this is deliberately
# set NOT to run so that you don't accidentally run it when you
# run this dir.
# To run it, stand in this directory and say:
#
# RUN_RR_EXAMPLE=true ruby ../bin/spec mocking_with_rr.rb
if ENV['RUN_RR_EXAMPLE']
Spec::Runner.configure do |config|
config.mock_with :rr
end
describe "RR framework" do
it "should should be made available by saying config.mock_with :rr" do
o = Object.new
mock(o).msg("arg")
o.msg
end
it "should should be made available by saying config.mock_with :rr" do
o = Object.new
mock(o) do |m|
m.msg("arg")
end
o.msg
end
end
end

View file

@ -0,0 +1,20 @@
require File.dirname(__FILE__) + '/spec_helper'
class MockableClass
def self.find id
return :original_return
end
end
describe "A partial mock" do
it "should work at the class level (but fail here due to the type mismatch)" do
MockableClass.should_receive(:find).with(1).and_return {:stub_return}
MockableClass.find("1").should equal(:stub_return)
end
it "should revert to the original after each spec" do
MockableClass.find(1).should equal(:original_return)
end
end

View file

@ -0,0 +1,29 @@
require File.dirname(__FILE__) + '/spec_helper'
class BddFramework
def intuitive?
true
end
def adopted_quickly?
#this will cause failures because it reallly SHOULD be adopted quickly
false
end
end
describe "BDD framework" do
before(:each) do
@bdd_framework = BddFramework.new
end
it "should be adopted quickly" do
#this will fail because it reallly SHOULD be adopted quickly
@bdd_framework.should be_adopted_quickly
end
it "should be intuitive" do
@bdd_framework.should be_intuitive
end
end

View file

@ -0,0 +1,47 @@
describe "This example" do
it "should show that a NoMethodError is raised but an Exception was expected" do
proc { ''.nonexistent_method }.should raise_error
end
it "should pass" do
proc { ''.nonexistent_method }.should raise_error(NoMethodError)
end
it "should show that a NoMethodError is raised but a SyntaxError was expected" do
proc { ''.nonexistent_method }.should raise_error(SyntaxError)
end
it "should show that nothing is raised when SyntaxError was expected" do
proc { }.should raise_error(SyntaxError)
end
it "should show that a NoMethodError is raised but a Exception was expected" do
proc { ''.nonexistent_method }.should_not raise_error
end
it "should show that a NoMethodError is raised" do
proc { ''.nonexistent_method }.should_not raise_error(NoMethodError)
end
it "should also pass" do
proc { ''.nonexistent_method }.should_not raise_error(SyntaxError)
end
it "should show that a NoMethodError is raised when nothing expected" do
proc { ''.nonexistent_method }.should_not raise_error(Exception)
end
it "should show that the wrong message was received" do
proc { raise StandardError.new("what is an enterprise?") }.should raise_error(StandardError, "not this")
end
it "should show that the unexpected error/message was thrown" do
proc { raise StandardError.new("abc") }.should_not raise_error(StandardError, "abc")
end
it "should pass too" do
proc { raise StandardError.new("abc") }.should_not raise_error(StandardError, "xyz")
end
end

View file

@ -0,0 +1,3 @@
lib_path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
require "spec"

View file

@ -0,0 +1,7 @@
describe "when passing a block to a matcher" do
it "you should use {} instead of do/end" do
Object.new.should satisfy do
"this block is being passed to #should instead of #satisfy - use {} instead"
end
end
end

View file

@ -0,0 +1,44 @@
require File.dirname(__FILE__) + '/spec_helper'
class Team
attr_reader :players
def initialize
@players = Players.new
end
end
class Players
def initialize
@players = []
end
def size
@players.size
end
def include? player
raise "player must be a string" unless player.is_a?(String)
@players.include? player
end
end
describe "A new team" do
before(:each) do
@team = Team.new
end
it "should have 3 players (failing example)" do
@team.should have(3).players
end
it "should include some player (failing example)" do
@team.players.should include("Some Player")
end
it "should include 5 (failing example)" do
@team.players.should include(5)
end
it "should have no players"
end

View file

@ -0,0 +1,7 @@
require File.dirname(__FILE__) + '/spec_helper'
describe "Something really slow" do
it "should be failed by RSpec when it takes longer than --timeout" do
sleep(2)
end
end

9
vendor/plugins/rspec/init.rb vendored Normal file
View file

@ -0,0 +1,9 @@
# Placeholder to satisfy Rails.
#
# Do NOT add any require statements to this file. Doing
# so will cause Rails to load this plugin all of the time.
#
# Running 'ruby script/generate rspec' will
# generate spec/spec_helper.rb, which includes the necessary
# require statements and configuration. This file should
# be required by all of your spec files.

View file

@ -0,0 +1,3 @@
Autotest.add_discovery do
"rspec" if File.exist?('spec')
end

View file

@ -0,0 +1,72 @@
require 'autotest'
Autotest.add_hook :initialize do |at|
at.clear_mappings
# watch out: Ruby bug (1.8.6):
# %r(/) != /\//
at.add_mapping(%r%^spec/.*\.rb$%) { |filename, _|
filename
}
at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m|
["spec/#{m[1]}_spec.rb"]
}
at.add_mapping(%r%^spec/(spec_helper|shared/.*)\.rb$%) {
at.files_matching %r%^spec/.*_spec\.rb$%
}
end
class RspecCommandError < StandardError; end
class Autotest::Rspec < Autotest
def initialize
super
self.failed_results_re = /^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m
self.completed_re = /\n(?:\e\[\d*m)?\d* examples?/m
end
def consolidate_failures(failed)
filters = new_hash_of_arrays
failed.each do |spec, trace|
if trace =~ /\n(\.\/)?(.*spec\.rb):[\d]+:\Z?/
filters[$2] << spec
end
end
return filters
end
def make_test_cmd(files_to_test)
return "#{ruby} -S #{spec_command} #{add_options_if_present} #{files_to_test.keys.flatten.join(' ')}"
end
def add_options_if_present # :nodoc:
File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : ""
end
# Finds the proper spec command to use. Precendence is set in the
# lazily-evaluated method spec_commands. Alias + Override that in
# ~/.autotest to provide a different spec command then the default
# paths provided.
def spec_command(separator=File::ALT_SEPARATOR)
unless defined? @spec_command then
@spec_command = spec_commands.find { |cmd| File.exists? cmd }
raise RspecCommandError, "No spec command could be found!" unless @spec_command
@spec_command.gsub! File::SEPARATOR, separator if separator
end
@spec_command
end
# Autotest will look for spec commands in the following
# locations, in this order:
#
# * bin/spec
# * default spec bin/loader installed in Rubygems
def spec_commands
[
File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec')),
File.join(Config::CONFIG['bindir'], 'spec')
]
end
end

31
vendor/plugins/rspec/lib/spec.rb vendored Normal file
View file

@ -0,0 +1,31 @@
require 'spec/version'
require 'spec/matchers'
require 'spec/expectations'
require 'spec/example'
require 'spec/extensions'
require 'spec/runner'
require 'spec/adapters'
if Object.const_defined?(:Test)
require 'spec/interop/test'
end
module Spec
class << self
def run?
@run || rspec_options.examples_run?
end
def run
return true if run?
result = rspec_options.run_examples
@run = true
result
end
attr_writer :run
def exit?
!Object.const_defined?(:Test) || Test::Unit.run?
end
end
end

View file

@ -0,0 +1 @@
require 'spec/adapters/ruby_engine'

View file

@ -0,0 +1,26 @@
require 'spec/adapters/ruby_engine/mri'
require 'spec/adapters/ruby_engine/rubinius'
module Spec
module Adapters
module RubyEngine
ENGINES = {
'mri' => MRI.new,
'rbx' => Rubinius.new
}
def self.engine
if const_defined?(:RUBY_ENGINE)
return RUBY_ENGINE
else
return 'mri'
end
end
def self.adapter
return ENGINES[engine]
end
end
end
end

View file

@ -0,0 +1,8 @@
module Spec
module Adapters
module RubyEngine
class MRI
end
end
end
end

View file

@ -0,0 +1,8 @@
module Spec
module Adapters
module RubyEngine
class Rubinius
end
end
end
end

View file

@ -0,0 +1,12 @@
require 'timeout'
require 'spec/example/pending'
require 'spec/example/module_reopening_fix'
require 'spec/example/module_inclusion_warnings'
require 'spec/example/example_group_methods'
require 'spec/example/example_methods'
require 'spec/example/example_group'
require 'spec/example/shared_example_group'
require 'spec/example/example_group_factory'
require 'spec/example/errors'
require 'spec/example/configuration'
require 'spec/example/example_matcher'

View file

@ -0,0 +1,158 @@
module Spec
module Example
class Configuration
# Chooses what mock framework to use. Example:
#
# Spec::Runner.configure do |config|
# config.mock_with :rspec, :mocha, :flexmock, or :rr
# end
#
# To use any other mock framework, you'll have to provide your own
# adapter. This is simply a module that responds to the following
# methods:
#
# setup_mocks_for_rspec
# verify_mocks_for_rspec
# teardown_mocks_for_rspec.
#
# These are your hooks into the lifecycle of a given example. RSpec will
# call setup_mocks_for_rspec before running anything else in each
# Example. After executing the #after methods, RSpec will then call
# verify_mocks_for_rspec and teardown_mocks_for_rspec (this is
# guaranteed to run even if there are failures in
# verify_mocks_for_rspec).
#
# Once you've defined this module, you can pass that to mock_with:
#
# Spec::Runner.configure do |config|
# config.mock_with MyMockFrameworkAdapter
# end
#
def mock_with(mock_framework)
@mock_framework = case mock_framework
when Symbol
mock_framework_path(mock_framework.to_s)
else
mock_framework
end
end
def mock_framework # :nodoc:
@mock_framework ||= mock_framework_path("rspec")
end
# :call-seq:
# include(Some::Helpers)
# include(Some::Helpers, More::Helpers)
# include(My::Helpers, :type => :key)
#
# Declares modules to be included in multiple example groups
# (<tt>describe</tt> blocks). With no :type, the modules listed will be
# included in all example groups. Use :type to restrict the inclusion to
# a subset of example groups. The value assigned to :type should be a
# key that maps to a class that is either a subclass of
# Spec::Example::ExampleGroup or extends Spec::Example::ExampleGroupMethods
# and includes Spec::Example::ExampleMethods
#
# config.include(My::Pony, My::Horse, :type => :farm)
#
# Only example groups that have that type will get the modules included:
#
# describe "Downtown", :type => :city do
# # Will *not* get My::Pony and My::Horse included
# end
#
# describe "Old Mac Donald", :type => :farm do
# # *Will* get My::Pony and My::Horse included
# end
#
def include(*args)
args << {} unless Hash === args.last
modules, options = args_and_options(*args)
required_example_group = get_type_from_options(options)
required_example_group = required_example_group.to_sym if required_example_group
modules.each do |mod|
ExampleGroupFactory.get(required_example_group).send(:include, mod)
end
end
# Defines global predicate matchers. Example:
#
# config.predicate_matchers[:swim] = :can_swim?
#
# This makes it possible to say:
#
# person.should swim # passes if person.can_swim? returns true
#
def predicate_matchers
@predicate_matchers ||= {}
end
# Prepends a global <tt>before</tt> block to all example groups.
# See #append_before for filtering semantics.
def prepend_before(*args, &proc)
scope, options = scope_and_options(*args)
example_group = ExampleGroupFactory.get(
get_type_from_options(options)
)
example_group.prepend_before(scope, &proc)
end
# Appends a global <tt>before</tt> block to all example groups.
#
# If you want to restrict the block to a subset of all the example
# groups then specify this in a Hash as the last argument:
#
# config.prepend_before(:all, :type => :farm)
#
# or
#
# config.prepend_before(:type => :farm)
#
def append_before(*args, &proc)
scope, options = scope_and_options(*args)
example_group = ExampleGroupFactory.get(
get_type_from_options(options)
)
example_group.append_before(scope, &proc)
end
alias_method :before, :append_before
# Prepends a global <tt>after</tt> block to all example groups.
# See #append_before for filtering semantics.
def prepend_after(*args, &proc)
scope, options = scope_and_options(*args)
example_group = ExampleGroupFactory.get(
get_type_from_options(options)
)
example_group.prepend_after(scope, &proc)
end
alias_method :after, :prepend_after
# Appends a global <tt>after</tt> block to all example groups.
# See #append_before for filtering semantics.
def append_after(*args, &proc)
scope, options = scope_and_options(*args)
example_group = ExampleGroupFactory.get(
get_type_from_options(options)
)
example_group.append_after(scope, &proc)
end
private
def scope_and_options(*args)
args, options = args_and_options(*args)
scope = (args[0] || :each), options
end
def get_type_from_options(options)
options[:type] || options[:behaviour_type]
end
def mock_framework_path(framework_name)
File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "plugins", "mock_frameworks", framework_name))
end
end
end
end

View file

@ -0,0 +1,9 @@
module Spec
module Example
class ExamplePendingError < StandardError
end
class PendingExampleFixedError < StandardError
end
end
end

View file

@ -0,0 +1,17 @@
module Spec
module Example
# Base class for customized example groups. Use this if you
# want to make a custom example group.
class ExampleGroup
extend Spec::Example::ExampleGroupMethods
include Spec::Example::ExampleMethods
def initialize(defined_description, &implementation)
@_defined_description = defined_description
@_implementation = implementation
end
end
end
end
Spec::ExampleGroup = Spec::Example::ExampleGroup

View file

@ -0,0 +1,64 @@
module Spec
module Example
class ExampleGroupFactory
class << self
def reset
@example_group_types = nil
default(ExampleGroup)
end
# Registers an example group class +klass+ with the symbol +type+. For
# example:
#
# Spec::Example::ExampleGroupFactory.register(:farm, FarmExampleGroup)
#
# With that you can append a hash with :type => :farm to the describe
# method and it will load an instance of FarmExampleGroup.
#
# describe Pig, :type => :farm do
# ...
#
# If you don't use the hash explicitly, <tt>describe</tt> will
# implicitly use an instance of FarmExampleGroup for any file loaded
# from the <tt>./spec/farm</tt> directory.
def register(key, example_group_class)
@example_group_types[key] = example_group_class
end
# Sets the default ExampleGroup class
def default(example_group_class)
old = @example_group_types
@example_group_types = Hash.new(example_group_class)
@example_group_types.merge!(old) if old
end
def get(key=nil)
if @example_group_types.values.include?(key)
key
else
@example_group_types[key]
end
end
def create_example_group(*args, &block)
opts = Hash === args.last ? args.last : {}
superclass = determine_superclass(opts)
superclass.describe(*args, &block)
end
protected
def determine_superclass(opts)
key = if opts[:type]
opts[:type]
elsif opts[:spec_path] =~ /spec(\\|\/)(#{@example_group_types.keys.join('|')})/
$2 == '' ? nil : $2.to_sym
end
get(key)
end
end
self.reset
end
end
end

View file

@ -0,0 +1,440 @@
module Spec
module Example
module ExampleGroupMethods
class << self
attr_accessor :matcher_class
def description_text(*args)
args.inject("") do |result, arg|
result << " " unless (result == "" || arg.to_s =~ /^(\s|\.|#)/)
result << arg.to_s
end
end
end
attr_reader :description_text, :description_args, :description_options, :spec_path, :registration_binding_block
def inherited(klass)
super
klass.register {}
Spec::Runner.register_at_exit_hook
end
# Makes the describe/it syntax available from a class. For example:
#
# class StackSpec < Spec::ExampleGroup
# describe Stack, "with no elements"
#
# before
# @stack = Stack.new
# end
#
# it "should raise on pop" do
# lambda{ @stack.pop }.should raise_error
# end
# end
#
def describe(*args, &example_group_block)
args << {} unless Hash === args.last
if example_group_block
params = args.last
params[:spec_path] = eval("caller(0)[1]", example_group_block) unless params[:spec_path]
if params[:shared]
SharedExampleGroup.new(*args, &example_group_block)
else
self.subclass("Subclass") do
describe(*args)
module_eval(&example_group_block)
end
end
else
set_description(*args)
before_eval
self
end
end
alias :context :describe
# Use this to pull in examples from shared example groups.
# See Spec::Runner for information about shared example groups.
def it_should_behave_like(shared_example_group)
case shared_example_group
when SharedExampleGroup
include shared_example_group
else
example_group = SharedExampleGroup.find_shared_example_group(shared_example_group)
unless example_group
raise RuntimeError.new("Shared Example Group '#{shared_example_group}' can not be found")
end
include(example_group)
end
end
# :call-seq:
# predicate_matchers[matcher_name] = method_on_object
# predicate_matchers[matcher_name] = [method1_on_object, method2_on_object]
#
# Dynamically generates a custom matcher that will match
# a predicate on your class. RSpec provides a couple of these
# out of the box:
#
# exist (or state expectations)
# File.should exist("path/to/file")
#
# an_instance_of (for mock argument constraints)
# mock.should_receive(:message).with(an_instance_of(String))
#
# == Examples
#
# class Fish
# def can_swim?
# true
# end
# end
#
# describe Fish do
# predicate_matchers[:swim] = :can_swim?
# it "should swim" do
# Fish.new.should swim
# end
# end
def predicate_matchers
@predicate_matchers ||= {:an_instance_of => :is_a?}
end
# Creates an instance of Spec::Example::Example and adds
# it to a collection of examples of the current example group.
def it(description=nil, &implementation)
e = new(description, &implementation)
example_objects << e
e
end
alias_method :specify, :it
# Use this to temporarily disable an example.
def xit(description=nil, opts={}, &block)
Kernel.warn("Example disabled: #{description}")
end
alias_method :xspecify, :xit
def run
examples = examples_to_run
reporter.add_example_group(self) unless examples_to_run.empty?
return true if examples.empty?
return dry_run(examples) if dry_run?
plugin_mock_framework
define_methods_from_predicate_matchers
success, before_all_instance_variables = run_before_all
success, after_all_instance_variables = execute_examples(success, before_all_instance_variables, examples)
success = run_after_all(success, after_all_instance_variables)
end
def description
result = ExampleGroupMethods.description_text(*description_parts)
if result.nil? || result == ""
return to_s
else
result
end
end
def described_type
description_parts.find {|part| part.is_a?(Module)}
end
def description_parts #:nodoc:
parts = []
execute_in_class_hierarchy do |example_group|
parts << example_group.description_args
end
parts.flatten.compact
end
def set_description(*args)
args, options = args_and_options(*args)
@description_args = args
@description_options = options
@description_text = ExampleGroupMethods.description_text(*args)
@spec_path = File.expand_path(options[:spec_path]) if options[:spec_path]
if described_type.class == Module
@described_module = described_type
end
self
end
attr_reader :described_module
def examples #:nodoc:
examples = example_objects.dup
add_method_examples(examples)
rspec_options.reverse ? examples.reverse : examples
end
def number_of_examples #:nodoc:
examples.length
end
# Registers a block to be executed before each example.
# This method prepends +block+ to existing before blocks.
def prepend_before(*args, &block)
scope, options = scope_and_options(*args)
parts = before_parts_from_scope(scope)
parts.unshift(block)
end
# Registers a block to be executed before each example.
# This method appends +block+ to existing before blocks.
def append_before(*args, &block)
scope, options = scope_and_options(*args)
parts = before_parts_from_scope(scope)
parts << block
end
alias_method :before, :append_before
# Registers a block to be executed after each example.
# This method prepends +block+ to existing after blocks.
def prepend_after(*args, &block)
scope, options = scope_and_options(*args)
parts = after_parts_from_scope(scope)
parts.unshift(block)
end
alias_method :after, :prepend_after
# Registers a block to be executed after each example.
# This method appends +block+ to existing after blocks.
def append_after(*args, &block)
scope, options = scope_and_options(*args)
parts = after_parts_from_scope(scope)
parts << block
end
def remove_after(scope, &block)
after_each_parts.delete(block)
end
# Deprecated. Use before(:each)
def setup(&block)
before(:each, &block)
end
# Deprecated. Use after(:each)
def teardown(&block)
after(:each, &block)
end
def before_all_parts # :nodoc:
@before_all_parts ||= []
end
def after_all_parts # :nodoc:
@after_all_parts ||= []
end
def before_each_parts # :nodoc:
@before_each_parts ||= []
end
def after_each_parts # :nodoc:
@after_each_parts ||= []
end
# Only used from RSpec's own examples
def reset # :nodoc:
@before_all_parts = nil
@after_all_parts = nil
@before_each_parts = nil
@after_each_parts = nil
end
def register(&registration_binding_block)
@registration_binding_block = registration_binding_block
rspec_options.add_example_group self
end
def unregister #:nodoc:
rspec_options.remove_example_group self
end
def registration_backtrace
eval("caller", registration_binding_block)
end
def run_before_each(example)
execute_in_class_hierarchy do |example_group|
example.eval_each_fail_fast(example_group.before_each_parts)
end
end
def run_after_each(example)
execute_in_class_hierarchy(:superclass_first) do |example_group|
example.eval_each_fail_slow(example_group.after_each_parts)
end
end
private
def dry_run(examples)
examples.each do |example|
rspec_options.reporter.example_started(example)
rspec_options.reporter.example_finished(example)
end
return true
end
def run_before_all
before_all = new("before(:all)")
begin
execute_in_class_hierarchy do |example_group|
before_all.eval_each_fail_fast(example_group.before_all_parts)
end
return [true, before_all.instance_variable_hash]
rescue Exception => e
reporter.failure(before_all, e)
return [false, before_all.instance_variable_hash]
end
end
def execute_examples(success, instance_variables, examples)
return [success, instance_variables] unless success
after_all_instance_variables = instance_variables
examples.each do |example_group_instance|
success &= example_group_instance.execute(rspec_options, instance_variables)
after_all_instance_variables = example_group_instance.instance_variable_hash
end
return [success, after_all_instance_variables]
end
def run_after_all(success, instance_variables)
after_all = new("after(:all)")
after_all.set_instance_variables_from_hash(instance_variables)
execute_in_class_hierarchy(:superclass_first) do |example_group|
after_all.eval_each_fail_slow(example_group.after_all_parts)
end
return success
rescue Exception => e
reporter.failure(after_all, e)
return false
end
def examples_to_run
all_examples = examples
return all_examples unless specified_examples?
all_examples.reject do |example|
matcher = ExampleGroupMethods.matcher_class.
new(description.to_s, example.description)
!matcher.matches?(specified_examples)
end
end
def specified_examples?
specified_examples && !specified_examples.empty?
end
def specified_examples
rspec_options.examples
end
def reporter
rspec_options.reporter
end
def dry_run?
rspec_options.dry_run
end
def example_objects
@example_objects ||= []
end
def execute_in_class_hierarchy(superclass_last=false)
classes = []
current_class = self
while is_example_group?(current_class)
superclass_last ? classes << current_class : classes.unshift(current_class)
current_class = current_class.superclass
end
superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods)
classes.each do |example_group|
yield example_group
end
end
def is_example_group?(klass)
Module === klass && klass.kind_of?(ExampleGroupMethods)
end
def plugin_mock_framework
case mock_framework = Spec::Runner.configuration.mock_framework
when Module
include mock_framework
else
require Spec::Runner.configuration.mock_framework
include Spec::Plugins::MockFramework
end
end
def define_methods_from_predicate_matchers # :nodoc:
all_predicate_matchers = predicate_matchers.merge(
Spec::Runner.configuration.predicate_matchers
)
all_predicate_matchers.each_pair do |matcher_method, method_on_object|
define_method matcher_method do |*args|
eval("be_#{method_on_object.to_s.gsub('?','')}(*args)")
end
end
end
def scope_and_options(*args)
args, options = args_and_options(*args)
scope = (args[0] || :each), options
end
def before_parts_from_scope(scope)
case scope
when :each; before_each_parts
when :all; before_all_parts
when :suite; rspec_options.before_suite_parts
end
end
def after_parts_from_scope(scope)
case scope
when :each; after_each_parts
when :all; after_all_parts
when :suite; rspec_options.after_suite_parts
end
end
def before_eval
end
def add_method_examples(examples)
instance_methods.sort.each do |method_name|
if example_method?(method_name)
examples << new(method_name) do
__send__(method_name)
end
end
end
end
def example_method?(method_name)
should_method?(method_name)
end
def should_method?(method_name)
!(method_name =~ /^should(_not)?$/) &&
method_name =~ /^should/ && (
instance_method(method_name).arity == 0 ||
instance_method(method_name).arity == -1
)
end
end
end
end

View file

@ -0,0 +1,44 @@
module Spec
module Example
class ExampleMatcher
def initialize(example_group_description, example_name)
@example_group_description = example_group_description
@example_name = example_name
end
def matches?(specified_examples)
specified_examples.each do |specified_example|
return true if matches_literal_example?(specified_example) || matches_example_not_considering_modules?(specified_example)
end
false
end
protected
def matches_literal_example?(specified_example)
specified_example =~ /(^#{example_group_regex} #{example_regexp}$|^#{example_group_regex}$|^#{example_group_with_before_all_regexp}$|^#{example_regexp}$)/
end
def matches_example_not_considering_modules?(specified_example)
specified_example =~ /(^#{example_group_regex_not_considering_modules} #{example_regexp}$|^#{example_group_regex_not_considering_modules}$|^#{example_regexp}$)/
end
def example_group_regex
Regexp.escape(@example_group_description)
end
def example_group_with_before_all_regexp
Regexp.escape("#{@example_group_description} before(:all)")
end
def example_group_regex_not_considering_modules
Regexp.escape(@example_group_description.split('::').last)
end
def example_regexp
Regexp.escape(@example_name)
end
end
ExampleGroupMethods.matcher_class = ExampleMatcher
end
end

View file

@ -0,0 +1,112 @@
module Spec
module Example
module ExampleMethods
extend ExampleGroupMethods
extend ModuleReopeningFix
include ModuleInclusionWarnings
PENDING_EXAMPLE_BLOCK = lambda {
raise Spec::Example::ExamplePendingError.new("Not Yet Implemented")
}
def execute(options, instance_variables)
options.reporter.example_started(self)
set_instance_variables_from_hash(instance_variables)
execution_error = nil
Timeout.timeout(options.timeout) do
begin
before_example
run_with_description_capturing
rescue Exception => e
execution_error ||= e
end
begin
after_example
rescue Exception => e
execution_error ||= e
end
end
options.reporter.example_finished(self, execution_error)
success = execution_error.nil? || ExamplePendingError === execution_error
end
def instance_variable_hash
instance_variables.inject({}) do |variable_hash, variable_name|
variable_hash[variable_name] = instance_variable_get(variable_name)
variable_hash
end
end
def violated(message="")
raise Spec::Expectations::ExpectationNotMetError.new(message)
end
def eval_each_fail_fast(procs) #:nodoc:
procs.each do |proc|
instance_eval(&proc)
end
end
def eval_each_fail_slow(procs) #:nodoc:
first_exception = nil
procs.each do |proc|
begin
instance_eval(&proc)
rescue Exception => e
first_exception ||= e
end
end
raise first_exception if first_exception
end
def description
@_defined_description || @_matcher_description || "NO NAME"
end
def __full_description
"#{self.class.description} #{self.description}"
end
def set_instance_variables_from_hash(ivars)
ivars.each do |variable_name, value|
# Ruby 1.9 requires variable.to_s on the next line
unless ['@_implementation', '@_defined_description', '@_matcher_description', '@method_name'].include?(variable_name.to_s)
instance_variable_set variable_name, value
end
end
end
def run_with_description_capturing
begin
return instance_eval(&(@_implementation || PENDING_EXAMPLE_BLOCK))
ensure
@_matcher_description = Spec::Matchers.generated_description
Spec::Matchers.clear_generated_description
end
end
def implementation_backtrace
eval("caller", @_implementation)
end
protected
include Matchers
include Pending
def before_example
setup_mocks_for_rspec
self.class.run_before_each(self)
end
def after_example
self.class.run_after_each(self)
verify_mocks_for_rspec
ensure
teardown_mocks_for_rspec
end
end
end
end

View file

@ -0,0 +1,37 @@
module Spec
module Example
# In the future, modules will no longer be automatically included
# in the Example Group (based on the description name); when that
# time comes, this code should be removed.
module ModuleInclusionWarnings
# Thanks, Francis Hwang.
class MethodDispatcher
def initialize(mod, target=nil)
@mod = mod
@target = target
end
def respond_to?(sym)
@mod && @mod.instance_methods.include?(sym.to_s)
end
def call(sym, *args, &blk)
Kernel.warn("Modules will no longer be automatically included in RSpec version 1.1.4. Called from #{caller[2]}")
@target.extend @mod
@target.send(sym, *args, &blk)
end
end
def respond_to?(sym)
MethodDispatcher.new(self.class.described_module).respond_to?(sym) ? true : super
end
private
def method_missing(sym, *args, &blk)
md = MethodDispatcher.new(self.class.described_module, self)
self.respond_to?(sym) ? md.call(sym, *args, &blk) : super
end
end
end
end

View file

@ -0,0 +1,21 @@
module Spec
module Example
# This is a fix for ...Something in Ruby 1.8.6??... (Someone fill in here please - Aslak)
module ModuleReopeningFix
def child_modules
@child_modules ||= []
end
def included(mod)
child_modules << mod
end
def include(mod)
super
child_modules.each do |child_module|
child_module.__send__(:include, mod)
end
end
end
end
end

View file

@ -0,0 +1,18 @@
module Spec
module Example
module Pending
def pending(message = "TODO")
if block_given?
begin
yield
rescue Exception => e
raise Spec::Example::ExamplePendingError.new(message)
end
raise Spec::Example::PendingExampleFixedError.new("Expected pending '#{message}' to fail. No Error was raised.")
else
raise Spec::Example::ExamplePendingError.new(message)
end
end
end
end
end

View file

@ -0,0 +1,58 @@
module Spec
module Example
class SharedExampleGroup < Module
class << self
def add_shared_example_group(new_example_group)
guard_against_redefining_existing_example_group(new_example_group)
shared_example_groups << new_example_group
end
def find_shared_example_group(example_group_description)
shared_example_groups.find do |b|
b.description == example_group_description
end
end
def shared_example_groups
# TODO - this needs to be global, or at least accessible from
# from subclasses of Example in a centralized place. I'm not loving
# this as a solution, but it works for now.
$shared_example_groups ||= []
end
private
def guard_against_redefining_existing_example_group(new_example_group)
existing_example_group = find_shared_example_group(new_example_group.description)
return unless existing_example_group
return if new_example_group.equal?(existing_example_group)
return if spec_path(new_example_group) == spec_path(existing_example_group)
raise ArgumentError.new("Shared Example '#{existing_example_group.description}' already exists")
end
def spec_path(example_group)
File.expand_path(example_group.spec_path)
end
end
include ExampleGroupMethods
public :include
def initialize(*args, &example_group_block)
describe(*args)
@example_group_block = example_group_block
self.class.add_shared_example_group(self)
end
def included(mod) # :nodoc:
mod.module_eval(&@example_group_block)
end
def execute_in_class_hierarchy(superclass_last=false)
classes = [self]
superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods)
classes.each do |example_group|
yield example_group
end
end
end
end
end

Some files were not shown because too many files have changed in this diff Show more