diff options
Diffstat (limited to 'spec')
92 files changed, 14 insertions, 6209 deletions
diff --git a/spec/bin/spec b/spec/bin/spec deleted file mode 100755 index aaf320f34..000000000 --- a/spec/bin/spec +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby -$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib")) -require 'spec' -::Spec::Runner::CommandLine.run(ARGV, STDERR, STDOUT, true, true) diff --git a/spec/lib/autotest/discover.rb b/spec/lib/autotest/discover.rb deleted file mode 100644 index 0ac563724..000000000 --- a/spec/lib/autotest/discover.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'autotest' - -Autotest.add_discovery do - "rspec" -end - -Autotest.add_discovery do - "puppet" -end diff --git a/spec/lib/autotest/puppet_rspec.rb b/spec/lib/autotest/puppet_rspec.rb deleted file mode 100644 index 8536f3912..000000000 --- a/spec/lib/autotest/puppet_rspec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'autotest' -require 'autotest/rspec' - -class Autotest::PuppetRspec < Autotest::Rspec - def initialize # :nodoc: - super - @test_mappings = { - # the libraries under lib/puppet - %r%^lib/puppet/(.*)\.rb$% => proc { |filename, m| - files_matching %r!spec/(unit|integration)/#{m[1]}.rb! - }, - - # the actual spec files themselves - %r%^spec/(unit|integration)/.*\.rb$% => proc { |filename, _| - filename - }, - - # force a complete re-run for all of these: - - # main puppet lib - %r!^lib/puppet\.rb$! => proc { |filename, _| - files_matching %r!spec/(unit|integration)/.*\.rb! - }, - - # the spec_helper - %r!^spec/spec_helper\.rb$! => proc { |filename, _| - files_matching %r!spec/(unit|integration)/.*\.rb! - }, - - # the puppet test libraries - %r!^test/lib/puppettest/.*! => proc { |filename, _| - files_matching %r!spec/(unit|integration)/.*\.rb! - }, - - # the puppet spec libraries - %r!^spec/lib/spec.*! => proc { |filename, _| - files_matching %r!spec/(unit|integration)/.*\.rb! - }, - - # the monkey patches for rspec - %r!^spec/lib/monkey_patches/.*! => proc { |filename, _| - files_matching %r!spec/(unit|integration)/.*\.rb! - }, - } - end -end diff --git a/spec/lib/autotest/rspec.rb b/spec/lib/autotest/rspec.rb deleted file mode 100644 index d4b77ea6b..000000000 --- a/spec/lib/autotest/rspec.rb +++ /dev/null @@ -1,95 +0,0 @@ -require 'autotest' - -class RspecCommandError < StandardError; end - -class Autotest::Rspec < Autotest - - def initialize(kernel=Kernel, separator=File::SEPARATOR, alt_separator=File::ALT_SEPARATOR) # :nodoc: - super() - @kernel, @separator, @alt_separator = kernel, separator, alt_separator - @spec_command = spec_command - - # watch out: Ruby bug (1.8.6): - # %r(/) != /\// - # since Ruby compares the REGEXP source, not the resulting pattern - @test_mappings = { - %r%^spec/.*\.rb$% => kernel.proc { |filename, _| - filename - }, - %r%^lib/(.*)\.rb$% => kernel.proc { |_, m| - ["spec/#{m[1]}_spec.rb"] - }, - %r%^spec/(spec_helper|shared/.*)\.rb$% => kernel.proc { - files_matching %r%^spec/.*_spec\.rb$% - } - } - end - - def tests_for_file(filename) - super.select { |f| @files.has_key? f } - end - - alias :specs_for_file :tests_for_file - - def failed_results(results) - results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m) - end - - def handle_results(results) - @files_to_test = consolidate_failures failed_results(results) - unless @files_to_test.empty? then - hook :red - else - hook :green - end unless $TESTING - @tainted = true unless @files_to_test.empty? - end - - def consolidate_failures(failed) - filters = Hash.new { |h,k| h[k] = [] } - failed.each do |spec, failed_trace| - @files.keys.select{|f| f =~ /spec\//}.each do |f| - if failed_trace =~ Regexp.new(f) - filters[f] << spec - break - end - 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 - 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 - spec_commands.each do |command| - if File.exists?(command) - return @alt_separator ? (command.gsub @separator, @alt_separator) : command - end - end - - raise RspecCommandError, "No spec command could be found!" - 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.join('bin', 'spec'), - File.join(Config::CONFIG['bindir'], 'spec') - ] - end - -end diff --git a/spec/lib/spec.rb b/spec/lib/spec.rb deleted file mode 100644 index 48c12595c..000000000 --- a/spec/lib/spec.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'spec/extensions' -require 'spec/version' -require 'spec/matchers' -require 'spec/expectations' -require 'spec/translator' -require 'spec/dsl' -require 'spec/runner' - -class Object - def metaclass - class << self; self; end - end -end diff --git a/spec/lib/spec/dsl.rb b/spec/lib/spec/dsl.rb deleted file mode 100644 index f960eb907..000000000 --- a/spec/lib/spec/dsl.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'spec/dsl/description' -require 'spec/dsl/errors' -require 'spec/dsl/configuration' -require 'spec/dsl/behaviour_callbacks' -require 'spec/dsl/behaviour' -require 'spec/dsl/behaviour_eval' -require 'spec/dsl/composite_proc_builder' -require 'spec/dsl/example' -require 'spec/dsl/example_matcher' -require 'spec/dsl/example_should_raise_handler' -require 'spec/dsl/behaviour_factory' diff --git a/spec/lib/spec/dsl/behaviour.rb b/spec/lib/spec/dsl/behaviour.rb deleted file mode 100644 index cc71ccffe..000000000 --- a/spec/lib/spec/dsl/behaviour.rb +++ /dev/null @@ -1,221 +0,0 @@ -require(File.expand_path(File.dirname(__FILE__) + '../../../../../test/lib/puppettest/runnable_test.rb')) - -module Spec - module DSL - class Behaviour - extend BehaviourCallbacks - - class << self - def add_shared_behaviour(behaviour) - return if behaviour.equal?(found_behaviour = find_shared_behaviour(behaviour.description)) - return if found_behaviour and File.expand_path(behaviour.description[:spec_path]) == File.expand_path(found_behaviour.description[:spec_path]) - raise ArgumentError.new("Shared Behaviour '#{behaviour.description}' already exists") if found_behaviour - shared_behaviours << behaviour - end - - def find_shared_behaviour(behaviour_description) - shared_behaviours.find { |b| b.description == behaviour_description } - end - - def shared_behaviours - # TODO - this needs to be global, or at least accessible from - # from subclasses of Behaviour in a centralized place. I'm not loving - # this as a solution, but it works for now. - $shared_behaviours ||= [] - end - end - - def initialize(*args, &behaviour_block) - init_description(*args) - init_eval_module - before_eval - eval_behaviour(&behaviour_block) - end - - private - - def init_description(*args) - unless self.class == Behaviour - args << {} unless Hash === args.last - args.last[:behaviour_class] = self.class - end - @description = Description.new(*args) - end - - def init_eval_module - @eval_module = EvalModule.new - @eval_module.extend BehaviourEval::ModuleMethods - @eval_module.include BehaviourEval::InstanceMethods - @eval_module.include described_type if described_type.class == Module - @eval_module.behaviour = self - @eval_module.description = @description - end - - def eval_behaviour(&behaviour_block) - @eval_module.class_eval(&behaviour_block) - end - - protected - - def before_eval - end - - public - - def run(reporter, dry_run=false, reverse=false, timeout=nil) - raise "shared behaviours should never run" if shared? - # TODO - change add_behaviour to add_description ?????? - reporter.add_behaviour(@description) - prepare_execution_context_class - before_all_errors = run_before_all(reporter, dry_run) - - exs = reverse ? examples.reverse : examples - example_execution_context = nil - - if before_all_errors.empty? - exs.each do |example| - example_execution_context = execution_context(example) - example_execution_context.copy_instance_variables_from(@before_and_after_all_context_instance) unless before_all_proc(behaviour_type).nil? - - befores = before_each_proc(behaviour_type) {|e| raise e} - afters = after_each_proc(behaviour_type) - example.run(reporter, befores, afters, dry_run, example_execution_context, timeout) - end - end - - @before_and_after_all_context_instance.copy_instance_variables_from(example_execution_context) unless after_all_proc(behaviour_type).nil? - run_after_all(reporter, dry_run) - end - - def number_of_examples - examples.length - end - - def matches?(specified_examples) - matcher ||= ExampleMatcher.new(description) - - examples.each do |example| - return true if example.matches?(matcher, specified_examples) - end - return false - end - - def shared? - @description[:shared] - end - - def retain_examples_matching!(specified_examples) - return if specified_examples.index(description) - matcher = ExampleMatcher.new(description) - examples.reject! do |example| - !example.matches?(matcher, specified_examples) - end - end - - def methods - my_methods = super - my_methods |= @eval_module.methods - my_methods - end - - # Includes modules in the Behaviour (the <tt>describe</tt> block). - def include(*args) - @eval_module.include(*args) - end - - def behaviour_type #:nodoc: - @description[:behaviour_type] - end - - # Sets the #number on each Example and returns the next number - def set_sequence_numbers(number, reverse) #:nodoc: - exs = reverse ? examples.reverse : examples - exs.each do |example| - example.number = number - number += 1 - end - number - end - - protected - - # Messages that this class does not understand - # are passed directly to the @eval_module. - def method_missing(sym, *args, &block) - @eval_module.send(sym, *args, &block) - end - - def prepare_execution_context_class - plugin_mock_framework - weave_in_included_modules - define_predicate_matchers #this is in behaviour_eval - execution_context_class - end - - def weave_in_included_modules - mods = [@eval_module] - mods << included_modules.dup - mods << Spec::Runner.configuration.modules_for(behaviour_type) - execution_context_class.class_eval do - # WARNING - the following can be executed in the context of any - # class, and should never pass more than one module to include - # even though we redefine include in this class. This is NOT - # tested anywhere, hence this comment. - mods.flatten.each {|mod| include mod} - end - end - - def execution_context(example) - execution_context_class.new(example) - end - - def run_before_all(reporter, dry_run) - errors = [] - unless dry_run - begin - @before_and_after_all_context_instance = execution_context(nil) - @before_and_after_all_context_instance.instance_eval(&before_all_proc(behaviour_type)) - rescue Exception => e - errors << e - location = "before(:all)" - # The easiest is to report this as an example failure. We don't have an Example - # at this point, so we'll just create a placeholder. - reporter.example_finished(Example.new(location), e, location) if reporter - end - end - errors - end - - def run_after_all(reporter, dry_run) - unless dry_run - begin - @before_and_after_all_context_instance ||= execution_context(nil) - @before_and_after_all_context_instance.instance_eval(&after_all_proc(behaviour_type)) - rescue Exception => e - location = "after(:all)" - reporter.example_finished(Example.new(location), e, location) if reporter - end - end - 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 description - @description.to_s - end - - def described_type - @description.described_type - end - - end - end -end diff --git a/spec/lib/spec/dsl/behaviour_callbacks.rb b/spec/lib/spec/dsl/behaviour_callbacks.rb deleted file mode 100644 index 8b69ad9e5..000000000 --- a/spec/lib/spec/dsl/behaviour_callbacks.rb +++ /dev/null @@ -1,82 +0,0 @@ -module Spec - module DSL - # See http://rspec.rubyforge.org/documentation/before_and_after.html - module BehaviourCallbacks - def prepend_before(*args, &block) - scope, options = scope_and_options(*args) - add(scope, options, :before, :unshift, &block) - end - def append_before(*args, &block) - scope, options = scope_and_options(*args) - add(scope, options, :before, :<<, &block) - end - alias_method :before, :append_before - - def prepend_after(*args, &block) - scope, options = scope_and_options(*args) - add(scope, options, :after, :unshift, &block) - end - alias_method :after, :prepend_after - def append_after(*args, &block) - scope, options = scope_and_options(*args) - add(scope, options, :after, :<<, &block) - end - - def scope_and_options(*args) - args, options = args_and_options(*args) - scope = (args[0] || :each), options - end - - def add(scope, options, where, how, &block) - scope ||= :each - options ||= {} - behaviour_type = options[:behaviour_type] - case scope - when :each; self.__send__("#{where}_each_parts", behaviour_type).__send__(how, block) - when :all; self.__send__("#{where}_all_parts", behaviour_type).__send__(how, block) - end - 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(behaviour_type=nil) # :nodoc: - @before_all_parts ||= {} - @before_all_parts[behaviour_type] ||= [] - end - - def after_all_parts(behaviour_type=nil) # :nodoc: - @after_all_parts ||= {} - @after_all_parts[behaviour_type] ||= [] - end - - def before_each_parts(behaviour_type=nil) # :nodoc: - @before_each_parts ||= {} - @before_each_parts[behaviour_type] ||= [] - end - - def after_each_parts(behaviour_type=nil) # :nodoc: - @after_each_parts ||= {} - @after_each_parts[behaviour_type] ||= [] - end - - def clear_before_and_after! # :nodoc: - @before_all_parts = nil - @after_all_parts = nil - @before_each_parts = nil - @after_each_parts = nil - end - end - end -end diff --git a/spec/lib/spec/dsl/behaviour_eval.rb b/spec/lib/spec/dsl/behaviour_eval.rb deleted file mode 100644 index 9f7b8281e..000000000 --- a/spec/lib/spec/dsl/behaviour_eval.rb +++ /dev/null @@ -1,231 +0,0 @@ -module Spec - module DSL - module BehaviourEval - module ModuleMethods - include BehaviourCallbacks - - attr_writer :behaviour - attr_accessor :description - - # RSpec runs every example in a new instance of Object, mixing in - # the behaviour necessary to run examples. Because this behaviour gets - # mixed in, it can get mixed in to an instance of any class at all. - # - # This is something that you would hardly ever use, but there is one - # common use case for it - inheriting from Test::Unit::TestCase. RSpec's - # Rails plugin uses this feature to provide access to all of the features - # that are available for Test::Unit within RSpec examples. - def inherit(klass) - raise ArgumentError.new("Shared behaviours cannot inherit from classes") if @behaviour.shared? - @behaviour_superclass = klass - derive_execution_context_class_from_behaviour_superclass - end - - # You can pass this one or many modules. Each module will subsequently - # be included in the each object in which an example is run. Use this - # to provide global helper methods to your examples. - # - # == Example - # - # module HelperMethods - # def helper_method - # ... - # end - # end - # - # describe Thing do - # include HelperMethods - # it "should do stuff" do - # helper_method - # end - # end - def include(*mods) - mods.each do |mod| - included_modules << mod - mod.send :included, self - end - end - - # Use this to pull in examples from shared behaviours. - # See Spec::Runner for information about shared behaviours. - def it_should_behave_like(behaviour_description) - behaviour = @behaviour.class.find_shared_behaviour(behaviour_description) - if behaviour.nil? - raise RuntimeError.new("Shared Behaviour '#{behaviour_description}' can not be found") - end - behaviour.copy_to(self) - end - - def copy_to(eval_module) # :nodoc: - examples.each { |e| eval_module.examples << e; } - before_each_parts.each { |p| eval_module.before_each_parts << p } - after_each_parts.each { |p| eval_module.after_each_parts << p } - before_all_parts.each { |p| eval_module.before_all_parts << p } - after_all_parts.each { |p| eval_module.after_all_parts << p } - included_modules.each { |m| eval_module.included_modules << m } - eval_module.included_modules << self - 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 ||= {:exist => :exist?, :an_instance_of => :is_a?} - end - - def define_predicate_matchers(hash=nil) # :nodoc: - if hash.nil? - define_predicate_matchers(predicate_matchers) - define_predicate_matchers(Spec::Runner.configuration.predicate_matchers) - else - hash.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 - end - - # Creates an instance of Spec::DSL::Example and adds - # it to a collection of examples of the current behaviour. - def it(description=:__generate_description, opts={}, &block) - examples << Example.new(description, opts, &block) - end - - # Alias for it. - def specify(description=:__generate_description, opts={}, &block) - it(description, opts, &block) - end - - def methods # :nodoc: - my_methods = super - my_methods |= behaviour_superclass.methods - my_methods - end - - protected - - def method_missing(method_name, *args) - if behaviour_superclass.respond_to?(method_name) - return execution_context_class.send(method_name, *args) - end - super - end - - def before_each_proc(behaviour_type, &error_handler) - parts = [] - parts.push(*Behaviour.before_each_parts(nil)) - parts.push(*Behaviour.before_each_parts(behaviour_type)) unless behaviour_type.nil? - parts.push(*before_each_parts(nil)) - parts.push(*before_each_parts(behaviour_type)) unless behaviour_type.nil? - CompositeProcBuilder.new(parts).proc(&error_handler) - end - - def before_all_proc(behaviour_type, &error_handler) - parts = [] - parts.push(*Behaviour.before_all_parts(nil)) - parts.push(*Behaviour.before_all_parts(behaviour_type)) unless behaviour_type.nil? - parts.push(*before_all_parts(nil)) - parts.push(*before_all_parts(behaviour_type)) unless behaviour_type.nil? - CompositeProcBuilder.new(parts).proc(&error_handler) - end - - def after_all_proc(behaviour_type) - parts = [] - parts.push(*after_all_parts(behaviour_type)) unless behaviour_type.nil? - parts.push(*after_all_parts(nil)) - parts.push(*Behaviour.after_all_parts(behaviour_type)) unless behaviour_type.nil? - parts.push(*Behaviour.after_all_parts(nil)) - CompositeProcBuilder.new(parts).proc - end - - def after_each_proc(behaviour_type) - parts = [] - parts.push(*after_each_parts(behaviour_type)) unless behaviour_type.nil? - parts.push(*after_each_parts(nil)) - parts.push(*Behaviour.after_each_parts(behaviour_type)) unless behaviour_type.nil? - parts.push(*Behaviour.after_each_parts(nil)) - CompositeProcBuilder.new(parts).proc - end - - private - - def execution_context_class - @execution_context_class ||= derive_execution_context_class_from_behaviour_superclass - end - - def derive_execution_context_class_from_behaviour_superclass - @execution_context_class = Class.new(behaviour_superclass) - behaviour_superclass.spec_inherited(self) if behaviour_superclass.respond_to?(:spec_inherited) - @execution_context_class - end - - def behaviour_superclass - @behaviour_superclass ||= Object - end - - protected - def included_modules - @included_modules ||= [::Spec::Matchers] - end - - def examples - @examples ||= [] - end - end - - module InstanceMethods - def initialize(*args, &block) #:nodoc: - # TODO - inheriting from TestUnit::TestCase fails without this - # - let's figure out why and move this somewhere else - end - - def violated(message="") - raise Spec::Expectations::ExpectationNotMetError.new(message) - end - - def inspect - "[RSpec example]" - end - - def pending(message) - if block_given? - begin - yield - rescue Exception => e - raise Spec::DSL::ExamplePendingError.new(message) - end - raise Spec::DSL::PendingFixedError.new("Expected pending '#{message}' to fail. No Error was raised.") - else - raise Spec::DSL::ExamplePendingError.new(message) - end - end - end - end - end -end diff --git a/spec/lib/spec/dsl/behaviour_factory.rb b/spec/lib/spec/dsl/behaviour_factory.rb deleted file mode 100755 index 44b60c641..000000000 --- a/spec/lib/spec/dsl/behaviour_factory.rb +++ /dev/null @@ -1,42 +0,0 @@ -module Spec - module DSL - class BehaviourFactory - - class << self - - BEHAVIOUR_CLASSES = {:default => Spec::DSL::Behaviour} - - # Registers a behaviour class +klass+ with the symbol - # +behaviour_type+. For example: - # - # Spec::DSL::BehaviourFactory.add_behaviour_class(:farm, Spec::Farm::DSL::FarmBehaviour) - # - # This will cause Kernel#describe from a file living in - # <tt>spec/farm</tt> to create behaviour instances of type - # Spec::Farm::DSL::FarmBehaviour. - def add_behaviour_class(behaviour_type, klass) - BEHAVIOUR_CLASSES[behaviour_type] = klass - end - - def remove_behaviour_class(behaviour_type) - BEHAVIOUR_CLASSES.delete(behaviour_type) - end - - def create(*args, &block) - opts = Hash === args.last ? args.last : {} - if opts[:shared] - behaviour_type = :default - elsif opts[:behaviour_type] - behaviour_type = opts[:behaviour_type] - elsif opts[:spec_path] =~ /spec(\\|\/)(#{BEHAVIOUR_CLASSES.keys.join('|')})/ - behaviour_type = $2.to_sym - else - behaviour_type = :default - end - return BEHAVIOUR_CLASSES[behaviour_type].new(*args, &block) - end - - end - end - end -end diff --git a/spec/lib/spec/dsl/composite_proc_builder.rb b/spec/lib/spec/dsl/composite_proc_builder.rb deleted file mode 100644 index 373f44953..000000000 --- a/spec/lib/spec/dsl/composite_proc_builder.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Spec - module DSL - class CompositeProcBuilder < Array - def initialize(callbacks=[]) - push(*callbacks) - end - - def proc(&error_handler) - parts = self - errors = [] - Proc.new do - result = parts.collect do |part| - begin - if part.is_a?(UnboundMethod) - part.bind(self).call - else - instance_eval(&part) - end - rescue Exception => e - if error_handler - error_handler.call(e) - else - errors << e - end - end - end - raise errors.first unless errors.empty? - result - end - end - end - end -end diff --git a/spec/lib/spec/dsl/configuration.rb b/spec/lib/spec/dsl/configuration.rb deleted file mode 100755 index 709574ded..000000000 --- a/spec/lib/spec/dsl/configuration.rb +++ /dev/null @@ -1,135 +0,0 @@ -module Spec - module DSL - 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 - # setup_mocks_for_rspec, verify_mocks_for_rspec and 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 - - # Declares modules to be included in all behaviours (<tt>describe</tt> blocks). - # - # config.include(My::Bottle, My::Cup) - # - # If you want to restrict the inclusion to a subset of all the behaviours then - # specify this in a Hash as the last argument: - # - # config.include(My::Pony, My::Horse, :behaviour_type => :farm) - # - # Only behaviours that have that type will get the modules included: - # - # describe "Downtown", :behaviour_type => :city do - # # Will *not* get My::Pony and My::Horse included - # end - # - # describe "Old Mac Donald", :behaviour_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_behaviour_type = options[:behaviour_type] - required_behaviour_type = required_behaviour_type.to_sym unless required_behaviour_type.nil? - @modules ||= {} - @modules[required_behaviour_type] ||= [] - @modules[required_behaviour_type] += modules - end - - def modules_for(required_behaviour_type) #:nodoc: - @modules ||= {} - modules = @modules[nil] || [] # general ones - modules << @modules[required_behaviour_type.to_sym] unless required_behaviour_type.nil? - modules.uniq.compact - end - - # This is just for cleanup in RSpec's own examples - def exclude(*modules) #:nodoc: - @modules.each do |behaviour_type, mods| - modules.each{|m| mods.delete(m)} - 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.should_swim? returns true - # - def predicate_matchers - @predicate_matchers ||= {} - end - - # Prepends a global <tt>before</tt> block to all behaviours. - # See #append_before for filtering semantics. - def prepend_before(*args, &proc) - Behaviour.prepend_before(*args, &proc) - end - # Appends a global <tt>before</tt> block to all behaviours. - # - # If you want to restrict the block to a subset of all the behaviours then - # specify this in a Hash as the last argument: - # - # config.prepend_before(:all, :behaviour_type => :farm) - # - # or - # - # config.prepend_before(:behaviour_type => :farm) - # - def append_before(*args, &proc) - Behaviour.append_before(*args, &proc) - end - alias_method :before, :append_before - - # Prepends a global <tt>after</tt> block to all behaviours. - # See #append_before for filtering semantics. - def prepend_after(*args, &proc) - Behaviour.prepend_after(*args, &proc) - end - alias_method :after, :prepend_after - # Appends a global <tt>after</tt> block to all behaviours. - # See #append_before for filtering semantics. - def append_after(*args, &proc) - Behaviour.append_after(*args, &proc) - end - - private - - def mock_framework_path(framework_name) - File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "plugins", "mock_frameworks", framework_name)) - end - - end - end -end diff --git a/spec/lib/spec/dsl/description.rb b/spec/lib/spec/dsl/description.rb deleted file mode 100755 index fe8c9b0c9..000000000 --- a/spec/lib/spec/dsl/description.rb +++ /dev/null @@ -1,76 +0,0 @@ -module Spec - module DSL - class Description - module ClassMethods - def generate_description(*args) - description = args.shift.to_s - unless args.empty? - suffix = args.shift.to_s - description << " " unless suffix =~ /^\s|\.|#/ - description << suffix - end - description - end - end - extend ClassMethods - - attr_reader :description, :described_type - - def initialize(*args) - args, @options = args_and_options(*args) - init_behaviour_type(@options) - init_spec_path(@options) - init_described_type(args) - init_description(*args) - end - - def [](key) - @options[key] - end - - def []=(key, value) - @options[key] = value - end - - def to_s; @description; end - - def ==(value) - case value - when Description - @description == value.description - else - @description == value - end - end - - private - def init_behaviour_type(options) - # NOTE - BE CAREFUL IF CHANGING THIS NEXT LINE: - # this line is as it is to satisfy JRuby - the original version - # read, simply: "if options[:behaviour_class]", which passed against ruby, but failed against jruby - if options[:behaviour_class] && options[:behaviour_class].ancestors.include?(Behaviour) - options[:behaviour_type] = parse_behaviour_type(@options[:behaviour_class]) - end - end - - def init_spec_path(options) - if options.has_key?(:spec_path) - options[:spec_path] = File.expand_path(@options[:spec_path]) - end - end - - def init_description(*args) - @description = self.class.generate_description(*args) - end - - def init_described_type(args) - @described_type = args.first unless args.first.is_a?(String) - end - - def parse_behaviour_type(behaviour_class) - behaviour_class.to_s.split("::").reverse[0].gsub!('Behaviour', '').downcase.to_sym - end - - end - end -end diff --git a/spec/lib/spec/dsl/errors.rb b/spec/lib/spec/dsl/errors.rb deleted file mode 100644 index ba7046a89..000000000 --- a/spec/lib/spec/dsl/errors.rb +++ /dev/null @@ -1,9 +0,0 @@ -module Spec - module DSL - class ExamplePendingError < StandardError - end - - class PendingFixedError < StandardError - end - end -end diff --git a/spec/lib/spec/dsl/example.rb b/spec/lib/spec/dsl/example.rb deleted file mode 100644 index d04073f7e..000000000 --- a/spec/lib/spec/dsl/example.rb +++ /dev/null @@ -1,135 +0,0 @@ -require 'timeout' - -module Spec - module DSL - class Example - # The global sequence number of this example - attr_accessor :number - - def initialize(description, options={}, &example_block) - @from = caller(0)[3] - @options = options - @example_block = example_block - @description = description - @description_generated_proc = lambda { |desc| @generated_description = desc } - end - - def run(reporter, before_each_block, after_each_block, dry_run, execution_context, timeout=nil) - @dry_run = dry_run - reporter.example_started(self) - return reporter.example_finished(self) if dry_run - - errors = [] - location = nil - Timeout.timeout(timeout) do - before_each_ok = before_example(execution_context, errors, &before_each_block) - example_ok = run_example(execution_context, errors) if before_each_ok - after_each_ok = after_example(execution_context, errors, &after_each_block) - location = failure_location(before_each_ok, example_ok, after_each_ok) - end - - ExampleShouldRaiseHandler.new(@from, @options).handle(errors) - reporter.example_finished(self, errors.first, location, @example_block.nil?) if reporter - end - - def matches?(matcher, specified_examples) - matcher.example_desc = description - matcher.matches?(specified_examples) - end - - def description - @description == :__generate_description ? generated_description : @description - end - - def to_s - description - end - - private - - def generated_description - return @generated_description if @generated_description - if @dry_run - "NO NAME (Because of --dry-run)" - else - if @failed - "NO NAME (Because of Error raised in matcher)" - else - "NO NAME (Because there were no expectations)" - end - end - end - - def before_example(execution_context, errors, &behaviour_before_block) - setup_mocks(execution_context) - Spec::Matchers.description_generated(@description_generated_proc) - - builder = CompositeProcBuilder.new - before_proc = builder.proc(&append_errors(errors)) - execution_context.instance_eval(&before_proc) - - execution_context.instance_eval(&behaviour_before_block) if behaviour_before_block - return errors.empty? - rescue Exception => e - @failed = true - errors << e - return false - end - - def run_example(execution_context, errors) - begin - execution_context.instance_eval(&@example_block) if @example_block - return true - rescue Exception => e - @failed = true - errors << e - return false - end - end - - def after_example(execution_context, errors, &behaviour_after_each) - execution_context.instance_eval(&behaviour_after_each) if behaviour_after_each - - begin - verify_mocks(execution_context) - ensure - teardown_mocks(execution_context) - end - - Spec::Matchers.unregister_description_generated(@description_generated_proc) - - builder = CompositeProcBuilder.new - after_proc = builder.proc(&append_errors(errors)) - execution_context.instance_eval(&after_proc) - - return errors.empty? - rescue Exception => e - @failed = true - errors << e - return false - end - - def setup_mocks(execution_context) - execution_context.setup_mocks_for_rspec if execution_context.respond_to?(:setup_mocks_for_rspec) - end - - def verify_mocks(execution_context) - execution_context.verify_mocks_for_rspec if execution_context.respond_to?(:verify_mocks_for_rspec) - end - - def teardown_mocks(execution_context) - execution_context.teardown_mocks_for_rspec if execution_context.respond_to?(:teardown_mocks_for_rspec) - end - - def append_errors(errors) - proc {|error| errors << error} - end - - def failure_location(before_each_ok, example_ok, after_each_ok) - return 'before(:each)' unless before_each_ok - return description unless example_ok - return 'after(:each)' unless after_each_ok - end - end - end -end diff --git a/spec/lib/spec/dsl/example_matcher.rb b/spec/lib/spec/dsl/example_matcher.rb deleted file mode 100755 index 18cc47409..000000000 --- a/spec/lib/spec/dsl/example_matcher.rb +++ /dev/null @@ -1,40 +0,0 @@ -module Spec - module DSL - class ExampleMatcher - - attr_writer :example_desc - def initialize(behaviour_desc, example_desc=nil) - @behaviour_desc = behaviour_desc - @example_desc = example_desc - 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 - - private - def matches_literal_example?(specified_example) - specified_example =~ /(^#{context_regexp} #{example_regexp}$|^#{context_regexp}$|^#{example_regexp}$)/ - end - - def matches_example_not_considering_modules?(specified_example) - specified_example =~ /(^#{context_regexp_not_considering_modules} #{example_regexp}$|^#{context_regexp_not_considering_modules}$|^#{example_regexp}$)/ - end - - def context_regexp - Regexp.escape(@behaviour_desc) - end - - def context_regexp_not_considering_modules - Regexp.escape(@behaviour_desc.split('::').last) - end - - def example_regexp - Regexp.escape(@example_desc) - end - end - end -end diff --git a/spec/lib/spec/dsl/example_should_raise_handler.rb b/spec/lib/spec/dsl/example_should_raise_handler.rb deleted file mode 100644 index 942327317..000000000 --- a/spec/lib/spec/dsl/example_should_raise_handler.rb +++ /dev/null @@ -1,74 +0,0 @@ -module Spec - module DSL - class ExampleShouldRaiseHandler - def initialize(file_and_line_number, opts) - @file_and_line_number = file_and_line_number - @options = opts - @expected_error_class = determine_error_class(opts) - @expected_error_message = determine_error_message(opts) - end - - def determine_error_class(opts) - if candidate = opts[:should_raise] - if candidate.is_a?(Class) - return candidate - elsif candidate.is_a?(Array) - return candidate[0] - else - return Exception - end - end - end - - def determine_error_message(opts) - if candidate = opts[:should_raise] - if candidate.is_a?(Array) - return candidate[1] - end - end - return nil - end - - def build_message(exception=nil) - if @expected_error_message.nil? - message = "example block expected #{@expected_error_class.to_s}" - else - message = "example block expected #{@expected_error_class.new(@expected_error_message.to_s).inspect}" - end - message << " but raised #{exception.inspect}" if exception - message << " but nothing was raised" unless exception - message << "\n" - message << @file_and_line_number - end - - def error_matches?(error) - return false unless error.kind_of?(@expected_error_class) - unless @expected_error_message.nil? - if @expected_error_message.is_a?(Regexp) - return false unless error.message =~ @expected_error_message - else - return false unless error.message == @expected_error_message - end - end - return true - end - - def handle(errors) - if @expected_error_class - if errors.empty? - errors << Spec::Expectations::ExpectationNotMetError.new(build_message) - else - error_to_remove = errors.detect do |error| - error_matches?(error) - end - if error_to_remove.nil? - errors.insert(0,Spec::Expectations::ExpectationNotMetError.new(build_message(errors[0]))) - else - errors.delete(error_to_remove) - end - end - end - end - end - end -end diff --git a/spec/lib/spec/expectations.rb b/spec/lib/spec/expectations.rb deleted file mode 100644 index 65ea47425..000000000 --- a/spec/lib/spec/expectations.rb +++ /dev/null @@ -1,56 +0,0 @@ -require 'spec/matchers' -require 'spec/expectations/errors' -require 'spec/expectations/extensions' -require 'spec/expectations/handler' - -module Spec - - # Spec::Expectations lets you set expectations on your objects. - # - # result.should == 37 - # team.should have(11).players_on_the_field - # - # == How Expectations work. - # - # Spec::Expectations adds two methods to Object: - # - # should(matcher=nil) - # should_not(matcher=nil) - # - # Both methods take an optional Expression Matcher (See Spec::Matchers). - # - # When +should+ receives an Expression Matcher, it calls <tt>matches?(self)</tt>. If - # it returns +true+, the spec passes and execution continues. If it returns - # +false+, then the spec fails with the message returned by <tt>matcher.failure_message</tt>. - # - # Similarly, when +should_not+ receives a matcher, it calls <tt>matches?(self)</tt>. If - # it returns +false+, the spec passes and execution continues. If it returns - # +true+, then the spec fails with the message returned by <tt>matcher.negative_failure_message</tt>. - # - # RSpec ships with a standard set of useful matchers, and writing your own - # matchers is quite simple. See Spec::Matchers for details. - module Expectations - class << self - attr_accessor :differ - - # raises a Spec::Expectations::ExpectationNotMetError with message - # - # When a differ has been assigned and fail_with is passed - # <code>expected</code> and <code>target</code>, passes them - # to the differ to append a diff message to the failure message. - def fail_with(message, expected=nil, target=nil) # :nodoc: - if Array === message && message.length == 3 - message, expected, target = message[0], message[1], message[2] - end - unless (differ.nil? || expected.nil? || target.nil?) - if expected.is_a?(String) - message << "\nDiff:" << self.differ.diff_as_string(target.to_s, expected) - elsif !target.is_a?(Proc) - message << "\nDiff:" << self.differ.diff_as_object(target, expected) - end - end - Kernel::raise(Spec::Expectations::ExpectationNotMetError.new(message)) - end - end - end -end diff --git a/spec/lib/spec/expectations/differs/default.rb b/spec/lib/spec/expectations/differs/default.rb deleted file mode 100644 index 87e59b3a6..000000000 --- a/spec/lib/spec/expectations/differs/default.rb +++ /dev/null @@ -1,61 +0,0 @@ -begin - require 'rubygems' - require 'diff/lcs' #necessary due to loading bug on some machines - not sure why - DaC - require 'diff/lcs/hunk' -rescue LoadError ; raise "You must gem install diff-lcs to use diffing" ; end - -require 'pp' - -module Spec - module Expectations - module Differs - - # TODO add some rdoc - class Default - def initialize(format=:unified,context_lines=nil,colour=nil) - - context_lines ||= 3 - colour ||= false - - @format,@context_lines,@colour = format,context_lines,colour - end - - # This is snagged from diff/lcs/ldiff.rb (which is a commandline tool) - def diff_as_string(data_old, data_new) - data_old = data_old.split(/\n/).map! { |e| e.chomp } - data_new = data_new.split(/\n/).map! { |e| e.chomp } - output = "" - diffs = Diff::LCS.diff(data_old, data_new) - return output if diffs.empty? - oldhunk = hunk = nil - file_length_difference = 0 - diffs.each do |piece| - begin - hunk = Diff::LCS::Hunk.new(data_old, data_new, piece, @context_lines, - file_length_difference) - file_length_difference = hunk.file_length_difference - next unless oldhunk - # Hunks may overlap, which is why we need to be careful when our - # diff includes lines of context. Otherwise, we might print - # redundant lines. - if (@context_lines > 0) and hunk.overlaps?(oldhunk) - hunk.unshift(oldhunk) - else - output << oldhunk.diff(@format) - end - ensure - oldhunk = hunk - output << "\n" - end - end - #Handle the last remaining hunk - output << oldhunk.diff(@format) << "\n" - end - - def diff_as_object(target,expected) - diff_as_string(PP.pp(target,""), PP.pp(expected,"")) - end - end - end - end -end diff --git a/spec/lib/spec/expectations/errors.rb b/spec/lib/spec/expectations/errors.rb deleted file mode 100644 index 03e81a064..000000000 --- a/spec/lib/spec/expectations/errors.rb +++ /dev/null @@ -1,6 +0,0 @@ -module Spec - module Expectations - class ExpectationNotMetError < StandardError - end - end -end diff --git a/spec/lib/spec/expectations/extensions.rb b/spec/lib/spec/expectations/extensions.rb deleted file mode 100644 index 60c9b9e7d..000000000 --- a/spec/lib/spec/expectations/extensions.rb +++ /dev/null @@ -1,2 +0,0 @@ -require 'spec/expectations/extensions/object' -require 'spec/expectations/extensions/string_and_symbol' diff --git a/spec/lib/spec/expectations/extensions/object.rb b/spec/lib/spec/expectations/extensions/object.rb deleted file mode 100644 index f59af722e..000000000 --- a/spec/lib/spec/expectations/extensions/object.rb +++ /dev/null @@ -1,66 +0,0 @@ -module Spec - module Expectations - # rspec adds #should and #should_not to every Object (and, - # implicitly, every Class). - module ObjectExpectations - - # :call-seq: - # should(matcher) - # should == expected - # should === expected - # should =~ expected - # - # receiver.should(matcher) - # => Passes if matcher.matches?(receiver) - # - # receiver.should == expected #any value - # => Passes if (receiver == expected) - # - # receiver.should === expected #any value - # => Passes if (receiver === expected) - # - # receiver.should =~ regexp - # => Passes if (receiver =~ regexp) - # - # See Spec::Matchers for more information about matchers - # - # == Warning - # - # NOTE that this does NOT support receiver.should != expected. - # Instead, use receiver.should_not == expected - def should(matcher=nil, &block) - return ExpectationMatcherHandler.handle_matcher(self, matcher, &block) if matcher - Spec::Matchers::PositiveOperatorMatcher.new(self) - end - - # :call-seq: - # should_not(matcher) - # should_not == expected - # should_not === expected - # should_not =~ expected - # - # receiver.should_not(matcher) - # => Passes unless matcher.matches?(receiver) - # - # receiver.should_not == expected - # => Passes unless (receiver == expected) - # - # receiver.should_not === expected - # => Passes unless (receiver === expected) - # - # receiver.should_not =~ regexp - # => Passes unless (receiver =~ regexp) - # - # See Spec::Matchers for more information about matchers - def should_not(matcher=nil, &block) - return NegativeExpectationMatcherHandler.handle_matcher(self, matcher, &block) if matcher - Spec::Matchers::NegativeOperatorMatcher.new(self) - end - - end - end -end - -class Object - include Spec::Expectations::ObjectExpectations -end diff --git a/spec/lib/spec/expectations/extensions/string_and_symbol.rb b/spec/lib/spec/expectations/extensions/string_and_symbol.rb deleted file mode 100644 index 29cfbddfa..000000000 --- a/spec/lib/spec/expectations/extensions/string_and_symbol.rb +++ /dev/null @@ -1,17 +0,0 @@ -module Spec - module Expectations - module StringHelpers - def starts_with?(prefix) - to_s[0..(prefix.to_s.length - 1)] == prefix.to_s - end - end - end -end - -class String - include Spec::Expectations::StringHelpers -end - -class Symbol - include Spec::Expectations::StringHelpers -end diff --git a/spec/lib/spec/expectations/handler.rb b/spec/lib/spec/expectations/handler.rb deleted file mode 100644 index 4caa321e4..000000000 --- a/spec/lib/spec/expectations/handler.rb +++ /dev/null @@ -1,43 +0,0 @@ -module Spec - module Expectations - - module MatcherHandlerHelper - def describe(matcher) - matcher.respond_to?(:description) ? matcher.description : "[#{matcher.class.name} does not provide a description]" - end - end - - class ExpectationMatcherHandler - class << self - include MatcherHandlerHelper - def handle_matcher(actual, matcher, &block) - match = matcher.matches?(actual, &block) - ::Spec::Matchers.generated_description = "should #{describe(matcher)}" - Spec::Expectations.fail_with(matcher.failure_message) unless match - end - end - end - - class NegativeExpectationMatcherHandler - class << self - include MatcherHandlerHelper - def handle_matcher(actual, matcher, &block) - unless matcher.respond_to?(:negative_failure_message) - Spec::Expectations.fail_with( -<<-EOF -Matcher does not support should_not. -See Spec::Matchers for more information -about matchers. -EOF -) - end - match = matcher.matches?(actual, &block) - ::Spec::Matchers.generated_description = "should not #{describe(matcher)}" - Spec::Expectations.fail_with(matcher.negative_failure_message) if match - end - end - end - - end -end - diff --git a/spec/lib/spec/extensions.rb b/spec/lib/spec/extensions.rb deleted file mode 100755 index 824f03bfb..000000000 --- a/spec/lib/spec/extensions.rb +++ /dev/null @@ -1 +0,0 @@ -require 'spec/extensions/object' diff --git a/spec/lib/spec/extensions/object.rb b/spec/lib/spec/extensions/object.rb deleted file mode 100755 index 6218aa770..000000000 --- a/spec/lib/spec/extensions/object.rb +++ /dev/null @@ -1,6 +0,0 @@ -class Object - def args_and_options(*args) - options = Hash === args.last ? args.pop : {} - return args, options - end -end diff --git a/spec/lib/spec/matchers.rb b/spec/lib/spec/matchers.rb deleted file mode 100644 index fd208d628..000000000 --- a/spec/lib/spec/matchers.rb +++ /dev/null @@ -1,166 +0,0 @@ -require 'spec/matchers/be' -require 'spec/matchers/be_close' -require 'spec/matchers/change' -require 'spec/matchers/eql' -require 'spec/matchers/equal' -require 'spec/matchers/has' -require 'spec/matchers/have' -require 'spec/matchers/include' -require 'spec/matchers/match' -require 'spec/matchers/raise_error' -require 'spec/matchers/respond_to' -require 'spec/matchers/satisfy' -require 'spec/matchers/throw_symbol' -require 'spec/matchers/operator_matcher' - -module Spec - - # RSpec ships with a number of useful Expression Matchers. An Expression Matcher - # is any object that responds to the following methods: - # - # matches?(actual) - # failure_message - # negative_failure_message #optional - # description #optional - # - # See Spec::Expectations to learn how to use these as Expectation Matchers. - # See Spec::Mocks to learn how to use them as Mock Argument Constraints. - # - # == Predicates - # - # In addition to those Expression Matchers that are defined explicitly, RSpec will - # create custom Matchers on the fly for any arbitrary predicate, giving your specs - # a much more natural language feel. - # - # A Ruby predicate is a method that ends with a "?" and returns true or false. - # Common examples are +empty?+, +nil?+, and +instance_of?+. - # - # All you need to do is write +should be_+ followed by the predicate without - # the question mark, and RSpec will figure it out from there. For example: - # - # [].should be_empty => [].empty? #passes - # [].should_not be_empty => [].empty? #fails - # - # In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_" - # and "be_an_", making your specs read much more naturally: - # - # "a string".should be_an_instance_of(String) =>"a string".instance_of?(String) #passes - # - # 3.should be_a_kind_of(Fixnum) => 3.kind_of?(Numeric) #passes - # 3.should be_a_kind_of(Numeric) => 3.kind_of?(Numeric) #passes - # 3.should be_an_instance_of(Fixnum) => 3.instance_of?(Fixnum) #passes - # 3.should_not be_instance_of(Numeric) => 3.instance_of?(Numeric) #fails - # - # RSpec will also create custom matchers for predicates like +has_key?+. To - # use this feature, just state that the object should have_key(:key) and RSpec will - # call has_key?(:key) on the target. For example: - # - # {:a => "A"}.should have_key(:a) => {:a => "A"}.has_key?(:a) #passes - # {:a => "A"}.should have_key(:b) => {:a => "A"}.has_key?(:b) #fails - # - # You can use this feature to invoke any predicate that begins with "has_", whether it is - # part of the Ruby libraries (like +Hash#has_key?+) or a method you wrote on your own class. - # - # == Custom Expectation Matchers - # - # When you find that none of the stock Expectation Matchers provide a natural - # feeling expectation, you can very easily write your own. - # - # For example, imagine that you are writing a game in which players can - # be in various zones on a virtual board. To specify that bob should - # be in zone 4, you could say: - # - # bob.current_zone.should eql(Zone.new("4")) - # - # But you might find it more expressive to say: - # - # bob.should be_in_zone("4") - # - # and/or - # - # bob.should_not be_in_zone("3") - # - # To do this, you would need to write a class like this: - # - # class BeInZone - # def initialize(expected) - # @expected = expected - # end - # def matches?(target) - # @target = target - # @target.current_zone.eql?(Zone.new(@expected)) - # end - # def failure_message - # "expected #{@target.inspect} to be in Zone #{@expected}" - # end - # def negative_failure_message - # "expected #{@target.inspect} not to be in Zone #{@expected}" - # end - # end - # - # ... and a method like this: - # - # def be_in_zone(expected) - # BeInZone.new(expected) - # end - # - # And then expose the method to your specs. This is normally done - # by including the method and the class in a module, which is then - # included in your spec: - # - # module CustomGameMatchers - # class BeInZone - # ... - # end - # - # def be_in_zone(expected) - # ... - # end - # end - # - # describe "Player behaviour" do - # include CustomGameMatchers - # ... - # end - # - # or you can include in globally in a spec_helper.rb file <tt>require</tt>d - # from your spec file(s): - # - # Spec::Runner.configure do |config| - # config.include(CustomGameMatchers) - # end - # - module Matchers - module ModuleMethods - def description_generated(callback) - description_generated_callbacks << callback - end - - def unregister_description_generated(callback) - description_generated_callbacks.delete(callback) - end - - def generated_description=(name) - description_generated_callbacks.each do |callback| - callback.call(name) - end - end - - private - def description_generated_callbacks - @description_generated_callbacks ||= [] - end - end - extend ModuleMethods - - def method_missing(sym, *args, &block) # :nodoc: - return Matchers::Be.new(sym, *args) if sym.starts_with?("be_") - return Matchers::Has.new(sym, *args) if sym.starts_with?("have_") - super - end - - class MatcherError < StandardError - end - - end -end diff --git a/spec/lib/spec/matchers/be.rb b/spec/lib/spec/matchers/be.rb deleted file mode 100644 index 0eb1629a6..000000000 --- a/spec/lib/spec/matchers/be.rb +++ /dev/null @@ -1,206 +0,0 @@ -module Spec - module Matchers - - class Be #:nodoc: - def initialize(*args) - @expected = parse_expected(args.shift) - @args = args - @comparison = "" - end - - def matches?(actual) - @actual = actual - return true if match_or_compare unless handling_predicate? - if handling_predicate? - begin - return @result = actual.__send__(predicate, *@args) - rescue => predicate_error - # This clause should be empty, but rcov will not report it as covered - # unless something (anything) is executed within the clause - rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0" - end - - # This supports should_exist > target.exists? in the old world. - # We should consider deprecating that ability as in the new world - # you can't write "should exist" unless you have your own custom matcher. - begin - return @result = actual.__send__(present_tense_predicate, *@args) - rescue - raise predicate_error - end - end - return false - end - - def failure_message - return "expected #{@comparison}#{expected}, got #{@actual.inspect}" unless handling_predicate? - return "expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}" - end - - def negative_failure_message - return "expected not #{expected}, got #{@actual.inspect}" unless handling_predicate? - return "expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}" - end - - def expected - return true if @expected == :true - return false if @expected == :false - return "nil" if @expected == :nil - return @expected.inspect - end - - def match_or_compare - return @actual == true if @expected == :true - return @actual == false if @expected == :false - return @actual.nil? if @expected == :nil - return @actual < @expected if @less_than - return @actual <= @expected if @less_than_or_equal - return @actual >= @expected if @greater_than_or_equal - return @actual > @expected if @greater_than - return @actual == @expected if @double_equal - return @actual === @expected if @triple_equal - return @actual.equal?(@expected) - end - - def ==(expected) - @double_equal = true - @comparison = "== " - @expected = expected - self - end - - def ===(expected) - @triple_equal = true - @comparison = "=== " - @expected = expected - self - end - - def <(expected) - @less_than = true - @comparison = "< " - @expected = expected - self - end - - def <=(expected) - @less_than_or_equal = true - @comparison = "<= " - @expected = expected - self - end - - def >=(expected) - @greater_than_or_equal = true - @comparison = ">= " - @expected = expected - self - end - - def >(expected) - @greater_than = true - @comparison = "> " - @expected = expected - self - end - - def description - "#{prefix_to_sentence}#{comparison}#{expected_to_sentence}#{args_to_sentence}" - end - - private - def parse_expected(expected) - if Symbol === expected - @handling_predicate = true - ["be_an_","be_a_","be_"].each do |@prefix| - return "#{expected.to_s.sub(@prefix,"")}".to_sym if expected.starts_with?(@prefix) - end - end - @prefix = "be " - return expected - end - - def handling_predicate? - return false if [:true, :false, :nil].include?(@expected) - return @handling_predicate - end - - def predicate - "#{@expected.to_s}?".to_sym - end - - def present_tense_predicate - "#{@expected.to_s}s?".to_sym - end - - def args_to_s - return "" if @args.empty? - inspected_args = @args.collect{|a| a.inspect} - return "(#{inspected_args.join(', ')})" - end - - def comparison - @comparison - end - - def expected_to_sentence - split_words(@expected) - end - - def prefix_to_sentence - split_words(@prefix) - end - - def split_words(sym) - sym.to_s.gsub(/_/,' ') - end - - def args_to_sentence - case @args.length - when 0 - "" - when 1 - " #{@args[0]}" - else - " #{@args[0...-1].join(', ')} and #{@args[-1]}" - end - end - - end - - # :call-seq: - # should be_true - # should be_false - # should be_nil - # should be_arbitrary_predicate(*args) - # should_not be_nil - # should_not be_arbitrary_predicate(*args) - # - # Given true, false, or nil, will pass if actual is - # true, false or nil (respectively). - # - # Predicates are any Ruby method that ends in a "?" and returns true or false. - # Given be_ followed by arbitrary_predicate (without the "?"), RSpec will match - # convert that into a query against the target object. - # - # The arbitrary_predicate feature will handle any predicate - # prefixed with "be_an_" (e.g. be_an_instance_of), "be_a_" (e.g. be_a_kind_of) - # or "be_" (e.g. be_empty), letting you choose the prefix that best suits the predicate. - # - # == Examples - # - # target.should be_true - # target.should be_false - # target.should be_nil - # target.should_not be_nil - # - # collection.should be_empty #passes if target.empty? - # "this string".should be_an_intance_of(String) - # - # target.should_not be_empty #passes unless target.empty? - # target.should_not be_old_enough(16) #passes unless target.old_enough?(16) - def be(*args) - Matchers::Be.new(*args) - end - end -end diff --git a/spec/lib/spec/matchers/be_close.rb b/spec/lib/spec/matchers/be_close.rb deleted file mode 100644 index 7763eb97e..000000000 --- a/spec/lib/spec/matchers/be_close.rb +++ /dev/null @@ -1,37 +0,0 @@ -module Spec - module Matchers - - class BeClose #:nodoc: - def initialize(expected, delta) - @expected = expected - @delta = delta - end - - def matches?(actual) - @actual = actual - (@actual - @expected).abs < @delta - end - - def failure_message - "expected #{@expected} +/- (< #{@delta}), got #{@actual}" - end - - def description - "be close to #{@expected} (within +- #{@delta})" - end - end - - # :call-seq: - # should be_close(expected, delta) - # should_not be_close(expected, delta) - # - # Passes if actual == expected +/- delta - # - # == Example - # - # result.should be_close(3.0, 0.5) - def be_close(expected, delta) - Matchers::BeClose.new(expected, delta) - end - end -end diff --git a/spec/lib/spec/matchers/change.rb b/spec/lib/spec/matchers/change.rb deleted file mode 100644 index 41a718aca..000000000 --- a/spec/lib/spec/matchers/change.rb +++ /dev/null @@ -1,120 +0,0 @@ -module Spec - module Matchers - - #Based on patch from Wilson Bilkovich - class Change #:nodoc: - def initialize(receiver=nil, message=nil, &block) - @receiver = receiver - @message = message - @block = block - end - - def matches?(target, &block) - if block - raise MatcherError.new(<<-EOF -block passed to should or should_not change must use {} instead of do/end -EOF -) - end - @target = target - execute_change - return false if @from && (@from != @before) - return false if @to && (@to != @after) - return (@before + @amount == @after) if @amount - return @before != @after - end - - def execute_change - @before = @block.nil? ? @receiver.send(@message) : @block.call - @target.call - @after = @block.nil? ? @receiver.send(@message) : @block.call - end - - def failure_message - if @to - "#{result} should have been changed to #{@to.inspect}, but is now #{@after.inspect}" - elsif @from - "#{result} should have initially been #{@from.inspect}, but was #{@before.inspect}" - elsif @amount - "#{result} should have been changed by #{@amount.inspect}, but was changed by #{actual_delta.inspect}" - else - "#{result} should have changed, but is still #{@before.inspect}" - end - end - - def result - @message || "result" - end - - def actual_delta - @after - @before - end - - def negative_failure_message - "#{result} should not have changed, but did change from #{@before.inspect} to #{@after.inspect}" - end - - def by(amount) - @amount = amount - self - end - - def to(to) - @to = to - self - end - - def from (from) - @from = from - self - end - end - - # :call-seq: - # should change(receiver, message, &block) - # should change(receiver, message, &block).by(value) - # should change(receiver, message, &block).from(old).to(new) - # should_not change(receiver, message, &block) - # - # Allows you to specify that a Proc will cause some value to change. - # - # == Examples - # - # lambda { - # team.add_player(player) - # }.should change(roster, :count) - # - # lambda { - # team.add_player(player) - # }.should change(roster, :count).by(1) - # - # string = "string" - # lambda { - # string.reverse - # }.should change { string }.from("string").to("gnirts") - # - # lambda { - # person.happy_birthday - # }.should change(person, :birthday).from(32).to(33) - # - # lambda { - # employee.develop_great_new_social_networking_app - # }.should change(employee, :title).from("Mail Clerk").to("CEO") - # - # Evaluates +receiver.message+ or +block+ before and - # after it evaluates the c object (generated by the lambdas in the examples above). - # - # Then compares the values before and after the +receiver.message+ and - # evaluates the difference compared to the expected difference. - # - # == Warning - # +should_not+ +change+ only supports the form with no subsequent calls to - # +be+, +to+ or +from+. - # - # blocks passed to +should+ +change+ and +should_not+ +change+ - # must use the <tt>{}</tt> form (<tt>do/end</tt> is not supported) - def change(target=nil, message=nil, &block) - Matchers::Change.new(target, message, &block) - end - end -end diff --git a/spec/lib/spec/matchers/eql.rb b/spec/lib/spec/matchers/eql.rb deleted file mode 100644 index 280ca5454..000000000 --- a/spec/lib/spec/matchers/eql.rb +++ /dev/null @@ -1,43 +0,0 @@ -module Spec - module Matchers - - class Eql #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - @actual.eql?(@expected) - end - - def failure_message - return "expected #{@expected.inspect}, got #{@actual.inspect} (using .eql?)", @expected, @actual - end - - def negative_failure_message - return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .eql?)", @expected, @actual - end - - def description - "eql #{@expected.inspect}" - end - end - - # :call-seq: - # should eql(expected) - # should_not eql(expected) - # - # Passes if actual and expected are of equal value, but not necessarily the same object. - # - # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby. - # - # == Examples - # - # 5.should eql(5) - # 5.should_not eql(3) - def eql(expected) - Matchers::Eql.new(expected) - end - end -end diff --git a/spec/lib/spec/matchers/equal.rb b/spec/lib/spec/matchers/equal.rb deleted file mode 100644 index 4bfc74951..000000000 --- a/spec/lib/spec/matchers/equal.rb +++ /dev/null @@ -1,43 +0,0 @@ -module Spec - module Matchers - - class Equal #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - @actual.equal?(@expected) - end - - def failure_message - return "expected #{@expected.inspect}, got #{@actual.inspect} (using .equal?)", @expected, @actual - end - - def negative_failure_message - return "expected #{@actual.inspect} not to equal #{@expected.inspect} (using .equal?)", @expected, @actual - end - - def description - "equal #{@expected.inspect}" - end - end - - # :call-seq: - # should equal(expected) - # should_not equal(expected) - # - # Passes if actual and expected are the same object (object identity). - # - # See http://www.ruby-doc.org/core/classes/Object.html#M001057 for more information about equality in Ruby. - # - # == Examples - # - # 5.should equal(5) #Fixnums are equal - # "5".should_not equal("5") #Strings that look the same are not the same object - def equal(expected) - Matchers::Equal.new(expected) - end - end -end diff --git a/spec/lib/spec/matchers/has.rb b/spec/lib/spec/matchers/has.rb deleted file mode 100644 index cc5a250b8..000000000 --- a/spec/lib/spec/matchers/has.rb +++ /dev/null @@ -1,44 +0,0 @@ -module Spec - module Matchers - - class Has #:nodoc: - def initialize(sym, *args) - @sym = sym - @args = args - end - - def matches?(target) - @target = target - begin - return target.send(predicate, *@args) - rescue => @error - # This clause should be empty, but rcov will not report it as covered - # unless something (anything) is executed within the clause - rcov_error_report = "http://eigenclass.org/hiki.rb?rcov-0.8.0" - end - return false - end - - def failure_message - raise @error if @error - "expected ##{predicate}(#{@args[0].inspect}) to return true, got false" - end - - def negative_failure_message - raise @error if @error - "expected ##{predicate}(#{@args[0].inspect}) to return false, got true" - end - - def description - "have key #{@args[0].inspect}" - end - - private - def predicate - "#{@sym.to_s.sub("have_","has_")}?".to_sym - end - - end - - end -end diff --git a/spec/lib/spec/matchers/have.rb b/spec/lib/spec/matchers/have.rb deleted file mode 100644 index f28b86ad3..000000000 --- a/spec/lib/spec/matchers/have.rb +++ /dev/null @@ -1,142 +0,0 @@ -module Spec - module Matchers - - class Have #:nodoc: - def initialize(expected, relativity=:exactly) - @expected = (expected == :no ? 0 : expected) - @relativity = relativity - end - - def relativities - @relativities ||= { - :exactly => "", - :at_least => "at least ", - :at_most => "at most " - } - end - - def method_missing(sym, *args, &block) - @collection_name = sym - @args = args - @block = block - self - end - - def matches?(collection_owner) - if collection_owner.respond_to?(@collection_name) - collection = collection_owner.send(@collection_name, *@args, &@block) - elsif (collection_owner.respond_to?(:length) || collection_owner.respond_to?(:size)) - collection = collection_owner - else - collection_owner.send(@collection_name, *@args, &@block) - end - @actual = collection.size if collection.respond_to?(:size) - @actual = collection.length if collection.respond_to?(:length) - raise not_a_collection if @actual.nil? - return @actual >= @expected if @relativity == :at_least - return @actual <= @expected if @relativity == :at_most - return @actual == @expected - end - - def not_a_collection - "expected #{@collection_name} to be a collection but it does not respond to #length or #size" - end - - def failure_message - "expected #{relative_expectation} #{@collection_name}, got #{@actual}" - end - - def negative_failure_message - if @relativity == :exactly - return "expected target not to have #{@expected} #{@collection_name}, got #{@actual}" - elsif @relativity == :at_most - return <<-EOF -Isn't life confusing enough? -Instead of having to figure out the meaning of this: - should_not have_at_most(#{@expected}).#{@collection_name} -We recommend that you use this instead: - should have_at_least(#{@expected + 1}).#{@collection_name} -EOF - elsif @relativity == :at_least - return <<-EOF -Isn't life confusing enough? -Instead of having to figure out the meaning of this: - should_not have_at_least(#{@expected}).#{@collection_name} -We recommend that you use this instead: - should have_at_most(#{@expected - 1}).#{@collection_name} -EOF - end - end - - def description - "have #{relative_expectation} #{@collection_name}" - end - - private - - def relative_expectation - "#{relativities[@relativity]}#{@expected}" - end - end - - # :call-seq: - # should have(number).named_collection__or__sugar - # should_not have(number).named_collection__or__sugar - # - # Passes if receiver is a collection with the submitted - # number of items OR if the receiver OWNS a collection - # with the submitted number of items. - # - # If the receiver OWNS the collection, you must use the name - # of the collection. So if a <tt>Team</tt> instance has a - # collection named <tt>#players</tt>, you must use that name - # to set the expectation. - # - # If the receiver IS the collection, you can use any name - # you like for <tt>named_collection</tt>. We'd recommend using - # either "elements", "members", or "items" as these are all - # standard ways of describing the things IN a collection. - # - # This also works for Strings, letting you set an expectation - # about its length - # - # == Examples - # - # # Passes if team.players.size == 11 - # team.should have(11).players - # - # # Passes if [1,2,3].length == 3 - # [1,2,3].should have(3).items #"items" is pure sugar - # - # # Passes if "this string".length == 11 - # "this string".should have(11).characters #"characters" is pure sugar - def have(n) - Matchers::Have.new(n) - end - alias :have_exactly :have - - # :call-seq: - # should have_at_least(number).items - # - # Exactly like have() with >=. - # - # == Warning - # - # +should_not+ +have_at_least+ is not supported - def have_at_least(n) - Matchers::Have.new(n, :at_least) - end - - # :call-seq: - # should have_at_most(number).items - # - # Exactly like have() with <=. - # - # == Warning - # - # +should_not+ +have_at_most+ is not supported - def have_at_most(n) - Matchers::Have.new(n, :at_most) - end - end -end diff --git a/spec/lib/spec/matchers/include.rb b/spec/lib/spec/matchers/include.rb deleted file mode 100644 index 5476f97d8..000000000 --- a/spec/lib/spec/matchers/include.rb +++ /dev/null @@ -1,70 +0,0 @@ -module Spec - module Matchers - - class Include #:nodoc: - - def initialize(*expecteds) - @expecteds = expecteds - end - - def matches?(actual) - @actual = actual - @expecteds.each do |expected| - return false unless actual.include?(expected) - end - true - end - - def failure_message - _message - end - - def negative_failure_message - _message("not ") - end - - def description - "include #{_pretty_print(@expecteds)}" - end - - private - def _message(maybe_not="") - "expected #{@actual.inspect} #{maybe_not}to include #{_pretty_print(@expecteds)}" - end - - def _pretty_print(array) - result = "" - array.each_with_index do |item, index| - if index < (array.length - 2) - result << "#{item.inspect}, " - elsif index < (array.length - 1) - result << "#{item.inspect} and " - else - result << "#{item.inspect}" - end - end - result - end - end - - # :call-seq: - # should include(expected) - # should_not include(expected) - # - # Passes if actual includes expected. This works for - # collections and Strings. You can also pass in multiple args - # and it will only pass if all args are found in collection. - # - # == Examples - # - # [1,2,3].should include(3) - # [1,2,3].should include(2,3) #would pass - # [1,2,3].should include(2,3,4) #would fail - # [1,2,3].should_not include(4) - # "spread".should include("read") - # "spread".should_not include("red") - def include(*expected) - Matchers::Include.new(*expected) - end - end -end diff --git a/spec/lib/spec/matchers/match.rb b/spec/lib/spec/matchers/match.rb deleted file mode 100644 index 61ab52429..000000000 --- a/spec/lib/spec/matchers/match.rb +++ /dev/null @@ -1,41 +0,0 @@ -module Spec - module Matchers - - class Match #:nodoc: - def initialize(expected) - @expected = expected - end - - def matches?(actual) - @actual = actual - return true if actual =~ @expected - return false - end - - def failure_message - return "expected #{@actual.inspect} to match #{@expected.inspect}", @expected, @actual - end - - def negative_failure_message - return "expected #{@actual.inspect} not to match #{@expected.inspect}", @expected, @actual - end - - def description - "match #{@expected.inspect}" - end - end - - # :call-seq: - # should match(regexp) - # should_not match(regexp) - # - # Given a Regexp, passes if actual =~ regexp - # - # == Examples - # - # email.should match(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i) - def match(regexp) - Matchers::Match.new(regexp) - end - end -end diff --git a/spec/lib/spec/matchers/operator_matcher.rb b/spec/lib/spec/matchers/operator_matcher.rb deleted file mode 100755 index 2d47ea85a..000000000 --- a/spec/lib/spec/matchers/operator_matcher.rb +++ /dev/null @@ -1,72 +0,0 @@ -module Spec - module Matchers - class BaseOperatorMatcher - - def initialize(target) - @target = target - end - - def ==(expected) - @expected = expected - __delegate_method_missing_to_target("==", expected) - end - - def ===(expected) - @expected = expected - __delegate_method_missing_to_target("===", expected) - end - - def =~(expected) - @expected = expected - __delegate_method_missing_to_target("=~", expected) - end - - def >(expected) - @expected = expected - __delegate_method_missing_to_target(">", expected) - end - - def >=(expected) - @expected = expected - __delegate_method_missing_to_target(">=", expected) - end - - def <(expected) - @expected = expected - __delegate_method_missing_to_target("<", expected) - end - - def <=(expected) - @expected = expected - __delegate_method_missing_to_target("<=", expected) - end - - def fail_with_message(message) - Spec::Expectations.fail_with(message, @expected, @target) - end - - end - - class PositiveOperatorMatcher < BaseOperatorMatcher #:nodoc: - - def __delegate_method_missing_to_target(operator, expected) - ::Spec::Matchers.generated_description = "should #{operator} #{expected.inspect}" - return if @target.send(operator, expected) - return fail_with_message("expected: #{expected.inspect},\n got: #{@target.inspect} (using #{operator})") if ['==','===', '=~'].include?(operator) - return fail_with_message("expected: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}") - end - - end - - class NegativeOperatorMatcher < BaseOperatorMatcher #:nodoc: - - def __delegate_method_missing_to_target(operator, expected) - ::Spec::Matchers.generated_description = "should not #{operator} #{expected.inspect}" - return unless @target.send(operator, expected) - return fail_with_message("expected not: #{operator} #{expected.inspect},\n got: #{operator.gsub(/./, ' ')} #{@target.inspect}") - end - - end - - end -end diff --git a/spec/lib/spec/matchers/raise_error.rb b/spec/lib/spec/matchers/raise_error.rb deleted file mode 100644 index b45dcf65c..000000000 --- a/spec/lib/spec/matchers/raise_error.rb +++ /dev/null @@ -1,105 +0,0 @@ -module Spec - module Matchers - - class RaiseError #:nodoc: - def initialize(error_or_message=Exception, message=nil) - if String === error_or_message - @expected_error = Exception - @expected_message = error_or_message - else - @expected_error = error_or_message - @expected_message = message - end - end - - def matches?(proc) - @raised_expected_error = false - @raised_other = false - begin - proc.call - rescue @expected_error => @actual_error - if @expected_message.nil? - @raised_expected_error = true - else - case @expected_message - when Regexp - if @expected_message =~ @actual_error.message - @raised_expected_error = true - else - @raised_other = true - end - else - if @expected_message == @actual_error.message - @raised_expected_error = true - else - @raised_other = true - end - end - end - rescue => @actual_error - @raised_other = true - ensure - return @raised_expected_error - end - end - - def failure_message - return "expected #{expected_error}#{actual_error}" if @raised_other || !@raised_expected_error - end - - def negative_failure_message - "expected no #{expected_error}#{actual_error}" - end - - def description - "raise #{expected_error}" - end - - private - def expected_error - case @expected_message - when nil - @expected_error - when Regexp - "#{@expected_error} with message matching #{@expected_message.inspect}" - else - "#{@expected_error} with #{@expected_message.inspect}" - end - end - - def actual_error - @actual_error.nil? ? " but nothing was raised" : ", got #{@actual_error.inspect}" - end - end - - # :call-seq: - # should raise_error() - # should raise_error(NamedError) - # should raise_error(NamedError, String) - # should raise_error(NamedError, Regexp) - # should_not raise_error() - # should_not raise_error(NamedError) - # should_not raise_error(NamedError, String) - # should_not raise_error(NamedError, Regexp) - # - # With no args, matches if any error is raised. - # With a named error, matches only if that specific error is raised. - # With a named error and messsage specified as a String, matches only if both match. - # With a named error and messsage specified as a Regexp, matches only if both match. - # - # == Examples - # - # lambda { do_something_risky }.should raise_error - # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError) - # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, "that was too risky") - # lambda { do_something_risky }.should raise_error(PoorRiskDecisionError, /oo ri/) - # - # lambda { do_something_risky }.should_not raise_error - # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError) - # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, "that was too risky") - # lambda { do_something_risky }.should_not raise_error(PoorRiskDecisionError, /oo ri/) - def raise_error(error=Exception, message=nil) - Matchers::RaiseError.new(error, message) - end - end -end diff --git a/spec/lib/spec/matchers/respond_to.rb b/spec/lib/spec/matchers/respond_to.rb deleted file mode 100644 index 3d23422aa..000000000 --- a/spec/lib/spec/matchers/respond_to.rb +++ /dev/null @@ -1,45 +0,0 @@ -module Spec - module Matchers - - class RespondTo #:nodoc: - def initialize(*names) - @names = names - @names_not_responded_to = [] - end - - def matches?(target) - @names.each do |name| - unless target.respond_to?(name) - @names_not_responded_to << name - end - end - return @names_not_responded_to.empty? - end - - def failure_message - "expected target to respond to #{@names_not_responded_to.collect {|name| name.inspect }.join(', ')}" - end - - def negative_failure_message - "expected target not to respond to #{@names.collect {|name| name.inspect }.join(', ')}" - end - - def description - "respond to ##{@names.to_s}" - end - end - - # :call-seq: - # should respond_to(*names) - # should_not respond_to(*names) - # - # Matches if the target object responds to all of the names - # provided. Names can be Strings or Symbols. - # - # == Examples - # - def respond_to(*names) - Matchers::RespondTo.new(*names) - end - end -end diff --git a/spec/lib/spec/matchers/satisfy.rb b/spec/lib/spec/matchers/satisfy.rb deleted file mode 100644 index 6c0ca95bc..000000000 --- a/spec/lib/spec/matchers/satisfy.rb +++ /dev/null @@ -1,47 +0,0 @@ -module Spec - module Matchers - - class Satisfy #:nodoc: - def initialize(&block) - @block = block - end - - def matches?(actual, &block) - @block = block if block - @actual = actual - @block.call(actual) - end - - def failure_message - "expected #{@actual} to satisfy block" - end - - def negative_failure_message - "expected #{@actual} not to satisfy block" - end - end - - # :call-seq: - # should satisfy {} - # should_not satisfy {} - # - # Passes if the submitted block returns true. Yields target to the - # block. - # - # Generally speaking, this should be thought of as a last resort when - # you can't find any other way to specify the behaviour you wish to - # specify. - # - # If you do find yourself in such a situation, you could always write - # a custom matcher, which would likely make your specs more expressive. - # - # == Examples - # - # 5.should satisfy { |n| - # n > 3 - # } - def satisfy(&block) - Matchers::Satisfy.new(&block) - end - end -end diff --git a/spec/lib/spec/matchers/throw_symbol.rb b/spec/lib/spec/matchers/throw_symbol.rb deleted file mode 100644 index 6d047bc39..000000000 --- a/spec/lib/spec/matchers/throw_symbol.rb +++ /dev/null @@ -1,72 +0,0 @@ -module Spec - module Matchers - - class ThrowSymbol #:nodoc: - def initialize(expected=nil) - @expected = expected - end - - def matches?(proc) - begin - proc.call - rescue NameError => e - @actual = e.name.to_sym - ensure - if @expected.nil? - return @actual.nil? ? false : true - else - return @actual == @expected - end - end - end - - def failure_message - if @actual - "expected #{expected}, got #{@actual.inspect}" - else - "expected #{expected} but nothing was thrown" - end - end - - def negative_failure_message - if @expected - "expected #{expected} not to be thrown" - else - "expected no Symbol, got :#{@actual}" - end - end - - def description - "throw #{expected}" - end - - private - - def expected - @expected.nil? ? "a Symbol" : @expected.inspect - end - - end - - # :call-seq: - # should throw_symbol() - # should throw_symbol(:sym) - # should_not throw_symbol() - # should_not throw_symbol(:sym) - # - # Given a Symbol argument, matches if a proc throws the specified Symbol. - # - # Given no argument, matches if a proc throws any Symbol. - # - # == Examples - # - # lambda { do_something_risky }.should throw_symbol - # lambda { do_something_risky }.should throw_symbol(:that_was_risky) - # - # lambda { do_something_risky }.should_not throw_symbol - # lambda { do_something_risky }.should_not throw_symbol(:that_was_risky) - def throw_symbol(sym=nil) - Matchers::ThrowSymbol.new(sym) - end - end -end diff --git a/spec/lib/spec/mocks.rb b/spec/lib/spec/mocks.rb deleted file mode 100644 index 66cbafb3c..000000000 --- a/spec/lib/spec/mocks.rb +++ /dev/null @@ -1,208 +0,0 @@ -require 'spec/mocks/methods' -require 'spec/mocks/argument_constraint_matchers' -require 'spec/mocks/spec_methods' -require 'spec/mocks/proxy' -require 'spec/mocks/mock' -require 'spec/mocks/argument_expectation' -require 'spec/mocks/message_expectation' -require 'spec/mocks/order_group' -require 'spec/mocks/errors' -require 'spec/mocks/error_generator' -require 'spec/mocks/extensions/object' -require 'spec/mocks/space' - - -module Spec - # == Mocks and Stubs - # - # RSpec will create Mock Objects and Stubs for you at runtime, or attach stub/mock behaviour - # to any of your real objects (Partial Mock/Stub). Because the underlying implementation - # for mocks and stubs is the same, you can intermingle mock and stub - # behaviour in either dynamically generated mocks or your pre-existing classes. - # There is a semantic difference in how they are created, however, - # which can help clarify the role it is playing within a given spec. - # - # == Mock Objects - # - # Mocks are objects that allow you to set and verify expectations that they will - # receive specific messages during run time. They are very useful for specifying how the subject of - # the spec interacts with its collaborators. This approach is widely known as "interaction - # testing". - # - # Mocks are also very powerful as a design tool. As you are - # driving the implementation of a given class, Mocks provide an anonymous - # collaborator that can change in behaviour as quickly as you can write an expectation in your - # spec. This flexibility allows you to design the interface of a collaborator that often - # does not yet exist. As the shape of the class being specified becomes more clear, so do the - # requirements for its collaborators - often leading to the discovery of new types that are - # needed in your system. - # - # Read Endo-Testing[http://www.mockobjects.com/files/endotesting.pdf] for a much - # more in depth description of this process. - # - # == Stubs - # - # Stubs are objects that allow you to set "stub" responses to - # messages. As Martin Fowler points out on his site, - # mocks_arent_stubs[http://www.martinfowler.com/articles/mocksArentStubs.html]. - # Paraphrasing Fowler's paraphrasing - # of Gerard Meszaros: Stubs provide canned responses to messages they might receive in a test, while - # mocks allow you to specify and, subsquently, verify that certain messages should be received during - # the execution of a test. - # - # == Partial Mocks/Stubs - # - # RSpec also supports partial mocking/stubbing, allowing you to add stub/mock behaviour - # to instances of your existing classes. This is generally - # something to be avoided, because changes to the class can have ripple effects on - # seemingly unrelated specs. When specs fail due to these ripple effects, the fact - # that some methods are being mocked can make it difficult to understand why a - # failure is occurring. - # - # That said, partials do allow you to expect and - # verify interactions with class methods such as +#find+ and +#create+ - # on Ruby on Rails model classes. - # - # == Further Reading - # - # There are many different viewpoints about the meaning of mocks and stubs. If you are interested - # in learning more, here is some recommended reading: - # - # * Mock Objects: http://www.mockobjects.com/ - # * Endo-Testing: http://www.mockobjects.com/files/endotesting.pdf - # * Mock Roles, Not Objects: http://www.mockobjects.com/files/mockrolesnotobjects.pdf - # * Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html - # * Mocks aren't stubs: http://www.martinfowler.com/articles/mocksArentStubs.html - # - # == Creating a Mock - # - # You can create a mock in any specification (or setup) using: - # - # mock(name, options={}) - # - # The optional +options+ argument is a +Hash+. Currently the only supported - # option is +:null_object+. Setting this to true instructs the mock to ignore - # any messages it hasn’t been told to expect – and quietly return itself. For example: - # - # mock("person", :null_object => true) - # - # == Creating a Stub - # - # You can create a stub in any specification (or setup) using: - # - # stub(name, stub_methods_and_values_hash) - # - # For example, if you wanted to create an object that always returns - # "More?!?!?!" to "please_sir_may_i_have_some_more" you would do this: - # - # stub("Mr Sykes", :please_sir_may_i_have_some_more => "More?!?!?!") - # - # == Creating a Partial Mock - # - # You don't really "create" a partial mock, you simply add method stubs and/or - # mock expectations to existing classes and objects: - # - # Factory.should_receive(:find).with(id).and_return(value) - # obj.stub!(:to_i).and_return(3) - # etc ... - # - # == Expecting Messages - # - # my_mock.should_receive(:sym) - # my_mock.should_not_receive(:sym) - # - # == Expecting Arguments - # - # my_mock.should_receive(:sym).with(*args) - # my_mock.should_not_receive(:sym).with(*args) - # - # == Argument Constraints using Expression Matchers - # - # Arguments that are passed to #with are compared with actual arguments received - # using == by default. In cases in which you want to specify things about the arguments - # rather than the arguments themselves, you can use any of the Expression Matchers. - # They don't all make syntactic sense (they were primarily designed for use with - # Spec::Expectations), but you are free to create your own custom Spec::Matchers. - # - # Spec::Mocks does provide one additional Matcher method named #ducktype. - # - # In addition, Spec::Mocks adds some keyword Symbols that you can use to - # specify certain kinds of arguments: - # - # my_mock.should_receive(:sym).with(no_args()) - # my_mock.should_receive(:sym).with(any_args()) - # my_mock.should_receive(:sym).with(1, an_instance_of(Numeric), "b") #2nd argument can any type of Numeric - # my_mock.should_receive(:sym).with(1, boolean(), "b") #2nd argument can true or false - # my_mock.should_receive(:sym).with(1, /abc/, "b") #2nd argument can be any String matching the submitted Regexp - # my_mock.should_receive(:sym).with(1, anything(), "b") #2nd argument can be anything at all - # my_mock.should_receive(:sym).with(1, ducktype(:abs, :div), "b") - # #2nd argument can be object that responds to #abs and #div - # - # == Receive Counts - # - # my_mock.should_receive(:sym).once - # my_mock.should_receive(:sym).twice - # my_mock.should_receive(:sym).exactly(n).times - # my_mock.should_receive(:sym).at_least(:once) - # my_mock.should_receive(:sym).at_least(:twice) - # my_mock.should_receive(:sym).at_least(n).times - # my_mock.should_receive(:sym).at_most(:once) - # my_mock.should_receive(:sym).at_most(:twice) - # my_mock.should_receive(:sym).at_most(n).times - # my_mock.should_receive(:sym).any_number_of_times - # - # == Ordering - # - # my_mock.should_receive(:sym).ordered - # my_mock.should_receive(:other_sym).ordered - # #This will fail if the messages are received out of order - # - # == Setting Reponses - # - # Whether you are setting a mock expectation or a simple stub, you can tell the - # object precisely how to respond: - # - # my_mock.should_receive(:sym).and_return(value) - # my_mock.should_receive(:sym).exactly(3).times.and_return(value1, value2, value3) - # # returns value1 the first time, value2 the second, etc - # my_mock.should_receive(:sym).and_return { ... } #returns value returned by the block - # my_mock.should_receive(:sym).and_raise(error) - # #error can be an instantiated object or a class - # #if it is a class, it must be instantiable with no args - # my_mock.should_receive(:sym).and_throw(:sym) - # my_mock.should_receive(:sym).and_yield([array,of,values,to,yield]) - # - # Any of these responses can be applied to a stub as well, but stubs do - # not support any qualifiers about the message received (i.e. you can't specify arguments - # or receive counts): - # - # my_mock.stub!(:sym).and_return(value) - # my_mock.stub!(:sym).and_return(value1, value2, value3) - # my_mock.stub!(:sym).and_raise(error) - # my_mock.stub!(:sym).and_throw(:sym) - # my_mock.stub!(:sym).and_yield([array,of,values,to,yield]) - # - # == Arbitrary Handling - # - # Once in a while you'll find that the available expectations don't solve the - # particular problem you are trying to solve. Imagine that you expect the message - # to come with an Array argument that has a specific length, but you don't care - # what is in it. You could do this: - # - # my_mock.should_receive(:sym) do |arg| - # arg.should be_an_istance_of(Array) - # arg.length.should == 7 - # end - # - # Note that this would fail if the number of arguments received was different from - # the number of block arguments (in this case 1). - # - # == Combining Expectation Details - # - # Combining the message name with specific arguments, receive counts and responses - # you can get quite a bit of detail in your expectations: - # - # my_mock.should_receive(:<<).with("illegal value").once.and_raise(ArgumentError) - module Mocks - end -end diff --git a/spec/lib/spec/mocks/argument_constraint_matchers.rb b/spec/lib/spec/mocks/argument_constraint_matchers.rb deleted file mode 100644 index 0e4777082..000000000 --- a/spec/lib/spec/mocks/argument_constraint_matchers.rb +++ /dev/null @@ -1,27 +0,0 @@ -module Spec - module Mocks - module ArgumentConstraintMatchers - - # Shortcut for creating an instance of Spec::Mocks::DuckTypeArgConstraint - def duck_type(*args) - DuckTypeArgConstraint.new(*args) - end - - def any_args - AnyArgsConstraint.new - end - - def anything - AnyArgConstraint.new(nil) - end - - def boolean - BooleanArgConstraint.new(nil) - end - - def no_args - NoArgsConstraint.new - end - end - end -end diff --git a/spec/lib/spec/mocks/argument_expectation.rb b/spec/lib/spec/mocks/argument_expectation.rb deleted file mode 100644 index 5da069b87..000000000 --- a/spec/lib/spec/mocks/argument_expectation.rb +++ /dev/null @@ -1,183 +0,0 @@ -module Spec - module Mocks - - class MatcherConstraint - def initialize(matcher) - @matcher = matcher - end - - def matches?(value) - @matcher.matches?(value) - end - end - - class LiteralArgConstraint - def initialize(literal) - @literal_value = literal - end - - def matches?(value) - @literal_value == value - end - end - - class RegexpArgConstraint - def initialize(regexp) - @regexp = regexp - end - - def matches?(value) - return value =~ @regexp unless value.is_a?(Regexp) - value == @regexp - end - end - - class AnyArgConstraint - def initialize(ignore) - end - - def ==(other) - true - end - - # TODO - need this? - def matches?(value) - true - end - end - - class AnyArgsConstraint - def description - "any args" - end - end - - class NoArgsConstraint - def description - "no args" - end - - def ==(args) - args == [] - end - end - - class NumericArgConstraint - def initialize(ignore) - end - - def matches?(value) - value.is_a?(Numeric) - end - end - - class BooleanArgConstraint - def initialize(ignore) - end - - def ==(value) - matches?(value) - end - - def matches?(value) - return true if value.is_a?(TrueClass) - return true if value.is_a?(FalseClass) - false - end - end - - class StringArgConstraint - def initialize(ignore) - end - - def matches?(value) - value.is_a?(String) - end - end - - class DuckTypeArgConstraint - def initialize(*methods_to_respond_to) - @methods_to_respond_to = methods_to_respond_to - end - - def matches?(value) - @methods_to_respond_to.all? { |sym| value.respond_to?(sym) } - end - - def description - "duck_type" - end - end - - class ArgumentExpectation - attr_reader :args - @@constraint_classes = Hash.new { |hash, key| LiteralArgConstraint} - @@constraint_classes[:anything] = AnyArgConstraint - @@constraint_classes[:numeric] = NumericArgConstraint - @@constraint_classes[:boolean] = BooleanArgConstraint - @@constraint_classes[:string] = StringArgConstraint - - def initialize(args) - @args = args - if [:any_args] == args - @expected_params = nil - warn_deprecated(:any_args.inspect, "any_args()") - elsif args.length == 1 && args[0].is_a?(AnyArgsConstraint) then @expected_params = nil - elsif [:no_args] == args - @expected_params = [] - warn_deprecated(:no_args.inspect, "no_args()") - elsif args.length == 1 && args[0].is_a?(NoArgsConstraint) then @expected_params = [] - else @expected_params = process_arg_constraints(args) - end - end - - def process_arg_constraints(constraints) - constraints.collect do |constraint| - convert_constraint(constraint) - end - end - - def warn_deprecated(deprecated_method, instead) - STDERR.puts "The #{deprecated_method} constraint is deprecated. Use #{instead} instead." - end - - def convert_constraint(constraint) - if [:anything, :numeric, :boolean, :string].include?(constraint) - case constraint - when :anything - instead = "anything()" - when :boolean - instead = "boolean()" - when :numeric - instead = "an_instance_of(Numeric)" - when :string - instead = "an_instance_of(String)" - end - warn_deprecated(constraint.inspect, instead) - return @@constraint_classes[constraint].new(constraint) - end - return MatcherConstraint.new(constraint) if is_matcher?(constraint) - return RegexpArgConstraint.new(constraint) if constraint.is_a?(Regexp) - return LiteralArgConstraint.new(constraint) - end - - def is_matcher?(obj) - return obj.respond_to?(:matches?) && obj.respond_to?(:description) - end - - def check_args(args) - return true if @expected_params.nil? - return true if @expected_params == args - return constraints_match?(args) - end - - def constraints_match?(args) - return false if args.length != @expected_params.length - @expected_params.each_index { |i| return false unless @expected_params[i].matches?(args[i]) } - return true - end - - end - - end -end diff --git a/spec/lib/spec/mocks/error_generator.rb b/spec/lib/spec/mocks/error_generator.rb deleted file mode 100644 index 01d8f720d..000000000 --- a/spec/lib/spec/mocks/error_generator.rb +++ /dev/null @@ -1,84 +0,0 @@ -module Spec - module Mocks - class ErrorGenerator - attr_writer :opts - - def initialize(target, name) - @target = target - @name = name - end - - def opts - @opts ||= {} - end - - def raise_unexpected_message_error(sym, *args) - __raise "#{intro} received unexpected message :#{sym}#{arg_message(*args)}" - end - - def raise_unexpected_message_args_error(expectation, *args) - expected_args = format_args(*expectation.expected_args) - actual_args = args.empty? ? "(no args)" : format_args(*args) - __raise "#{intro} expected #{expectation.sym.inspect} with #{expected_args} but received it with #{actual_args}" - end - - def raise_expectation_error(sym, expected_received_count, actual_received_count, *args) - __raise "#{intro} expected :#{sym}#{arg_message(*args)} #{count_message(expected_received_count)}, but received it #{count_message(actual_received_count)}" - end - - def raise_out_of_order_error(sym) - __raise "#{intro} received :#{sym} out of order" - end - - def raise_block_failed_error(sym, detail) - __raise "#{intro} received :#{sym} but passed block failed with: #{detail}" - end - - def raise_missing_block_error(args_to_yield) - __raise "#{intro} asked to yield |#{arg_list(*args_to_yield)}| but no block was passed" - end - - def raise_wrong_arity_error(args_to_yield, arity) - __raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}" - end - - private - def intro - @name ? "Mock '#{@name}'" : @target.inspect - end - - def __raise(message) - message = opts[:message] unless opts[:message].nil? - Kernel::raise(Spec::Mocks::MockExpectationError, message) - end - - def arg_message(*args) - " with " + format_args(*args) - end - - def format_args(*args) - return "(no args)" if args.empty? || args == [:no_args] - return "(any args)" if args == [:any_args] - "(" + arg_list(*args) + ")" - end - - def arg_list(*args) - args.collect do |arg| - arg.respond_to?(:description) ? arg.description : arg.inspect - end.join(", ") - end - - def count_message(count) - return "at least #{pretty_print(count.abs)}" if count < 0 - return pretty_print(count) - end - - def pretty_print(count) - return "once" if count == 1 - return "twice" if count == 2 - return "#{count} times" - end - - end - end -end diff --git a/spec/lib/spec/mocks/errors.rb b/spec/lib/spec/mocks/errors.rb deleted file mode 100644 index 68fdfe006..000000000 --- a/spec/lib/spec/mocks/errors.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Spec - module Mocks - class MockExpectationError < StandardError - end - - class AmbiguousReturnError < StandardError - end - end -end - diff --git a/spec/lib/spec/mocks/extensions/object.rb b/spec/lib/spec/mocks/extensions/object.rb deleted file mode 100644 index 4b7531066..000000000 --- a/spec/lib/spec/mocks/extensions/object.rb +++ /dev/null @@ -1,3 +0,0 @@ -class Object - include Spec::Mocks::Methods -end diff --git a/spec/lib/spec/mocks/message_expectation.rb b/spec/lib/spec/mocks/message_expectation.rb deleted file mode 100644 index 74ade3c58..000000000 --- a/spec/lib/spec/mocks/message_expectation.rb +++ /dev/null @@ -1,242 +0,0 @@ -module Spec - module Mocks - - class BaseExpectation - attr_reader :sym - - def initialize(error_generator, expectation_ordering, expected_from, sym, method_block, expected_received_count=1, opts={}) - @error_generator = error_generator - @error_generator.opts = opts - @expected_from = expected_from - @sym = sym - @method_block = method_block - @return_block = lambda {} - @received_count = 0 - @expected_received_count = expected_received_count - @args_expectation = ArgumentExpectation.new([AnyArgsConstraint.new]) - @consecutive = false - @exception_to_raise = nil - @symbol_to_throw = nil - @order_group = expectation_ordering - @at_least = nil - @at_most = nil - @args_to_yield = nil - end - - def expected_args - @args_expectation.args - end - - def and_return(*values, &return_block) - Kernel::raise AmbiguousReturnError unless @method_block.nil? - if values.size == 0 - value = nil - elsif values.size == 1 - value = values[0] - else - value = values - @consecutive = true - @expected_received_count = values.size if @expected_received_count != :any && - @expected_received_count < values.size - end - @return_block = block_given? ? return_block : lambda { value } - end - - # :call-seq: - # and_raise() - # and_raise(Exception) #any exception class - # and_raise(exception) #any exception object - # - # == Warning - # - # When you pass an exception class, the MessageExpectation will - # raise an instance of it, creating it with +new+. If the exception - # class initializer requires any parameters, you must pass in an - # instance and not the class. - def and_raise(exception=Exception) - @exception_to_raise = exception - end - - def and_throw(symbol) - @symbol_to_throw = symbol - end - - def and_yield(*args) - @args_to_yield = args - end - - def matches(sym, args) - @sym == sym and @args_expectation.check_args(args) - end - - def invoke(args, block) - @order_group.handle_order_constraint self - - begin - if @exception_to_raise.class == Class - @exception_instance_to_raise = @exception_to_raise.new - else - @exception_instance_to_raise = @exception_to_raise - end - Kernel::raise @exception_to_raise unless @exception_to_raise.nil? - Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil? - - if !@method_block.nil? - return invoke_method_block(args) - elsif !@args_to_yield.nil? - return invoke_with_yield(block) - elsif @consecutive - return invoke_consecutive_return_block(args, block) - else - return invoke_return_block(args, block) - end - ensure - @received_count += 1 - end - end - - protected - - def invoke_method_block(args) - begin - @method_block.call(*args) - rescue => detail - @error_generator.raise_block_failed_error @sym, detail.message - end - end - - def invoke_with_yield(block) - if block.nil? - @error_generator.raise_missing_block_error @args_to_yield - end - if block.arity > -1 && @args_to_yield.length != block.arity - @error_generator.raise_wrong_arity_error @args_to_yield, block.arity - end - block.call(*@args_to_yield) - end - - def invoke_consecutive_return_block(args, block) - args << block unless block.nil? - value = @return_block.call(*args) - - index = [@received_count, value.size-1].min - value[index] - end - - def invoke_return_block(args, block) - args << block unless block.nil? - value = @return_block.call(*args) - - value - end - end - - class MessageExpectation < BaseExpectation - - def matches_name_but_not_args(sym, args) - @sym == sym and not @args_expectation.check_args(args) - end - - def verify_messages_received - return if @expected_received_count == :any - return if (@at_least) && (@received_count >= @expected_received_count) - return if (@at_most) && (@received_count <= @expected_received_count) - return if @expected_received_count == @received_count - - begin - @error_generator.raise_expectation_error(@sym, @expected_received_count, @received_count, *@args_expectation.args) - rescue => error - error.backtrace.insert(0, @expected_from) - Kernel::raise error - end - end - - def with(*args, &block) - @method_block = block if block - @args_expectation = ArgumentExpectation.new(args) - self - end - - def exactly(n) - set_expected_received_count :exactly, n - self - end - - def at_least(n) - set_expected_received_count :at_least, n - self - end - - def at_most(n) - set_expected_received_count :at_most, n - self - end - - def times(&block) - @method_block = block if block - self - end - - def any_number_of_times(&block) - @method_block = block if block - @expected_received_count = :any - self - end - - def never - @expected_received_count = 0 - self - end - - def once(&block) - @method_block = block if block - @expected_received_count = 1 - self - end - - def twice(&block) - @method_block = block if block - @expected_received_count = 2 - self - end - - def ordered(&block) - @method_block = block if block - @order_group.register(self) - @ordered = true - self - end - - def negative_expectation_for?(sym) - return false - end - - protected - def set_expected_received_count(relativity, n) - @at_least = (relativity == :at_least) - @at_most = (relativity == :at_most) - @expected_received_count = 1 if n == :once - @expected_received_count = 2 if n == :twice - @expected_received_count = n if n.kind_of? Numeric - end - - end - - class NegativeMessageExpectation < MessageExpectation - def initialize(message, expectation_ordering, expected_from, sym, method_block) - super(message, expectation_ordering, expected_from, sym, method_block, 0) - end - - def negative_expectation_for?(sym) - return @sym == sym - end - end - - class MethodStub < BaseExpectation - def initialize(message, expectation_ordering, expected_from, sym, method_block) - super(message, expectation_ordering, expected_from, sym, method_block, 0) - @expected_received_count = :any - end - end - end -end diff --git a/spec/lib/spec/mocks/methods.rb b/spec/lib/spec/mocks/methods.rb deleted file mode 100644 index 3d898cf31..000000000 --- a/spec/lib/spec/mocks/methods.rb +++ /dev/null @@ -1,39 +0,0 @@ -module Spec - module Mocks - module Methods - def should_receive(sym, opts={}, &block) - __mock_proxy.add_message_expectation(opts[:expected_from] || caller(1)[0], sym.to_sym, opts, &block) - end - - def should_not_receive(sym, &block) - __mock_proxy.add_negative_message_expectation(caller(1)[0], sym.to_sym, &block) - end - - def stub!(sym) - __mock_proxy.add_stub(caller(1)[0], sym.to_sym) - end - - def received_message?(sym, *args, &block) #:nodoc: - __mock_proxy.received_message?(sym.to_sym, *args, &block) - end - - def rspec_verify #:nodoc: - __mock_proxy.verify - end - - def rspec_reset #:nodoc: - __mock_proxy.reset - end - - private - - def __mock_proxy - if Mock === self - @mock_proxy ||= Proxy.new(self, @name, @options) - else - @mock_proxy ||= Proxy.new(self, self.class.name) - end - end - end - end -end diff --git a/spec/lib/spec/mocks/mock.rb b/spec/lib/spec/mocks/mock.rb deleted file mode 100644 index aa380e0af..000000000 --- a/spec/lib/spec/mocks/mock.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Spec - module Mocks - class Mock - include Methods - - # Creates a new mock with a +name+ (that will be used in error messages only) - # == Options: - # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving null object allowing any message to be sent to it. - def initialize(name, options={}) - @name = name - @options = options - end - - def method_missing(sym, *args, &block) - __mock_proxy.instance_eval {@messages_received << [sym, args, block]} - begin - return self if __mock_proxy.null_object? - super(sym, *args, &block) - rescue NoMethodError - __mock_proxy.raise_unexpected_message_error sym, *args - end - end - - def inspect - "#<#{self.class}:#{sprintf '0x%x', self.object_id} @name=#{@name.inspect}>" - end - end - end -end diff --git a/spec/lib/spec/mocks/order_group.rb b/spec/lib/spec/mocks/order_group.rb deleted file mode 100644 index 9983207eb..000000000 --- a/spec/lib/spec/mocks/order_group.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Spec - module Mocks - class OrderGroup - def initialize error_generator - @error_generator = error_generator - @ordering = Array.new - end - - def register(expectation) - @ordering << expectation - end - - def ready_for?(expectation) - return @ordering.first == expectation - end - - def consume - @ordering.shift - end - - def handle_order_constraint expectation - return unless @ordering.include? expectation - return consume if ready_for?(expectation) - @error_generator.raise_out_of_order_error expectation.sym - end - - end - end -end diff --git a/spec/lib/spec/mocks/proxy.rb b/spec/lib/spec/mocks/proxy.rb deleted file mode 100644 index 6c79d1068..000000000 --- a/spec/lib/spec/mocks/proxy.rb +++ /dev/null @@ -1,167 +0,0 @@ -module Spec - module Mocks - class Proxy - DEFAULT_OPTIONS = { - :null_object => false, - } - - def initialize(target, name, options={}) - @target = target - @name = name - @error_generator = ErrorGenerator.new target, name - @expectation_ordering = OrderGroup.new @error_generator - @expectations = [] - @messages_received = [] - @stubs = [] - @proxied_methods = [] - @options = options ? DEFAULT_OPTIONS.dup.merge(options) : DEFAULT_OPTIONS - end - - def null_object? - @options[:null_object] - end - - def add_message_expectation(expected_from, sym, opts={}, &block) - __add sym, block - @expectations << MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts) - @expectations.last - end - - def add_negative_message_expectation(expected_from, sym, &block) - __add sym, block - @expectations << NegativeMessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil) - @expectations.last - end - - def add_stub(expected_from, sym) - __add sym, nil - @stubs.unshift MethodStub.new(@error_generator, @expectation_ordering, expected_from, sym, nil) - @stubs.first - end - - def verify #:nodoc: - begin - verify_expectations - ensure - reset - end - end - - def reset - clear_expectations - clear_stubs - reset_proxied_methods - clear_proxied_methods - end - - def received_message?(sym, *args, &block) - return true if @messages_received.find {|array| array == [sym, args, block]} - return false - end - - def has_negative_expectation?(sym) - @expectations.detect {|expectation| expectation.negative_expectation_for?(sym)} - end - - def message_received(sym, *args, &block) - if expectation = find_matching_expectation(sym, *args) - expectation.invoke(args, block) - elsif stub = find_matching_method_stub(sym) - stub.invoke([], block) - elsif expectation = find_almost_matching_expectation(sym, *args) - raise_unexpected_message_args_error(expectation, *args) unless has_negative_expectation?(sym) unless null_object? - else - @target.send :method_missing, sym, *args, &block - end - end - - def raise_unexpected_message_args_error(expectation, *args) - @error_generator.raise_unexpected_message_args_error expectation, *args - end - - def raise_unexpected_message_error(sym, *args) - @error_generator.raise_unexpected_message_error sym, *args - end - - private - - def __add(sym, block) - $rspec_mocks.add(@target) unless $rspec_mocks.nil? - define_expected_method(sym) - end - - def define_expected_method(sym) - if target_responds_to?(sym) && !@proxied_methods.include?(sym) - metaclass.__send__(:alias_method, munge(sym), sym) if metaclass.instance_methods.include?(sym.to_s) - @proxied_methods << sym - end - - metaclass_eval(<<-EOF, __FILE__, __LINE__) - def #{sym}(*args, &block) - __mock_proxy.message_received :#{sym}, *args, &block - end - EOF - end - - def target_responds_to?(sym) - return @target.send(munge(:respond_to?),sym) if @already_proxied_respond_to - return @already_proxied_respond_to = true if sym == :respond_to? - return @target.respond_to?(sym) - end - - def munge(sym) - "proxied_by_rspec__#{sym.to_s}".to_sym - end - - def clear_expectations - @expectations.clear - end - - def clear_stubs - @stubs.clear - end - - def clear_proxied_methods - @proxied_methods.clear - end - - def metaclass_eval(str, filename, lineno) - metaclass.class_eval(str, filename, lineno) - end - - def metaclass - (class << @target; self; end) - end - - def verify_expectations - @expectations.each do |expectation| - expectation.verify_messages_received - end - end - - def reset_proxied_methods - @proxied_methods.each do |sym| - if metaclass.instance_methods.include?(munge(sym).to_s) - metaclass.__send__(:alias_method, sym, munge(sym)) - metaclass.__send__(:undef_method, munge(sym)) - else - metaclass.__send__(:undef_method, sym) - end - end - end - - def find_matching_expectation(sym, *args) - @expectations.find {|expectation| expectation.matches(sym, args)} - end - - def find_almost_matching_expectation(sym, *args) - @expectations.find {|expectation| expectation.matches_name_but_not_args(sym, args)} - end - - def find_matching_method_stub(sym) - @stubs.find {|stub| stub.matches(sym, [])} - end - - end - end -end diff --git a/spec/lib/spec/mocks/space.rb b/spec/lib/spec/mocks/space.rb deleted file mode 100644 index e04bc5ccb..000000000 --- a/spec/lib/spec/mocks/space.rb +++ /dev/null @@ -1,28 +0,0 @@ -module Spec - module Mocks - class Space - def add(obj) - mocks << obj unless mocks.include?(obj) - end - - def verify_all - mocks.each do |mock| - mock.rspec_verify - end - end - - def reset_all - mocks.each do |mock| - mock.rspec_reset - end - mocks.clear - end - - private - - def mocks - @mocks ||= [] - end - end - end -end diff --git a/spec/lib/spec/mocks/spec_methods.rb b/spec/lib/spec/mocks/spec_methods.rb deleted file mode 100644 index fd67fd210..000000000 --- a/spec/lib/spec/mocks/spec_methods.rb +++ /dev/null @@ -1,30 +0,0 @@ -module Spec - module Mocks - module SpecMethods - include Spec::Mocks::ArgumentConstraintMatchers - - # Shortcut for creating an instance of Spec::Mocks::Mock. - def mock(name, options={}) - Spec::Mocks::Mock.new(name, options) - end - - # Shortcut for creating an instance of Spec::Mocks::Mock with - # predefined method stubs. - # - # == Examples - # - # stub_thing = stub("thing", :a => "A") - # stub_thing.a == "A" => true - # - # stub_person = stub("thing", :name => "Joe", :email => "joe@domain.com") - # stub_person.name => "Joe" - # stub_person.email => "joe@domain.com" - def stub(name, stubs={}) - object_stub = mock(name) - stubs.each { |key, value| object_stub.stub!(key).and_return(value) } - object_stub - end - - end - end -end diff --git a/spec/lib/spec/rake/spectask.rb b/spec/lib/spec/rake/spectask.rb deleted file mode 100644 index f8c6809a9..000000000 --- a/spec/lib/spec/rake/spectask.rb +++ /dev/null @@ -1,217 +0,0 @@ -#!/usr/bin/env ruby - -# Define a task library for running RSpec contexts. - -require 'rake' -require 'rake/tasklib' - -module Spec - module Rake - - # A Rake task that runs a set of RSpec contexts. - # - # Example: - # - # Spec::Rake::SpecTask.new do |t| - # t.warning = true - # t.rcov = true - # end - # - # This will create a task that can be run with: - # - # rake spec - # - # If rake is invoked with a "SPEC=filename" command line option, - # then the list of spec files will be overridden to include only the - # filename specified on the command line. This provides an easy way - # to run just one spec. - # - # If rake is invoked with a "SPEC_OPTS=options" command line option, - # then the given options will override the value of the +spec_opts+ - # attribute. - # - # If rake is invoked with a "RCOV_OPTS=options" command line option, - # then the given options will override the value of the +rcov_opts+ - # attribute. - # - # Examples: - # - # rake spec # run specs normally - # rake spec SPEC=just_one_file.rb # run just one spec file. - # rake spec SPEC_OPTS="--diff" # enable diffing - # rake spec RCOV_OPTS="--aggregate myfile.txt" # see rcov --help for details - # - # Each attribute of this task may be a proc. This allows for lazy evaluation, - # which is sometimes handy if you want to defer the evaluation of an attribute value - # until the task is run (as opposed to when it is defined). - class SpecTask < ::Rake::TaskLib - class << self - def attr_accessor(*names) - super(*names) - names.each do |name| - module_eval "def #{name}() evaluate(@#{name}) end" # Allows use of procs - end - end - end - - # Name of spec task. (default is :spec) - attr_accessor :name - - # Array of directories to be added to $LOAD_PATH before running the - # specs. Defaults to ['<the absolute path to RSpec's lib directory>'] - attr_accessor :libs - - # If true, requests that the specs be run with the warning flag set. - # E.g. warning=true implies "ruby -w" used to run the specs. Defaults to false. - attr_accessor :warning - - # Glob pattern to match spec files. (default is 'spec/**/*_spec.rb') - # Setting the SPEC environment variable overrides this. - attr_accessor :pattern - - # Array of commandline options to pass to RSpec. Defaults to []. - # Setting the SPEC_OPTS environment variable overrides this. - attr_accessor :spec_opts - - # Whether or not to use RCov (default is false) - # See http://eigenclass.org/hiki.rb?rcov - attr_accessor :rcov - - # Array of commandline options to pass to RCov. Defaults to ['--exclude', 'lib\/spec,bin\/spec']. - # Ignored if rcov=false - # Setting the RCOV_OPTS environment variable overrides this. - attr_accessor :rcov_opts - - # Directory where the RCov report is written. Defaults to "coverage" - # Ignored if rcov=false - attr_accessor :rcov_dir - - # Array of commandline options to pass to ruby. Defaults to []. - attr_accessor :ruby_opts - - # Whether or not to fail Rake when an error occurs (typically when specs fail). - # Defaults to true. - attr_accessor :fail_on_error - - # A message to print to stderr when there are failures. - attr_accessor :failure_message - - # Where RSpec's output is written. Defaults to STDOUT. - # DEPRECATED. Use --format FORMAT:WHERE in spec_opts. - attr_accessor :out - - # Explicitly define the list of spec files to be included in a - # spec. +spec_files+ is expected to be an array of file names (a - # FileList is acceptable). If both +pattern+ and +spec_files+ are - # used, then the list of spec files is the union of the two. - # Setting the SPEC environment variable overrides this. - attr_accessor :spec_files - - # Defines a new task, using the name +name+. - def initialize(name=:spec) - @name = name - @libs = [File.expand_path(File.dirname(__FILE__) + '/../../../lib')] - @pattern = nil - @spec_files = nil - @spec_opts = [] - @warning = false - @ruby_opts = [] - @fail_on_error = true - @rcov = false - @rcov_opts = ['--exclude', 'lib\/spec,bin\/spec,config\/boot.rb'] - @rcov_dir = "coverage" - - yield self if block_given? - @pattern = 'spec/**/*_spec.rb' if pattern.nil? && spec_files.nil? - define - end - - def define # :nodoc: - spec_script = File.expand_path(File.dirname(__FILE__) + '/../../../bin/spec') - - lib_path = libs.join(File::PATH_SEPARATOR) - actual_name = Hash === name ? name.keys.first : name - unless ::Rake.application.last_comment - desc "Run specs" + (rcov ? " using RCov" : "") - end - task name do - RakeFileUtils.verbose(verbose) do - unless spec_file_list.empty? - # ruby [ruby_opts] -Ilib -S rcov [rcov_opts] bin/spec -- examples [spec_opts] - # or - # ruby [ruby_opts] -Ilib bin/spec examples [spec_opts] - cmd = "ruby " - - rb_opts = ruby_opts.clone - rb_opts << "-I\"#{lib_path}\"" - rb_opts << "-S rcov" if rcov - rb_opts << "-w" if warning - cmd << rb_opts.join(" ") - cmd << " " - cmd << rcov_option_list - cmd << %[ -o "#{rcov_dir}" ] if rcov - cmd << %Q|"#{spec_script}"| - cmd << " " - cmd << "-- " if rcov - cmd << spec_file_list.collect { |fn| %["#{fn}"] }.join(' ') - cmd << " " - cmd << spec_option_list - if out - cmd << " " - cmd << %Q| > "#{out}"| - STDERR.puts "The Spec::Rake::SpecTask#out attribute is DEPRECATED and will be removed in a future version. Use --format FORMAT:WHERE instead." - end - unless system(cmd) - STDERR.puts failure_message if failure_message - raise("Command #{cmd} failed") if fail_on_error - end - end - end - end - - if rcov - desc "Remove rcov products for #{actual_name}" - task paste("clobber_", actual_name) do - rm_r rcov_dir rescue nil - end - - clobber_task = paste("clobber_", actual_name) - task :clobber => [clobber_task] - - task actual_name => clobber_task - end - self - end - - def rcov_option_list # :nodoc: - return "" unless rcov - ENV['RCOV_OPTS'] || rcov_opts.join(" ") || "" - end - - def spec_option_list # :nodoc: - STDERR.puts "RSPECOPTS is DEPRECATED and will be removed in a future version. Use SPEC_OPTS instead." if ENV['RSPECOPTS'] - ENV['SPEC_OPTS'] || ENV['RSPECOPTS'] || spec_opts.join(" ") || "" - end - - def evaluate(o) # :nodoc: - case o - when Proc then o.call - else o - end - end - - def spec_file_list # :nodoc: - if ENV['SPEC'] - FileList[ ENV['SPEC'] ] - else - result = [] - result += spec_files.to_a if spec_files - result += FileList[ pattern ].to_a if pattern - FileList[result] - end - end - - end - end -end - diff --git a/spec/lib/spec/rake/verify_rcov.rb b/spec/lib/spec/rake/verify_rcov.rb deleted file mode 100644 index 9715744e9..000000000 --- a/spec/lib/spec/rake/verify_rcov.rb +++ /dev/null @@ -1,52 +0,0 @@ -module RCov - # A task that can verify that the RCov coverage doesn't - # drop below a certain threshold. It should be run after - # running Spec::Rake::SpecTask. - class VerifyTask < Rake::TaskLib - # Name of the task. Defaults to :verify_rcov - attr_accessor :name - - # Path to the index.html file generated by RCov, which - # is the file containing the total coverage. - # Defaults to 'coverage/index.html' - attr_accessor :index_html - - # Whether or not to output details. Defaults to true. - attr_accessor :verbose - - # The threshold value (in percent) for coverage. If the - # actual coverage is not equal to this value, the task will raise an - # exception. - attr_accessor :threshold - - # Require the threshold value be met exactly. This is the default. - attr_accessor :require_exact_threshold - - def initialize(name=:verify_rcov) - @name = name - @index_html = 'coverage/index.html' - @verbose = true - @require_exact_threshold = true - yield self if block_given? - raise "Threshold must be set" if @threshold.nil? - define - end - - def define - desc "Verify that rcov coverage is at least #{threshold}%" - task @name do - total_coverage = nil - - File.open(index_html).each_line do |line| - if line =~ /<tt.*>(\d+\.\d+)%<\/tt> <\/td>/ - total_coverage = eval($1) - break - end - end - puts "Coverage: #{total_coverage}% (threshold: #{threshold}%)" if verbose - raise "Coverage must be at least #{threshold}% but was #{total_coverage}%" if total_coverage < threshold - raise "Coverage has increased above the threshold of #{threshold}% to #{total_coverage}%. You should update your threshold value." if (total_coverage > threshold) and require_exact_threshold - end - end - end -end diff --git a/spec/lib/spec/runner.rb b/spec/lib/spec/runner.rb deleted file mode 100644 index 9d801adc3..000000000 --- a/spec/lib/spec/runner.rb +++ /dev/null @@ -1,165 +0,0 @@ -require 'spec/runner/formatter' -require 'spec/runner/behaviour_runner' -require 'spec/runner/options' -require 'spec/runner/option_parser' -require 'spec/runner/command_line' -require 'spec/runner/drb_command_line' -require 'spec/runner/backtrace_tweaker' -require 'spec/runner/reporter' -require 'spec/runner/extensions/object' -require 'spec/runner/extensions/kernel' -require 'spec/runner/spec_parser' - -module Spec - # == Behaviours and Examples - # - # Rather than expressing examples in classes, RSpec uses a custom domain specific language to - # describe Behaviours and Examples of those behaviours. - # - # A Behaviour is the equivalent of a fixture in xUnit-speak. It is a metaphor for the context - # in which you will run your executable example - a set of known objects in a known starting state. - # We begin be describing - # - # describe Account do - # - # before do - # @account = Account.new - # end - # - # it "should have a balance of $0" do - # @account.balance.should == Money.new(0, :dollars) - # end - # - # end - # - # We use the before block to set up the Behaviour (given), and then the #it method to - # hold the example code that expresses the event (when) and the expected outcome (then). - # - # == Helper Methods - # - # A primary goal of RSpec is to keep the examples clear. We therefore prefer - # less indirection than you might see in xUnit examples and in well factored, DRY production code. We feel - # that duplication is OK if removing it makes it harder to understand an example without - # having to look elsewhere to understand its context. - # - # That said, RSpec does support some level of encapsulating common code in helper - # methods that can exist within a context or within an included module. - # - # == Setup and Teardown - # - # You can use before and after within a Behaviour. Both methods take an optional - # scope argument so you can run the block before :each example or before :all examples - # - # describe "..." do - # before :all do - # ... - # end - # - # before :each do - # ... - # end - # - # it "should do something" do - # ... - # end - # - # it "should do something else" do - # ... - # end - # - # after :each do - # ... - # end - # - # after :all do - # ... - # end - # - # end - # - # The <tt>before :each</tt> block will run before each of the examples, once for each example. Likewise, - # the <tt>after :each</tt> block will run after each of the examples. - # - # It is also possible to specify a <tt>before :all</tt> and <tt>after :all</tt> - # block that will run only once for each behaviour, respectively before the first <code>before :each</code> - # and after the last <code>after :each</code>. The use of these is generally discouraged, because it - # introduces dependencies between the examples. Still, it might prove useful for very expensive operations - # if you know what you are doing. - # - # == Local helper methods - # - # You can include local helper methods by simply expressing them within a context: - # - # describe "..." do - # - # it "..." do - # helper_method - # end - # - # def helper_method - # ... - # end - # - # end - # - # == Included helper methods - # - # You can include helper methods in multiple contexts by expressing them within - # a module, and then including that module in your context: - # - # module AccountExampleHelperMethods - # def helper_method - # ... - # end - # end - # - # describe "A new account" do - # include AccountExampleHelperMethods - # before do - # @account = Account.new - # end - # - # it "should have a balance of $0" do - # helper_method - # @account.balance.should eql(Money.new(0, :dollars)) - # end - # end - # - # == Shared behaviour - # - # You can define a shared behaviour, that may be used on other behaviours - # - # describe "All Editions", :shared => true do - # it "all editions behaviour" ... - # end - # - # describe SmallEdition do - # it_should_behave_like "All Editions" - # - # it "should do small edition stuff" do - # ... - # end - # end - module Runner - class << self - def configuration # :nodoc: - @configuration ||= Spec::DSL::Configuration.new - end - - # Use this to configure various configurable aspects of - # RSpec: - # - # Spec::Runner.configure do |configuration| - # # Configure RSpec here - # end - # - # The yielded <tt>configuration</tt> object is a - # Spec::DSL::Configuration instance. See its RDoc - # for details about what you can do with it. - # - def configure - yield configuration if @configuration.nil? - end - end - end -end diff --git a/spec/lib/spec/runner/backtrace_tweaker.rb b/spec/lib/spec/runner/backtrace_tweaker.rb deleted file mode 100644 index aacc2c8b8..000000000 --- a/spec/lib/spec/runner/backtrace_tweaker.rb +++ /dev/null @@ -1,57 +0,0 @@ -module Spec - module Runner - class BacktraceTweaker - def clean_up_double_slashes(line) - line.gsub!('//','/') - end - end - - class NoisyBacktraceTweaker < BacktraceTweaker - def tweak_backtrace(error, spec_name) - return if error.backtrace.nil? - error.backtrace.each do |line| - clean_up_double_slashes(line) - end - end - end - - # Tweaks raised Exceptions to mask noisy (unneeded) parts of the backtrace - class QuietBacktraceTweaker < BacktraceTweaker - unless defined?(IGNORE_PATTERNS) - root_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', '..')) - spec_files = Dir["#{root_dir}/lib/spec/*"].map do |path| - subpath = path[root_dir.length..-1] - /#{subpath}/ - end - IGNORE_PATTERNS = spec_files + [ - /\/lib\/ruby\//, - /bin\/spec:/, - /bin\/rcov:/, - /lib\/rspec_on_rails/, - /vendor\/rails/, - # TextMate's Ruby and RSpec plugins - /Ruby\.tmbundle\/Support\/tmruby.rb:/, - /RSpec\.tmbundle\/Support\/lib/, - /temp_textmate\./, - /mock_frameworks\/rspec/, - /spec_server/ - ] - end - - def tweak_backtrace(error, spec_name) - return if error.backtrace.nil? - error.backtrace.collect! do |line| - clean_up_double_slashes(line) - IGNORE_PATTERNS.each do |ignore| - if line =~ ignore - line = nil - break - end - end - line - end - error.backtrace.compact! - end - end - end -end diff --git a/spec/lib/spec/runner/behaviour_runner.rb b/spec/lib/spec/runner/behaviour_runner.rb deleted file mode 100644 index 1ac891f3c..000000000 --- a/spec/lib/spec/runner/behaviour_runner.rb +++ /dev/null @@ -1,123 +0,0 @@ -module Spec - module Runner - class BehaviourRunner - - def initialize(options, arg=nil) - @behaviours = [] - @options = options - end - - def add_behaviour(behaviour) - if !specified_examples.nil? && !specified_examples.empty? - behaviour.retain_examples_matching!(specified_examples) - end - @behaviours << behaviour if behaviour.number_of_examples != 0 && !behaviour.shared? - end - - # Runs all behaviours and returns the number of failures. - def run(paths, exit_when_done) - prepare!(paths) - begin - run_behaviours - rescue Interrupt - ensure - report_end - end - failure_count = report_dump - - heckle if(failure_count == 0 && !@options.heckle_runner.nil?) - - if(exit_when_done) - exit_code = (failure_count == 0) ? 0 : 1 - exit(exit_code) - end - failure_count - end - - def report_end - @options.reporter.end - end - - def report_dump - @options.reporter.dump - end - - def prepare!(paths) - unless paths.nil? # It's nil when running single specs with ruby - paths = find_paths(paths) - sorted_paths = sort_paths(paths) - load_specs(sorted_paths) # This will populate @behaviours via callbacks to add_behaviour - end - @options.reporter.start(number_of_examples) - @behaviours.reverse! if @options.reverse - set_sequence_numbers - end - - def run_behaviours - @behaviours.each do |behaviour| - behaviour.run(@options.reporter, @options.dry_run, @options.reverse, @options.timeout) - end - end - - def number_of_examples - @behaviours.inject(0) {|sum, behaviour| sum + behaviour.number_of_examples} - end - - FILE_SORTERS = { - 'mtime' => lambda {|file_a, file_b| File.mtime(file_b) <=> File.mtime(file_a)} - } - - def sorter(paths) - FILE_SORTERS[@options.loadby] - end - - def sort_paths(paths) - sorter = sorter(paths) - paths = paths.sort(&sorter) unless sorter.nil? - paths - end - - private - - # Sets the #number on each Example - def set_sequence_numbers - number = 0 - @behaviours.each do |behaviour| - number = behaviour.set_sequence_numbers(number, @options.reverse) - end - end - - def find_paths(paths) - result = [] - paths.each do |path| - if File.directory?(path) - result += Dir["#{path}/**/*.rb"] - elsif File.file?(path) - result << path - else - raise "File or directory not found: #{path}" - end - end - result - end - - def load_specs(paths) - paths.each do |path| - load path - end - end - - def specified_examples - @options.examples - end - - def heckle - heckle_runner = @options.heckle_runner - @options.heckle_runner = nil - behaviour_runner = self.class.new(@options) - behaviour_runner.instance_variable_set(:@behaviours, @behaviours) - heckle_runner.heckle_with(behaviour_runner) - end - end - end -end diff --git a/spec/lib/spec/runner/command_line.rb b/spec/lib/spec/runner/command_line.rb deleted file mode 100644 index 0d70337e1..000000000 --- a/spec/lib/spec/runner/command_line.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'spec/runner/option_parser' - -module Spec - module Runner - # Facade to run specs without having to fork a new ruby process (using `spec ...`) - class CommandLine - # Runs specs. +argv+ is the commandline args as per the spec commandline API, +err+ - # and +out+ are the streams output will be written to. +exit+ tells whether or - # not a system exit should be called after the specs are run and - # +warn_if_no_files+ tells whether or not a warning (the help message) - # should be printed to +err+ in case no files are specified. - def self.run(argv, err, out, exit=true, warn_if_no_files=true) - old_behaviour_runner = defined?($behaviour_runner) ? $behaviour_runner : nil - $behaviour_runner = OptionParser.new.create_behaviour_runner(argv, err, out, warn_if_no_files) - return if $behaviour_runner.nil? # This is the case if we use --drb - - $behaviour_runner.run(argv, exit) - $behaviour_runner = old_behaviour_runner - end - end - end -end diff --git a/spec/lib/spec/runner/drb_command_line.rb b/spec/lib/spec/runner/drb_command_line.rb deleted file mode 100644 index 7e745fb71..000000000 --- a/spec/lib/spec/runner/drb_command_line.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "drb/drb" - -module Spec - module Runner - # Facade to run specs by connecting to a DRB server - class DrbCommandLine - # Runs specs on a DRB server. Note that this API is similar to that of - # CommandLine - making it possible for clients to use both interchangeably. - def self.run(argv, stderr, stdout, exit=true, warn_if_no_files=true) - begin - DRb.start_service - spec_server = DRbObject.new_with_uri("druby://localhost:8989") - spec_server.run(argv, stderr, stdout) - rescue DRb::DRbConnError - stderr.puts "No server is running" - exit 1 if exit - end - end - end - end -end diff --git a/spec/lib/spec/runner/extensions/kernel.rb b/spec/lib/spec/runner/extensions/kernel.rb deleted file mode 100644 index 75f2c335e..000000000 --- a/spec/lib/spec/runner/extensions/kernel.rb +++ /dev/null @@ -1,50 +0,0 @@ -module Kernel - # Creates and registers an instance of a Spec::DSL::Behaviour (or a subclass). - # The instantiated behaviour class depends on the directory of the file - # calling this method. For example, Spec::Rails will use different - # classes for specs living in <tt>spec/models</tt>, <tt>spec/helpers</tt>, - # <tt>spec/views</tt> and <tt>spec/controllers</tt>. - # - # It is also possible to override autodiscovery of the behaviour class - # with an options Hash as the last argument: - # - # describe "name", :behaviour_type => :something_special do ... - # - # The reason for using different behaviour classes is to have - # different matcher methods available from within the <tt>describe</tt> - # block. - # - # See Spec::DSL::BehaviourFactory#add_behaviour_class for details about - # how to register special Spec::DSL::Behaviour implementations. - # - def describe(*args, &block) - raise ArgumentError if args.empty? - args << {} unless Hash === args.last - args.last[:spec_path] = caller(0)[1] - register_behaviour(Spec::DSL::BehaviourFactory.create(*args, &block)) - end - alias :context :describe - - def respond_to(*names) - Spec::Matchers::RespondTo.new(*names) - end - -private - - def register_behaviour(behaviour) - if behaviour.shared? - Spec::DSL::Behaviour.add_shared_behaviour(behaviour) - else - behaviour_runner.add_behaviour(behaviour) - end - end - - def behaviour_runner - # TODO: Figure out a better way to get this considered "covered" and keep this statement on multiple lines - unless $behaviour_runner; \ - $behaviour_runner = ::Spec::Runner::OptionParser.new.create_behaviour_runner(ARGV.dup, STDERR, STDOUT, false); \ - at_exit { $behaviour_runner.run(nil, false) }; \ - end - $behaviour_runner - end -end diff --git a/spec/lib/spec/runner/extensions/object.rb b/spec/lib/spec/runner/extensions/object.rb deleted file mode 100644 index 49745352f..000000000 --- a/spec/lib/spec/runner/extensions/object.rb +++ /dev/null @@ -1,32 +0,0 @@ -# The following copyright applies to Object#copy_instance_variables_from, -# which we borrowed from active_support. -# -# Copyright (c) 2004 David Heinemeier Hansson -# -# 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. -class Object - # From active_support - def copy_instance_variables_from(object, exclude = []) # :nodoc: - exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables - - instance_variables = object.instance_variables - exclude.map { |name| name.to_s } - instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) } - end -end diff --git a/spec/lib/spec/runner/formatter.rb b/spec/lib/spec/runner/formatter.rb deleted file mode 100644 index 17512d958..000000000 --- a/spec/lib/spec/runner/formatter.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'spec/runner/formatter/base_formatter' -require 'spec/runner/formatter/base_text_formatter' -require 'spec/runner/formatter/progress_bar_formatter' -require 'spec/runner/formatter/rdoc_formatter' -require 'spec/runner/formatter/specdoc_formatter' -require 'spec/runner/formatter/html_formatter' -require 'spec/runner/formatter/failing_examples_formatter' -require 'spec/runner/formatter/failing_behaviours_formatter' -require 'spec/runner/formatter/snippet_extractor' diff --git a/spec/lib/spec/runner/formatter/base_formatter.rb b/spec/lib/spec/runner/formatter/base_formatter.rb deleted file mode 100644 index 7cc43ef0e..000000000 --- a/spec/lib/spec/runner/formatter/base_formatter.rb +++ /dev/null @@ -1,76 +0,0 @@ -module Spec - module Runner - module Formatter - # Baseclass for formatters that implements all required methods as no-ops. - class BaseFormatter - def initialize(where) - @where = where - end - - # This method is invoked before any examples are run, right after - # they have all been collected. This can be useful for special - # formatters that need to provide progress on feedback (graphical ones) - # - # This method will only be invoked once, and the next one to be invoked - # is #add_behaviour - def start(example_count) - end - - # This method is invoked at the beginning of the execution of each behaviour. - # +name+ is the name of the behaviour and +first+ is true if it is the - # first behaviour - otherwise it's false. - # - # The next method to be invoked after this is #example_failed or #example_finished - def add_behaviour(name) - end - - # This method is invoked when an +example+ starts. - def example_started(example) - end - - # This method is invoked when an +example+ passes. - def example_passed(example) - end - - # This method is invoked when an +example+ fails, i.e. an exception occurred - # inside it (such as a failed should or other exception). +counter+ is the - # sequence number of the failure (starting at 1) and +failure+ is the associated - # Failure object. - def example_failed(example, counter, failure) - end - - # This method is invoked when an example is not yet implemented (i.e. has not - # been provided a block), or when an ExamplePendingError is raised. - # +name+ is the name of the example. - # +message+ is the message from the ExamplePendingError, if it exists, or the - # default value of "Not Yet Implemented" - def example_pending(behaviour_name, example_name, message) - end - - # This method is invoked after all of the examples have executed. The next method - # to be invoked after this one is #dump_failure (once for each failed example), - def start_dump - end - - # Dumps detailed information about an example failure. - # This method is invoked for each failed example after all examples have run. +counter+ is the sequence number - # of the associated example. +failure+ is a Failure object, which contains detailed - # information about the failure. - def dump_failure(counter, failure) - end - - # This method is invoked after the dumping of examples and failures. - def dump_summary(duration, example_count, failure_count, pending_count) - end - - # This gets invoked after the summary if option is set to do so. - def dump_pending - end - - # This method is invoked at the very end. Allows the formatter to clean up, like closing open streams. - def close - end - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/base_text_formatter.rb b/spec/lib/spec/runner/formatter/base_text_formatter.rb deleted file mode 100644 index c3cf01b76..000000000 --- a/spec/lib/spec/runner/formatter/base_text_formatter.rb +++ /dev/null @@ -1,130 +0,0 @@ -module Spec - module Runner - module Formatter - # Baseclass for text-based formatters. Can in fact be used for - # non-text based ones too - just ignore the +output+ constructor - # argument. - class BaseTextFormatter < BaseFormatter - attr_writer :dry_run - - # Creates a new instance that will write to +where+. If +where+ is a - # String, output will be written to the File with that name, otherwise - # +where+ is exected to be an IO (or an object that responds to #puts and #write). - def initialize(where) - super(where) - if where.is_a?(String) - @output = File.open(where, 'w') - elsif where == STDOUT - @output = Kernel - def @output.flush - STDOUT.flush - end - else - @output = where - end - @colour = false - @dry_run = false - @snippet_extractor = SnippetExtractor.new - @pending_examples = [] - end - - def example_pending(behaviour_name, example_name, message) - @pending_examples << ["#{behaviour_name} #{example_name}", message] - end - - def colour=(colour) - @colour = colour - begin ; require 'Win32/Console/ANSI' if @colour && PLATFORM =~ /win32/ ; rescue LoadError ; raise "You must gem install win32console to use colour on Windows" ; end - end - - def dump_failure(counter, failure) - @output.puts - @output.puts "#{counter.to_s})" - @output.puts colourise("#{failure.header}\n#{failure.exception.message}", failure) - @output.puts format_backtrace(failure.exception.backtrace) - @output.flush - end - - def colourise(s, failure) - if(failure.expectation_not_met?) - red(s) - elsif(failure.pending_fixed?) - blue(s) - else - magenta(s) - end - end - - def dump_summary(duration, example_count, failure_count, pending_count) - return if @dry_run - @output.puts - @output.puts "Finished in #{duration} seconds" - @output.puts - - summary = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}" - summary << ", #{pending_count} pending" if pending_count > 0 - - if failure_count == 0 - if pending_count > 0 - @output.puts yellow(summary) - else - @output.puts green(summary) - end - else - @output.puts red(summary) - end - @output.flush - dump_pending - end - - def dump_pending - unless @pending_examples.empty? - @output.puts - @output.puts "Pending:" - @pending_examples.each do |pending_example| - @output.puts "#{pending_example[0]} (#{pending_example[1]})" - end - end - @output.flush - end - - def close - if IO === @output - @output.close - end - end - - def format_backtrace(backtrace) - return "" if backtrace.nil? - backtrace.map { |line| backtrace_line(line) }.join("\n") - end - - protected - - def backtrace_line(line) - line.sub(/\A([^:]+:\d+)$/, '\\1:') - end - - def colour(text, colour_code) - return text unless @colour && output_to_tty? - "#{colour_code}#{text}\e[0m" - end - - def output_to_tty? - begin - @output == Kernel || @output.tty? - rescue NoMethodError - false - end - end - - def green(text); colour(text, "\e[32m"); end - def red(text); colour(text, "\e[31m"); end - def magenta(text); colour(text, "\e[35m"); end - def yellow(text); colour(text, "\e[33m"); end - def blue(text); colour(text, "\e[34m"); end - - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/failing_behaviours_formatter.rb b/spec/lib/spec/runner/formatter/failing_behaviours_formatter.rb deleted file mode 100644 index 2b3940fd3..000000000 --- a/spec/lib/spec/runner/formatter/failing_behaviours_formatter.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Spec - module Runner - module Formatter - class FailingBehavioursFormatter < BaseTextFormatter - def add_behaviour(behaviour_name) - if behaviour_name =~ /(.*) \(druby.*\)$/ - @behaviour_name = $1 - else - @behaviour_name = behaviour_name - end - end - - def example_failed(example, counter, failure) - unless @behaviour_name.nil? - @output.puts @behaviour_name - @behaviour_name = nil - @output.flush - end - end - - def dump_failure(counter, failure) - end - - def dump_summary(duration, example_count, failure_count, pending_count) - end - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/failing_examples_formatter.rb b/spec/lib/spec/runner/formatter/failing_examples_formatter.rb deleted file mode 100644 index 9728deaf0..000000000 --- a/spec/lib/spec/runner/formatter/failing_examples_formatter.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Spec - module Runner - module Formatter - class FailingExamplesFormatter < BaseTextFormatter - def add_behaviour(behaviour_name) - @behaviour_name = behaviour_name - end - - def example_failed(example, counter, failure) - @output.puts "#{@behaviour_name} #{example.description}" - @output.flush - end - - def dump_failure(counter, failure) - end - - def dump_summary(duration, example_count, failure_count, pending_count) - end - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/html_formatter.rb b/spec/lib/spec/runner/formatter/html_formatter.rb deleted file mode 100644 index d9c422e55..000000000 --- a/spec/lib/spec/runner/formatter/html_formatter.rb +++ /dev/null @@ -1,323 +0,0 @@ -require 'erb' - -module Spec - module Runner - module Formatter - class HtmlFormatter < BaseTextFormatter - include ERB::Util # for the #h method - - def initialize(output) - super - @current_behaviour_number = 0 - @current_example_number = 0 - end - - # The number of the currently running behaviour - def current_behaviour_number - @current_behaviour_number - end - - # The number of the currently running example (a global counter) - def current_example_number - @current_example_number - end - - def start(example_count) - @example_count = example_count - - @output.puts html_header - @output.puts report_header - @output.flush - end - - def add_behaviour(name) - @behaviour_red = false - @behaviour_red = false - @current_behaviour_number += 1 - unless current_behaviour_number == 1 - @output.puts " </dl>" - @output.puts "</div>" - end - @output.puts "<div class=\"behaviour\">" - @output.puts " <dl>" - @output.puts " <dt id=\"behaviour_#{current_behaviour_number}\">#{h(name)}</dt>" - @output.flush - end - - def start_dump - @output.puts " </dl>" - @output.puts "</div>" - @output.flush - end - - def example_started(example) - @current_example_number = example.number - end - - def example_passed(example) - move_progress - @output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{h(example.description)}</span></dd>" - @output.flush - end - - def example_failed(example, counter, failure) - extra = extra_failure_content(failure) - failure_style = failure.pending_fixed? ? 'pending_fixed' : 'failed' - @output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>" unless @header_red - @header_red = true - @output.puts " <script type=\"text/javascript\">makeRed('behaviour_#{current_behaviour_number}');</script>" unless @behaviour_red - @behaviour_red = true - move_progress - @output.puts " <dd class=\"spec #{failure_style}\">" - @output.puts " <span class=\"failed_spec_name\">#{h(example.description)}</span>" - @output.puts " <div class=\"failure\" id=\"failure_#{counter}\">" - @output.puts " <div class=\"message\"><pre>#{h(failure.exception.message)}</pre></div>" unless failure.exception.nil? - @output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil? - @output.puts extra unless extra == "" - @output.puts " </div>" - @output.puts " </dd>" - @output.flush - end - - def example_pending(behaviour_name, example_name, message) - @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red - @output.puts " <script type=\"text/javascript\">makeYellow('behaviour_#{current_behaviour_number}');</script>" unless @behaviour_red - move_progress - @output.puts " <dd class=\"spec not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example_name)}</span></dd>" - @output.flush - end - - # Override this method if you wish to output extra HTML for a failed spec. For example, you - # could output links to images or other files produced during the specs. - # - def extra_failure_content(failure) - " <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(failure.exception)}</code></pre>" - end - - def move_progress - percent_done = @example_count == 0 ? 100.0 : ((current_example_number + 1).to_f / @example_count.to_f * 1000).to_i / 10.0 - @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>" - @output.flush - end - - def dump_failure(counter, failure) - end - - def dump_summary(duration, example_count, failure_count, pending_count) - if @dry_run - totals = "This was a dry-run" - else - totals = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}" - totals << ", #{pending_count} pending" if pending_count > 0 - end - @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>" - @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>" - @output.puts "</div>" - @output.puts "</div>" - @output.puts "</body>" - @output.puts "</html>" - @output.flush - end - - def html_header - <<-EOF -<?xml version="1.0" encoding="iso-8859-1"?> -<!DOCTYPE html - PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <title>RSpec results</title> - <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> - <meta http-equiv="Expires" content="-1" /> - <meta http-equiv="Pragma" content="no-cache" /> - <style type="text/css"> - body { - margin: 0; - padding: 0; - background: #fff; - font-size: 80%; - } - </style> -</head> -<body> -EOF - end - - def report_header - <<-EOF -<div class="rspec-report"> - <script type="text/javascript"> - // <![CDATA[ -#{global_scripts} - // ]]> - </script> - <style type="text/css"> -#{global_styles} - </style> - -<div id="rspec-header"> - <h1>RSpec Results</h1> - - <div id="summary"> - <p id="totals"> </p> - <p id="duration"> </p> - </div> -</div> - -<div class="results"> -EOF - end - - def global_scripts - <<-EOF -function moveProgressBar(percentDone) { - document.getElementById("rspec-header").style.width = percentDone +"%"; -} -function makeRed(element_id) { - document.getElementById(element_id).style.background = '#C40D0D'; - document.getElementById(element_id).style.color = '#FFFFFF'; -} - -function makeYellow(element_id) { - if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D') - { - document.getElementById(element_id).style.background = '#FAF834'; - document.getElementById(element_id).style.color = '#000000'; - } - else - { - document.getElementById(element_id).style.background = '#FAF834'; - document.getElementById(element_id).style.color = '#000000'; - } -} -EOF - end - - def global_styles - <<-EOF -#rspec-header { - background: #65C400; color: #fff; -} - -.rspec-report h1 { - margin: 0px 10px 0px 10px; - padding: 10px; - font-family: "Lucida Grande", Helvetica, sans-serif; - font-size: 1.8em; -} - -#summary { - margin: 0; padding: 5px 10px; - font-family: "Lucida Grande", Helvetica, sans-serif; - text-align: right; - position: absolute; - top: 0px; - right: 0px; -} - -#summary p { - margin: 0 0 0 2px; -} - -#summary #totals { - font-size: 1.2em; -} - -.behaviour { - margin: 0 10px 5px; - background: #fff; -} - -dl { - margin: 0; padding: 0 0 5px; - font: normal 11px "Lucida Grande", Helvetica, sans-serif; -} - -dt { - padding: 3px; - background: #65C400; - color: #fff; - font-weight: bold; -} - -dd { - margin: 5px 0 5px 5px; - padding: 3px 3px 3px 18px; -} - -dd.spec.passed { - border-left: 5px solid #65C400; - border-bottom: 1px solid #65C400; - background: #DBFFB4; color: #3D7700; -} - -dd.spec.failed { - border-left: 5px solid #C20000; - border-bottom: 1px solid #C20000; - color: #C20000; background: #FFFBD3; -} - -dd.spec.not_implemented { - border-left: 5px solid #FAF834; - border-bottom: 1px solid #FAF834; - background: #FCFB98; color: #131313; -} - -dd.spec.pending_fixed { - border-left: 5px solid #0000C2; - border-bottom: 1px solid #0000C2; - color: #0000C2; background: #D3FBFF; -} - -.backtrace { - color: #000; - font-size: 12px; -} - -a { - color: #BE5C00; -} - -/* Ruby code, style similar to vibrant ink */ -.ruby { - font-size: 12px; - font-family: monospace; - color: white; - background-color: black; - padding: 0.1em 0 0.2em 0; -} - -.ruby .keyword { color: #FF6600; } -.ruby .constant { color: #339999; } -.ruby .attribute { color: white; } -.ruby .global { color: white; } -.ruby .module { color: white; } -.ruby .class { color: white; } -.ruby .string { color: #66FF00; } -.ruby .ident { color: white; } -.ruby .method { color: #FFCC00; } -.ruby .number { color: white; } -.ruby .char { color: white; } -.ruby .comment { color: #9933CC; } -.ruby .symbol { color: white; } -.ruby .regex { color: #44B4CC; } -.ruby .punct { color: white; } -.ruby .escape { color: white; } -.ruby .interp { color: white; } -.ruby .expr { color: white; } - -.ruby .offending { background-color: gray; } -.ruby .linenum { - width: 75px; - padding: 0.1em 1em 0.2em 0; - color: #000000; - background-color: #FFFBD3; -} -EOF - end - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/progress_bar_formatter.rb b/spec/lib/spec/runner/formatter/progress_bar_formatter.rb deleted file mode 100644 index 624f06e7c..000000000 --- a/spec/lib/spec/runner/formatter/progress_bar_formatter.rb +++ /dev/null @@ -1,31 +0,0 @@ -module Spec - module Runner - module Formatter - class ProgressBarFormatter < BaseTextFormatter - def add_behaviour(name) - end - - def example_failed(example, counter, failure) - @output.print colourise('F', failure) - @output.flush - end - - def example_passed(example) - @output.print green('.') - @output.flush - end - - def example_pending(behaviour_name, example_name, message) - super - @output.print yellow('P') - @output.flush - end - - def start_dump - @output.puts - @output.flush - end - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/rdoc_formatter.rb b/spec/lib/spec/runner/formatter/rdoc_formatter.rb deleted file mode 100644 index 0fd22ba6c..000000000 --- a/spec/lib/spec/runner/formatter/rdoc_formatter.rb +++ /dev/null @@ -1,24 +0,0 @@ -module Spec - module Runner - module Formatter - class RdocFormatter < BaseTextFormatter - def add_behaviour(name) - @output.puts "# #{name}" - end - - def example_passed(example) - @output.puts "# * #{example.description}" - @output.flush - end - - def example_failed(example, counter, failure) - @output.puts "# * #{example.description} [#{counter} - FAILED]" - end - - def example_pending(behaviour_name, example_name, message) - @output.puts "# * #{behaviour_name} #{example_name} [PENDING: #{message}]" - end - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/snippet_extractor.rb b/spec/lib/spec/runner/formatter/snippet_extractor.rb deleted file mode 100644 index 41119fe46..000000000 --- a/spec/lib/spec/runner/formatter/snippet_extractor.rb +++ /dev/null @@ -1,52 +0,0 @@ -module Spec - module Runner - module Formatter - # This class extracts code snippets by looking at the backtrace of the passed error - class SnippetExtractor #:nodoc: - class NullConverter; def convert(code, pre); code; end; end #:nodoc: - begin; require 'rubygems'; require 'syntax/convertors/html'; @@converter = Syntax::Convertors::HTML.for_syntax "ruby"; rescue LoadError => e; @@converter = NullConverter.new; end - - def snippet(error) - raw_code, line = snippet_for(error.backtrace[0]) - highlighted = @@converter.convert(raw_code, false) - highlighted << "\n<span class=\"comment\"># gem install syntax to get syntax highlighting</span>" if @@converter.is_a?(NullConverter) - post_process(highlighted, line) - end - - def snippet_for(error_line) - if error_line =~ /(.*):(\d+)/ - file = $1 - line = $2.to_i - [lines_around(file, line), line] - else - ["# Couldn't get snippet for #{error_line}", 1] - end - end - - def lines_around(file, line) - if File.file?(file) - lines = File.open(file).read.split("\n") - min = [0, line-3].max - max = [line+1, lines.length-1].min - selected_lines = [] - selected_lines.join("\n") - lines[min..max].join("\n") - else - "# Couldn't get snippet for #{file}" - end - end - - def post_process(highlighted, offending_line) - new_lines = [] - highlighted.split("\n").each_with_index do |line, i| - new_line = "<span class=\"linenum\">#{offending_line+i-2}</span>#{line}" - new_line = "<span class=\"offending\">#{new_line}</span>" if i == 2 - new_lines << new_line - end - new_lines.join("\n") - end - - end - end - end -end diff --git a/spec/lib/spec/runner/formatter/specdoc_formatter.rb b/spec/lib/spec/runner/formatter/specdoc_formatter.rb deleted file mode 100644 index ad794b238..000000000 --- a/spec/lib/spec/runner/formatter/specdoc_formatter.rb +++ /dev/null @@ -1,29 +0,0 @@ -module Spec - module Runner - module Formatter - class SpecdocFormatter < BaseTextFormatter - def add_behaviour(name) - @output.puts - @output.puts name - @output.flush - end - - def example_failed(example, counter, failure) - @output.puts failure.expectation_not_met? ? red("- #{example.description} (FAILED - #{counter})") : magenta("- #{example.description} (ERROR - #{counter})") - @output.flush - end - - def example_passed(example) - @output.puts green("- #{example.description}") - @output.flush - end - - def example_pending(behaviour_name, example_name, message) - super - @output.puts yellow("- #{example_name} (PENDING: #{message})") - @output.flush - end - end - end - end -end diff --git a/spec/lib/spec/runner/heckle_runner.rb b/spec/lib/spec/runner/heckle_runner.rb deleted file mode 100644 index b6de4ef73..000000000 --- a/spec/lib/spec/runner/heckle_runner.rb +++ /dev/null @@ -1,72 +0,0 @@ -begin - require 'rubygems' - require 'heckle' -rescue LoadError ; raise "You must gem install heckle to use --heckle" ; end - -module Spec - module Runner - # Creates a new Heckler configured to heckle all methods in the classes - # whose name matches +filter+ - class HeckleRunner - def initialize(filter, heckle_class=Heckler) - @filter = filter - @heckle_class = heckle_class - end - - # Runs all the contexts held by +behaviour_runner+ once for each of the - # methods in the matched classes. - def heckle_with(behaviour_runner) - if @filter =~ /(.*)[#\.](.*)/ - heckle_method($1, $2) - else - heckle_class_or_module(@filter) - end - end - - def heckle_method(class_name, method_name) - verify_constant(class_name) - heckle = @heckle_class.new(class_name, method_name, behaviour_runner) - heckle.validate - end - - def heckle_class_or_module(class_or_module_name) - verify_constant(class_or_module_name) - pattern = /^#{class_or_module_name}/ - classes = [] - ObjectSpace.each_object(Class) do |klass| - classes << klass if klass.name =~ pattern - end - - classes.each do |klass| - klass.instance_methods(false).each do |method_name| - heckle = @heckle_class.new(klass.name, method_name, behaviour_runner) - heckle.validate - end - end - end - - def verify_constant(name) - begin - # This is defined in Heckle - name.to_class - rescue - raise "Heckling failed - \"#{name}\" is not a known class or module" - end - end - end - - #Supports Heckle 1.2 and prior (earlier versions used Heckle::Base) - class Heckler < (Heckle.const_defined?(:Base) ? Heckle::Base : Heckle) - def initialize(klass_name, method_name, behaviour_runner) - super(klass_name, method_name) - @behaviour_runner = behaviour_runner - end - - def tests_pass? - paths = [] # We can pass an empty array of paths - our specs are already loaded. - failure_count = @behaviour_runner.run(paths, false) - failure_count == 0 - end - end - end -end diff --git a/spec/lib/spec/runner/heckle_runner_unsupported.rb b/spec/lib/spec/runner/heckle_runner_unsupported.rb deleted file mode 100644 index 02aa37953..000000000 --- a/spec/lib/spec/runner/heckle_runner_unsupported.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Spec - module Runner - # Dummy implementation for Windows that just fails (Heckle is not supported on Windows) - class HeckleRunner - def initialize(filter) - raise "Heckle not supported on Windows" - end - end - end -end diff --git a/spec/lib/spec/runner/option_parser.rb b/spec/lib/spec/runner/option_parser.rb deleted file mode 100644 index 1facb85a8..000000000 --- a/spec/lib/spec/runner/option_parser.rb +++ /dev/null @@ -1,227 +0,0 @@ -require 'optparse' -require 'stringio' - -module Spec - module Runner - class OptionParser - BUILT_IN_FORMATTERS = { - 'specdoc' => Formatter::SpecdocFormatter, - 's' => Formatter::SpecdocFormatter, - 'html' => Formatter::HtmlFormatter, - 'h' => Formatter::HtmlFormatter, - 'rdoc' => Formatter::RdocFormatter, - 'r' => Formatter::RdocFormatter, - 'progress' => Formatter::ProgressBarFormatter, - 'p' => Formatter::ProgressBarFormatter, - 'failing_examples' => Formatter::FailingExamplesFormatter, - 'e' => Formatter::FailingExamplesFormatter, - 'failing_behaviours' => Formatter::FailingBehavioursFormatter, - 'b' => Formatter::FailingBehavioursFormatter - } - - COMMAND_LINE = { - :diff => ["-D", "--diff [FORMAT]", "Show diff of objects that are expected to be equal when they are not", - "Builtin formats: unified|u|context|c", - "You can also specify a custom differ class", - "(in which case you should also specify --require)"], - :colour => ["-c", "--colour", "--color", "Show coloured (red/green) output"], - :example => ["-e", "--example [NAME|FILE_NAME]", "Execute example(s) with matching name(s). If the argument is", - "the path to an existing file (typically generated by a previous", - "run using --format failing_examples:file.txt), then the examples", - "on each line of thatfile will be executed. If the file is empty,", - "all examples will be run (as if --example was not specified).", - " ", - "If the argument is not an existing file, then it is treated as", - "an example name directly, causing RSpec to run just the example", - "matching that name"], - :specification => ["-s", "--specification [NAME]", "DEPRECATED - use -e instead", "(This will be removed when autotest works with -e)"], - :line => ["-l", "--line LINE_NUMBER", Integer, "Execute behaviout or specification at given line.", - "(does not work for dynamically generated specs)"], - :format => ["-f", "--format FORMAT[:WHERE]", "Specifies what format to use for output. Specify WHERE to tell", - "the formatter where to write the output. All built-in formats", - "expect WHERE to be a file name, and will write to STDOUT if it's", - "not specified. The --format option may be specified several times", - "if you want several outputs", - " ", - "Builtin formats: ", - "progress|p : Text progress", - "specdoc|s : Behaviour doc as text", - "rdoc|r : Behaviour doc as RDoc", - "html|h : A nice HTML report", - "failing_examples|e : Write all failing examples - input for --example", - "failing_behaviours|b : Write all failing behaviours - input for --example", - " ", - "FORMAT can also be the name of a custom formatter class", - "(in which case you should also specify --require to load it)"], - :require => ["-r", "--require FILE", "Require FILE before running specs", - "Useful for loading custom formatters or other extensions.", - "If this option is used it must come before the others"], - :backtrace => ["-b", "--backtrace", "Output full backtrace"], - :loadby => ["-L", "--loadby STRATEGY", "Specify the strategy by which spec files should be loaded.", - "STRATEGY can currently only be 'mtime' (File modification time)", - "By default, spec files are loaded in alphabetical order if --loadby", - "is not specified."], - :reverse => ["-R", "--reverse", "Run examples in reverse order"], - :timeout => ["-t", "--timeout FLOAT", "Interrupt and fail each example that doesn't complete in the", - "specified time"], - :heckle => ["-H", "--heckle CODE", "If all examples pass, this will mutate the classes and methods", - "identified by CODE little by little and run all the examples again", - "for each mutation. The intent is that for each mutation, at least", - "one example *should* fail, and RSpec will tell you if this is not the", - "case. CODE should be either Some::Module, Some::Class or", - "Some::Fabulous#method}"], - :dry_run => ["-d", "--dry-run", "Invokes formatters without executing the examples."], - :options_file => ["-O", "--options PATH", "Read options from a file"], - :generate_options => ["-G", "--generate-options PATH", "Generate an options file for --options"], - :runner => ["-U", "--runner RUNNER", "Use a custom BehaviourRunner."], - :drb => ["-X", "--drb", "Run examples via DRb. (For example against script/spec_server)"], - :version => ["-v", "--version", "Show version"], - :help => ["-h", "--help", "You're looking at it"] - } - - def initialize - @spec_parser = SpecParser.new - @file_factory = File - end - - def create_behaviour_runner(args, err, out, warn_if_no_files) - options = parse(args, err, out, warn_if_no_files) - # Some exit points in parse (--generate-options, --drb) don't return the options, - # but hand over control. In that case we don't want to continue. - return nil unless options.is_a?(Options) - options.configure - options.behaviour_runner - end - - def parse(args, err, out, warn_if_no_files) - options_file = nil - args_copy = args.dup - options = Options.new(err, out) - - opts = ::OptionParser.new do |opts| - opts.banner = "Usage: spec (FILE|DIRECTORY|GLOB)+ [options]" - opts.separator "" - - def opts.rspec_on(name, &block) - on(*COMMAND_LINE[name], &block) - end - - opts.rspec_on(:diff) {|diff| options.parse_diff(diff)} - - opts.rspec_on(:colour) {options.colour = true} - - opts.rspec_on(:example) {|example| options.parse_example(example)} - - opts.rspec_on(:specification) {|example| options.parse_example(example)} - - opts.rspec_on(:line) {|line_number| options.line_number = line_number.to_i} - - opts.rspec_on(:format) {|format| options.parse_format(format)} - - opts.rspec_on(:require) {|req| options.parse_require(req)} - - opts.rspec_on(:backtrace) {options.backtrace_tweaker = NoisyBacktraceTweaker.new} - - opts.rspec_on(:loadby) {|loadby| options.loadby = loadby} - - opts.rspec_on(:reverse) {options.reverse = true} - - opts.rspec_on(:timeout) {|timeout| options.timeout = timeout.to_f} - - opts.rspec_on(:heckle) {|heckle| options.parse_heckle(heckle)} - - opts.rspec_on(:dry_run) {options.dry_run = true} - - opts.rspec_on(:options_file) do |options_file| - return parse_options_file(options_file, out, err, args_copy, warn_if_no_files) - end - - opts.rspec_on(:generate_options) do |options_file| - options.parse_generate_options(options_file, args_copy, out) - end - - opts.rspec_on(:runner) do |runner| - options.runner_arg = runner - end - - opts.rspec_on(:drb) do - return parse_drb(args_copy, out, err, warn_if_no_files) - end - - opts.rspec_on(:version) {parse_version(out)} - - opts.on_tail(*COMMAND_LINE[:help]) {parse_help(opts, out)} - end - opts.parse!(args) - - if args.empty? && warn_if_no_files - err.puts "No files specified." - err.puts opts - exit(6) if err == $stderr - end - - if options.line_number - set_spec_from_line_number(options, args, err) - end - - if options.formatters.empty? - options.formatters << Formatter::ProgressBarFormatter.new(out) - end - - options - end - - def parse_options_file(options_file, out_stream, error_stream, args_copy, warn_if_no_files) - # Remove the --options option and the argument before writing to file - index = args_copy.index("-O") || args_copy.index("--options") - args_copy.delete_at(index) - args_copy.delete_at(index) - - new_args = args_copy + IO.readlines(options_file).map {|l| l.chomp.split " "}.flatten - return CommandLine.run(new_args, error_stream, out_stream, true, warn_if_no_files) - end - - def parse_drb(args_copy, out_stream, error_stream, warn_if_no_files) - # Remove the --drb option - index = args_copy.index("-X") || args_copy.index("--drb") - args_copy.delete_at(index) - - return DrbCommandLine.run(args_copy, error_stream, out_stream, true, warn_if_no_files) - end - - def parse_version(out_stream) - out_stream.puts ::Spec::VERSION::DESCRIPTION - exit if out_stream == $stdout - end - - def parse_help(opts, out_stream) - out_stream.puts opts - exit if out_stream == $stdout - end - - def set_spec_from_line_number(options, args, err) - if options.examples.empty? - if args.length == 1 - if @file_factory.file?(args[0]) - source = @file_factory.open(args[0]) - example = @spec_parser.spec_name_for(source, options.line_number) - options.parse_example(example) - elsif @file_factory.directory?(args[0]) - err.puts "You must specify one file, not a directory when using the --line option" - exit(1) if err == $stderr - else - err.puts "#{args[0]} does not exist" - exit(2) if err == $stderr - end - else - err.puts "Only one file can be specified when using the --line option: #{args.inspect}" - exit(3) if err == $stderr - end - else - err.puts "You cannot use both --line and --example" - exit(4) if err == $stderr - end - end - end - end -end diff --git a/spec/lib/spec/runner/options.rb b/spec/lib/spec/runner/options.rb deleted file mode 100644 index a940133eb..000000000 --- a/spec/lib/spec/runner/options.rb +++ /dev/null @@ -1,175 +0,0 @@ -module Spec - module Runner - class Options - BUILT_IN_FORMATTERS = { - 'specdoc' => Formatter::SpecdocFormatter, - 's' => Formatter::SpecdocFormatter, - 'html' => Formatter::HtmlFormatter, - 'h' => Formatter::HtmlFormatter, - 'rdoc' => Formatter::RdocFormatter, - 'r' => Formatter::RdocFormatter, - 'progress' => Formatter::ProgressBarFormatter, - 'p' => Formatter::ProgressBarFormatter, - 'failing_examples' => Formatter::FailingExamplesFormatter, - 'e' => Formatter::FailingExamplesFormatter, - 'failing_behaviours' => Formatter::FailingBehavioursFormatter, - 'b' => Formatter::FailingBehavioursFormatter - } - - attr_accessor( - :backtrace_tweaker, - :colour, - :context_lines, - :diff_format, - :differ_class, - :dry_run, - :examples, - :failure_file, - :formatters, - :generate, - :heckle_runner, - :line_number, - :loadby, - :reporter, - :reverse, - :timeout, - :verbose, - :runner_arg, - :behaviour_runner - ) - - def initialize(err, out) - @err, @out = err, out - @backtrace_tweaker = QuietBacktraceTweaker.new - @examples = [] - @formatters = [] - @colour = false - @dry_run = false - end - - def configure - configure_formatters - create_reporter - configure_differ - create_behaviour_runner - end - - def create_behaviour_runner - return nil if @generate - @behaviour_runner = if @runner_arg - klass_name, arg = split_at_colon(@runner_arg) - runner_type = load_class(klass_name, 'behaviour runner', '--runner') - runner_type.new(self, arg) - else - BehaviourRunner.new(self) - end - end - - def configure_formatters - @formatters.each do |formatter| - formatter.colour = @colour if formatter.respond_to?(:colour=) - formatter.dry_run = @dry_run if formatter.respond_to?(:dry_run=) - end - end - - def create_reporter - @reporter = Reporter.new(@formatters, @backtrace_tweaker) - end - - def configure_differ - if @differ_class - Spec::Expectations.differ = @differ_class.new(@diff_format, @context_lines, @colour) - end - end - - def parse_diff(format) - @context_lines = 3 - case format - when :context, 'context', 'c' - @diff_format = :context - when :unified, 'unified', 'u', '', nil - @diff_format = :unified - end - - if [:context,:unified].include? @diff_format - require 'spec/expectations/differs/default' - @differ_class = Spec::Expectations::Differs::Default - else - @diff_format = :custom - @differ_class = load_class(format, 'differ', '--diff') - end - end - - def parse_example(example) - if(File.file?(example)) - @examples = File.open(example).read.split("\n") - else - @examples = [example] - end - end - - def parse_format(format_arg) - format, where = split_at_colon(format_arg) - # This funky regexp checks whether we have a FILE_NAME or not - if where.nil? - raise "When using several --format options only one of them can be without a file" if @out_used - where = @out - @out_used = true - end - - formatter_type = BUILT_IN_FORMATTERS[format] || load_class(format, 'formatter', '--format') - @formatters << formatter_type.new(where) - end - - def parse_require(req) - req.split(",").each{|file| require file} - end - - def parse_heckle(heckle) - heckle_require = [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} ? 'spec/runner/heckle_runner_unsupported' : 'spec/runner/heckle_runner' - require heckle_require - @heckle_runner = HeckleRunner.new(heckle) - end - - def parse_generate_options(options_file, args_copy, out_stream) - # Remove the --generate-options option and the argument before writing to file - index = args_copy.index("-G") || args_copy.index("--generate-options") - args_copy.delete_at(index) - args_copy.delete_at(index) - File.open(options_file, 'w') do |io| - io.puts args_copy.join("\n") - end - out_stream.puts "\nOptions written to #{options_file}. You can now use these options with:" - out_stream.puts "spec --options #{options_file}" - @generate = true - end - - def split_at_colon(s) - if s =~ /([a-zA-Z_]+(?:::[a-zA-Z_]+)*):?(.*)/ - arg = $2 == "" ? nil : $2 - [$1, arg] - else - raise "Couldn't parse #{s.inspect}" - end - end - - def load_class(name, kind, option) - if name =~ /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ - arg = $2 == "" ? nil : $2 - [$1, arg] - else - m = "#{name.inspect} is not a valid class name" - @err.puts m - raise m - end - begin - eval(name, binding, __FILE__, __LINE__) - rescue NameError => e - @err.puts "Couldn't find #{kind} class #{name}" - @err.puts "Make sure the --require option is specified *before* #{option}" - if $_spec_spec ; raise e ; else exit(1) ; end - end - end - end - end -end diff --git a/spec/lib/spec/runner/reporter.rb b/spec/lib/spec/runner/reporter.rb deleted file mode 100644 index b1dc2a27a..000000000 --- a/spec/lib/spec/runner/reporter.rb +++ /dev/null @@ -1,125 +0,0 @@ -module Spec - module Runner - class Reporter - - def initialize(formatters, backtrace_tweaker) - @formatters = formatters - @backtrace_tweaker = backtrace_tweaker - clear! - end - - def add_behaviour(name) - @formatters.each{|f| f.add_behaviour(name)} - @behaviour_names << name - end - - def example_started(name) - @formatters.each{|f| f.example_started(name)} - end - - def example_finished(name, error=nil, failure_location=nil, not_implemented = false) - @example_names << name - - if not_implemented - example_pending(@behaviour_names.last, name) - elsif error.nil? - example_passed(name) - elsif Spec::DSL::ExamplePendingError === error - example_pending(@behaviour_names.last, name, error.message) - else - example_failed(name, error, failure_location) - end - end - - def start(number_of_examples) - clear! - @start_time = Time.new - @formatters.each{|f| f.start(number_of_examples)} - end - - def end - @end_time = Time.new - end - - # Dumps the summary and returns the total number of failures - def dump - @formatters.each{|f| f.start_dump} - dump_failures - @formatters.each do |f| - f.dump_summary(duration, @example_names.length, @failures.length, @pending_count) - f.close - end - @failures.length - end - - private - - def clear! - @behaviour_names = [] - @failures = [] - @pending_count = 0 - @example_names = [] - @start_time = nil - @end_time = nil - end - - def dump_failures - return if @failures.empty? - @failures.inject(1) do |index, failure| - @formatters.each{|f| f.dump_failure(index, failure)} - index + 1 - end - end - - def duration - return @end_time - @start_time unless (@end_time.nil? or @start_time.nil?) - return "0.0" - end - - def example_passed(name) - @formatters.each{|f| f.example_passed(name)} - end - - def example_failed(name, error, failure_location) - @backtrace_tweaker.tweak_backtrace(error, failure_location) - example_name = "#{@behaviour_names.last} #{name}" - failure = Failure.new(example_name, error) - @failures << failure - @formatters.each{|f| f.example_failed(name, @failures.length, failure)} - end - - def example_pending(behaviour_name, example_name, message="Not Yet Implemented") - @pending_count += 1 - @formatters.each{|f| f.example_pending(behaviour_name, example_name, message)} - end - - class Failure - attr_reader :exception - - def initialize(example_name, exception) - @example_name = example_name - @exception = exception - end - - def header - if expectation_not_met? - "'#{@example_name}' FAILED" - elsif pending_fixed? - "'#{@example_name}' FIXED" - else - "#{@exception.class.name} in '#{@example_name}'" - end - end - - def pending_fixed? - @exception.is_a?(Spec::DSL::PendingFixedError) - end - - def expectation_not_met? - @exception.is_a?(Spec::Expectations::ExpectationNotMetError) - end - - end - end - end -end diff --git a/spec/lib/spec/runner/spec_parser.rb b/spec/lib/spec/runner/spec_parser.rb deleted file mode 100644 index bc9170065..000000000 --- a/spec/lib/spec/runner/spec_parser.rb +++ /dev/null @@ -1,50 +0,0 @@ -module Spec - module Runner - # Parses a spec file and finds the nearest example for a given line number. - class SpecParser - def spec_name_for(io, line_number) - source = io.read - behaviour, behaviour_line = behaviour_at_line(source, line_number) - example, example_line = example_at_line(source, line_number) - if behaviour && example && (behaviour_line < example_line) - "#{behaviour} #{example}" - elsif behaviour - behaviour - else - nil - end - end - - protected - - def behaviour_at_line(source, line_number) - find_above(source, line_number, /^\s*(context|describe)\s+(.*)\s+do/) - end - - def example_at_line(source, line_number) - find_above(source, line_number, /^\s*(specify|it)\s+(.*)\s+do/) - end - - # Returns the context/describe or specify/it name and the line number - def find_above(source, line_number, pattern) - lines_above_reversed(source, line_number).each_with_index do |line, n| - return [parse_description($2), line_number-n] if line =~ pattern - end - nil - end - - def lines_above_reversed(source, line_number) - lines = source.split("\n") - lines[0...line_number].reverse - end - - def parse_description(str) - return str[1..-2] if str =~ /^['"].*['"]$/ - if matches = /^(.*)\s*,\s*['"](.*)['"]$/.match(str) - return ::Spec::DSL::Description.generate_description(matches[1], matches[2]) - end - return str - end - end - end -end diff --git a/spec/lib/spec/test_case_adapter.rb b/spec/lib/spec/test_case_adapter.rb deleted file mode 100755 index 992e098fd..000000000 --- a/spec/lib/spec/test_case_adapter.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'spec/expectations' -require 'spec/matchers' - -module Test - module Unit - class TestCase - include Spec::Matchers - end - end -end diff --git a/spec/lib/spec/translator.rb b/spec/lib/spec/translator.rb deleted file mode 100644 index c1e07eda4..000000000 --- a/spec/lib/spec/translator.rb +++ /dev/null @@ -1,114 +0,0 @@ -require 'fileutils' - -module Spec - class Translator - def translate(from, to) - from = File.expand_path(from) - to = File.expand_path(to) - if File.directory?(from) - translate_dir(from, to) - elsif(from =~ /\.rb$/) - translate_file(from, to) - end - end - - def translate_dir(from, to) - FileUtils.mkdir_p(to) unless File.directory?(to) - Dir["#{from}/*"].each do |sub_from| - path = sub_from[from.length+1..-1] - sub_to = File.join(to, path) - translate(sub_from, sub_to) - end - end - - def translate_file(from, to) - translation = "" - File.open(from) do |io| - io.each_line do |line| - translation << translate_line(line) - end - end - File.open(to, "w") do |io| - io.write(translation) - end - end - - def translate_line(line) - # Translate deprecated mock constraints - line.gsub!(/:any_args/, 'any_args') - line.gsub!(/:anything/, 'anything') - line.gsub!(/:boolean/, 'boolean') - line.gsub!(/:no_args/, 'no_args') - line.gsub!(/:numeric/, 'an_instance_of(Numeric)') - line.gsub!(/:string/, 'an_instance_of(String)') - - return line if line =~ /(should_not|should)_receive/ - - line.gsub!(/(^\s*)context([\s*|\(]['|"|A-Z])/, '\1describe\2') - line.gsub!(/(^\s*)specify([\s*|\(]['|"|A-Z])/, '\1it\2') - line.gsub!(/(^\s*)context_setup(\s*[do|\{])/, '\1before(:all)\2') - line.gsub!(/(^\s*)context_teardown(\s*[do|\{])/, '\1after(:all)\2') - line.gsub!(/(^\s*)setup(\s*[do|\{])/, '\1before(:each)\2') - line.gsub!(/(^\s*)teardown(\s*[do|\{])/, '\1after(:each)\2') - - if line =~ /(.*\.)(should_not|should)(?:_be)(?!_)(.*)/m - pre = $1 - should = $2 - post = $3 - be_or_equal = post =~ /(<|>)/ ? "be" : "equal" - - return "#{pre}#{should} #{be_or_equal}#{post}" - end - - if line =~ /(.*\.)(should_not|should)_(?!not)\s*(.*)/m - pre = $1 - should = $2 - post = $3 - - post.gsub!(/^raise/, 'raise_error') - post.gsub!(/^throw/, 'throw_symbol') - - unless standard_matcher?(post) - post = "be_#{post}" - end - - # Add parenthesis - post.gsub!(/^(\w+)\s+([\w|\.|\,|\(.*\)|\'|\"|\:|@| ]+)(\})/, '\1(\2)\3') # inside a block - post.gsub!(/^(redirect_to)\s+(.*)/, '\1(\2)') # redirect_to, which often has http: - post.gsub!(/^(\w+)\s+([\w|\.|\,|\(.*\)|\{.*\}|\'|\"|\:|@| ]+)/, '\1(\2)') - post.gsub!(/(\s+\))/, ')') - post.gsub!(/\)\}/, ') }') - post.gsub!(/^(\w+)\s+(\/.*\/)/, '\1(\2)') #regexps - line = "#{pre}#{should} #{post}" - end - - line - end - - def standard_matcher?(matcher) - patterns = [ - /^be/, - /^be_close/, - /^eql/, - /^equal/, - /^has/, - /^have/, - /^change/, - /^include/, - /^match/, - /^raise_error/, - /^respond_to/, - /^redirect_to/, - /^satisfy/, - /^throw_symbol/, - # Extra ones that we use in spec_helper - /^pass/, - /^fail/, - /^fail_with/, - ] - matched = patterns.detect{ |p| matcher =~ p } - !matched.nil? - end - - end -end diff --git a/spec/lib/spec/version.rb b/spec/lib/spec/version.rb deleted file mode 100644 index 5b1db9b37..000000000 --- a/spec/lib/spec/version.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Spec - module VERSION - unless defined? MAJOR - MAJOR = 1 - MINOR = 0 - TINY = 8 - RELEASE_CANDIDATE = nil - - # RANDOM_TOKEN: 0.510454315029681 - REV = "$LastChangedRevision: 2338 $".match(/LastChangedRevision: (\d+)/)[1] - - STRING = [MAJOR, MINOR, TINY].join('.') - TAG = "REL_#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('_')}".upcase.gsub(/\.|-/, '_') - FULL_VERSION = "#{[MAJOR, MINOR, TINY, RELEASE_CANDIDATE].compact.join('.')} (r#{REV})" - - NAME = "RSpec" - URL = "http://rspec.rubyforge.org/" - - DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}" - end - end -end - diff --git a/spec/lib/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb index bfa2a0c3c..941baa8de 100644 --- a/spec/lib/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb +++ b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb @@ -1,5 +1,5 @@ dir = File.expand_path(File.dirname(__FILE__)) -[ "#{dir}/../../lib", "#{dir}/../../../lib", "#{dir}/../../../test/lib"].each do |dir| +[ "#{dir}/../../lib", "#{dir}/../../test/lib"].each do |dir| fulldir = File.expand_path(dir) $LOAD_PATH.unshift(fulldir) unless $LOAD_PATH.include?(fulldir) end diff --git a/spec/plugins/mock_frameworks/flexmock.rb b/spec/plugins/mock_frameworks/flexmock.rb deleted file mode 100644 index 6875a5222..000000000 --- a/spec/plugins/mock_frameworks/flexmock.rb +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env ruby -# -# Created by Jim Weirich on 2007-04-10. -# Copyright (c) 2007. All rights reserved. - -require 'flexmock/rspec' - -module Spec - module Plugins - module MockFramework - include FlexMock::MockContainer - def setup_mocks_for_rspec - # No setup required - end - def verify_mocks_for_rspec - flexmock_verify - end - def teardown_mocks_for_rspec - flexmock_close - end - end - end -end diff --git a/spec/plugins/mock_frameworks/mocha.rb b/spec/plugins/mock_frameworks/mocha.rb deleted file mode 100644 index 69d11636c..000000000 --- a/spec/plugins/mock_frameworks/mocha.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'mocha/standalone' -require 'mocha/object' - -module Spec - module Plugins - module MockFramework - include Mocha::Standalone - def setup_mocks_for_rspec - mocha_setup - end - def verify_mocks_for_rspec - mocha_verify - end - def teardown_mocks_for_rspec - mocha_teardown - end - end - end -end diff --git a/spec/plugins/mock_frameworks/rr.rb b/spec/plugins/mock_frameworks/rr.rb deleted file mode 100644 index c019c18a1..000000000 --- a/spec/plugins/mock_frameworks/rr.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'rr' - -patterns = ::Spec::Runner::QuietBacktraceTweaker::IGNORE_PATTERNS -patterns.push(RR::Errors::BACKTRACE_IDENTIFIER) - -module Spec - module Plugins - module MockFramework - include RR::Extensions::InstanceMethods - def setup_mocks_for_rspec - RR::Space.instance.reset - end - def verify_mocks_for_rspec - RR::Space.instance.verify_doubles - end - def teardown_mocks_for_rspec - RR::Space.instance.reset - end - end - end -end diff --git a/spec/plugins/mock_frameworks/rspec.rb b/spec/plugins/mock_frameworks/rspec.rb deleted file mode 100644 index e606c3089..000000000 --- a/spec/plugins/mock_frameworks/rspec.rb +++ /dev/null @@ -1,18 +0,0 @@ -require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "spec", "mocks")) - -module Spec - module Plugins - module MockFramework - include Spec::Mocks::SpecMethods - def setup_mocks_for_rspec - $rspec_mocks ||= Spec::Mocks::Space.new - end - def verify_mocks_for_rspec - $rspec_mocks.verify_all - end - def teardown_mocks_for_rspec - $rspec_mocks.reset_all - end - end - end -end diff --git a/spec/lib/shared_behaviours/file_server_terminus.rb b/spec/shared_behaviours/file_server_terminus.rb index de08f29fc..de08f29fc 100644 --- a/spec/lib/shared_behaviours/file_server_terminus.rb +++ b/spec/shared_behaviours/file_server_terminus.rb diff --git a/spec/lib/shared_behaviours/file_serving.rb b/spec/shared_behaviours/file_serving.rb index b5ab6b0fd..b5ab6b0fd 100644 --- a/spec/lib/shared_behaviours/file_serving.rb +++ b/spec/shared_behaviours/file_serving.rb diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bfac9095f..c98709597 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,8 +1,14 @@ dir = File.expand_path(File.dirname(__FILE__)) -$LOAD_PATH.unshift("#{dir}/lib") + +$LOAD_PATH.unshift("#{dir}/") $LOAD_PATH.unshift("#{dir}/../lib") $LOAD_PATH.unshift("#{dir}/../test/lib") # Add the old test dir, so that we can still find our local mocha and spec +# include any gems in vendor/gems +Dir["#{dir}/../vendor/gems/**"].map do |path| + $LOAD_PATH.unshift(File.directory?(lib = "#{dir}/lib") ? lib : path) +end + require 'puppettest' require 'puppettest/runnable_test' require 'mocha' @@ -19,4 +25,5 @@ Spec::Runner.configure do |config| end end -require "#{dir}/lib/monkey_patches/add_confine_and_runnable_to_rspec_dsl" +# load any monkey-patches +Dir["#{dir}/monkey_patches/*.rb"].map { |file| require file } diff --git a/spec/unit/network/server.rb b/spec/unit/network/server.rb index 3e29807ad..846b5471d 100644 --- a/spec/unit/network/server.rb +++ b/spec/unit/network/server.rb @@ -212,7 +212,7 @@ describe Puppet::Network::Server, "when listening is on" do @server.listen end - it "should indicate that listening is turned off" do + it "should indicate that it is listening" do @server.should be_listening end @@ -235,14 +235,14 @@ describe Puppet::Network::Server, "when listening is being turned on" do @mock_http_server.stubs(:listen) end - it "should fetch an instance of an HTTP server when listening is turned on" do + it "should fetch an instance of an HTTP server" do mock_http_server_class = mock('http server class') mock_http_server_class.expects(:new).returns(@mock_http_server) @server.expects(:http_server_class).returns(mock_http_server_class) @server.listen end - it "should cause the HTTP server to listen when listening is turned on" do + it "should cause the HTTP server to listen" do @mock_http_server.expects(:listen) @server.expects(:http_server).returns(@mock_http_server) @server.listen @@ -261,7 +261,7 @@ describe Puppet::Network::Server, "when listening is being turned off" do @server.listen end - it "should cause the HTTP server to stop listening when listening is turned off" do + it "should cause the HTTP server to stop listening" do @mock_http_server.expects(:unlisten) @server.unlisten end diff --git a/spec/unit/util/settings.rb b/spec/unit/util/settings.rb index 540743d7e..a0cae936f 100755 --- a/spec/unit/util/settings.rb +++ b/spec/unit/util/settings.rb @@ -284,11 +284,6 @@ describe Puppet::Util::Settings, " when parsing its configuration" do lambda { @settings.parse(file) }.should_not raise_error end - it "should support an old parse method when per-executable configuration files still exist" do - # I'm not going to bother testing this method. - @settings.should respond_to(:old_parse) - end - it "should convert booleans in the configuration file into Ruby booleans" do text = "[main] one = true |