diff options
author | francis <francis> | 2008-01-23 01:57:59 +0000 |
---|---|---|
committer | francis <francis> | 2008-01-23 01:57:59 +0000 |
commit | 6d1733e8a0b5f404326cfbd78b7139c87ecbffa3 (patch) | |
tree | c86561445b9ec5179020f8f56afb7b9174b390c5 /vendor/plugins/rspec/lib/spec/example | |
parent | 8bd6667c7885870af45522315f501a2b87340b1a (diff) |
Add files new to new rspec
Diffstat (limited to 'vendor/plugins/rspec/lib/spec/example')
10 files changed, 890 insertions, 0 deletions
diff --git a/vendor/plugins/rspec/lib/spec/example/configuration.rb b/vendor/plugins/rspec/lib/spec/example/configuration.rb new file mode 100644 index 000000000..674184727 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/configuration.rb @@ -0,0 +1,144 @@ +module Spec + module Example + class Configuration + # Chooses what mock framework to use. Example: + # + # Spec::Runner.configure do |config| + # config.mock_with :rspec, :mocha, :flexmock, or :rr + # end + # + # To use any other mock framework, you'll have to provide + # your own adapter. This is simply a module that responds to + # 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 example groups (<tt>describe</tt> blocks). + # + # config.include(My::Bottle, My::Cup) + # + # If you want to restrict the inclusion to a subset of all the example groups then + # specify this in a Hash as the last argument: + # + # config.include(My::Pony, My::Horse, :type => :farm) + # + # Only example groups that have that type will get the modules included: + # + # describe "Downtown", :type => :city do + # # Will *not* get My::Pony and My::Horse included + # end + # + # describe "Old Mac Donald", :type => :farm do + # # *Will* get My::Pony and My::Horse included + # end + # + def include(*args) + args << {} unless Hash === args.last + modules, options = args_and_options(*args) + required_example_group = get_type_from_options(options) + required_example_group = required_example_group.to_sym if required_example_group + modules.each do |mod| + ExampleGroupFactory.get(required_example_group).send(:include, mod) + end + end + + # Defines global predicate matchers. Example: + # + # config.predicate_matchers[:swim] = :can_swim? + # + # This makes it possible to say: + # + # person.should swim # passes if person.should_swim? returns true + # + def predicate_matchers + @predicate_matchers ||= {} + end + + # Prepends a global <tt>before</tt> block to all example groups. + # See #append_before for filtering semantics. + def prepend_before(*args, &proc) + scope, options = scope_and_options(*args) + example_group = ExampleGroupFactory.get( + get_type_from_options(options) + ) + example_group.prepend_before(scope, &proc) + end + # Appends a global <tt>before</tt> block to all example groups. + # + # If you want to restrict the block to a subset of all the example groups then + # specify this in a Hash as the last argument: + # + # config.prepend_before(:all, :type => :farm) + # + # or + # + # config.prepend_before(:type => :farm) + # + def append_before(*args, &proc) + scope, options = scope_and_options(*args) + example_group = ExampleGroupFactory.get( + get_type_from_options(options) + ) + example_group.append_before(scope, &proc) + end + alias_method :before, :append_before + + # Prepends a global <tt>after</tt> block to all example groups. + # See #append_before for filtering semantics. + def prepend_after(*args, &proc) + scope, options = scope_and_options(*args) + example_group = ExampleGroupFactory.get( + get_type_from_options(options) + ) + example_group.prepend_after(scope, &proc) + end + alias_method :after, :prepend_after + # Appends a global <tt>after</tt> block to all example groups. + # See #append_before for filtering semantics. + def append_after(*args, &proc) + scope, options = scope_and_options(*args) + example_group = ExampleGroupFactory.get( + get_type_from_options(options) + ) + example_group.append_after(scope, &proc) + end + + private + + def scope_and_options(*args) + args, options = args_and_options(*args) + scope = (args[0] || :each), options + end + + def get_type_from_options(options) + options[:type] || options[:behaviour_type] + end + + def mock_framework_path(framework_name) + File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "plugins", "mock_frameworks", framework_name)) + end + end + end +end diff --git a/vendor/plugins/rspec/lib/spec/example/errors.rb b/vendor/plugins/rspec/lib/spec/example/errors.rb new file mode 100644 index 000000000..c6cb22453 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/errors.rb @@ -0,0 +1,9 @@ +module Spec + module Example + class ExamplePendingError < StandardError + end + + class PendingExampleFixedError < StandardError + end + end +end diff --git a/vendor/plugins/rspec/lib/spec/example/example_group.rb b/vendor/plugins/rspec/lib/spec/example/example_group.rb new file mode 100644 index 000000000..d6e156f93 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/example_group.rb @@ -0,0 +1,16 @@ +module Spec + module Example + # The superclass for all regular RSpec examples. + class ExampleGroup + extend Spec::Example::ExampleGroupMethods + include Spec::Example::ExampleMethods + + def initialize(defined_description, &implementation) + @_defined_description = defined_description + @_implementation = implementation + end + end + end +end + +Spec::ExampleGroup = Spec::Example::ExampleGroup diff --git a/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb b/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb new file mode 100644 index 000000000..0414a3b96 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/example_group_factory.rb @@ -0,0 +1,62 @@ +module Spec + module Example + class ExampleGroupFactory + class << self + def reset + @example_group_types = nil + default(ExampleGroup) + end + + # Registers an example group class +klass+ with the symbol + # +type+. For example: + # + # Spec::Example::ExampleGroupFactory.register(:farm, Spec::Farm::Example::FarmExampleGroup) + # + # This will cause Main#describe from a file living in + # <tt>spec/farm</tt> to create example group instances of type + # Spec::Farm::Example::FarmExampleGroup. + def register(id, example_group_class) + @example_group_types[id] = example_group_class + end + + # Sets the default ExampleGroup class + def default(example_group_class) + old = @example_group_types + @example_group_types = Hash.new(example_group_class) + @example_group_types.merge(old) if old + end + + def get(id=nil) + if @example_group_types.values.include?(id) + id + else + @example_group_types[id] + end + end + + def create_example_group(*args, &block) + opts = Hash === args.last ? args.last : {} + if opts[:shared] + SharedExampleGroup.new(*args, &block) + else + superclass = determine_superclass(opts) + superclass.describe(*args, &block) + end + end + + protected + + def determine_superclass(opts) + id = if opts[:type] + opts[:type] + elsif opts[:spec_path] =~ /spec(\\|\/)(#{@example_group_types.keys.join('|')})/ + $2 == '' ? nil : $2.to_sym + end + get(id) + end + + end + self.reset + end + end +end diff --git a/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb b/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb new file mode 100644 index 000000000..8f73a9853 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/example_group_methods.rb @@ -0,0 +1,418 @@ +module Spec + module Example + + module ExampleGroupMethods + class << self + def description_text(*args) + args.inject("") do |result, arg| + result << " " unless (result == "" || arg.to_s =~ /^(\s|\.|#)/) + result << arg.to_s + end + end + end + + attr_reader :description_text, :description_args, :description_options, :spec_path + + def inherited(klass) + super + klass.register + end + + # Makes the describe/it syntax available from a class. For example: + # + # class StackSpec < Spec::ExampleGroup + # describe Stack, "with no elements" + # + # before + # @stack = Stack.new + # end + # + # it "should raise on pop" do + # lambda{ @stack.pop }.should raise_error + # end + # end + # + def describe(*args, &example_group_block) + if example_group_block + self.subclass("Subclass") do + describe(*args) + module_eval(&example_group_block) + end + else + set_description(*args) + before_eval + self + end + end + + # Use this to pull in examples from shared example groups. + # See Spec::Runner for information about shared example groups. + def it_should_behave_like(shared_example_group) + case shared_example_group + when SharedExampleGroup + include shared_example_group + else + example_group = SharedExampleGroup.find_shared_example_group(shared_example_group) + unless example_group + raise RuntimeError.new("Shared Example Group '#{shared_example_group}' can not be found") + end + include(example_group) + end + end + + # :call-seq: + # predicate_matchers[matcher_name] = method_on_object + # predicate_matchers[matcher_name] = [method1_on_object, method2_on_object] + # + # Dynamically generates a custom matcher that will match + # a predicate on your class. RSpec provides a couple of these + # out of the box: + # + # exist (or state expectations) + # File.should exist("path/to/file") + # + # an_instance_of (for mock argument constraints) + # mock.should_receive(:message).with(an_instance_of(String)) + # + # == Examples + # + # class Fish + # def can_swim? + # true + # end + # end + # + # describe Fish do + # predicate_matchers[:swim] = :can_swim? + # it "should swim" do + # Fish.new.should swim + # end + # end + def predicate_matchers + @predicate_matchers ||= {:an_instance_of => :is_a?} + end + + # Creates an instance of Spec::Example::Example and adds + # it to a collection of examples of the current example group. + def it(description=nil, &implementation) + e = new(description, &implementation) + example_objects << e + e + end + + alias_method :specify, :it + + # Use this to temporarily disable an example. + def xit(description=nil, opts={}, &block) + Kernel.warn("Example disabled: #{description}") + end + + def run + examples = examples_to_run + return true if examples.empty? + reporter.add_example_group(self) + return dry_run(examples) if dry_run? + + plugin_mock_framework + define_methods_from_predicate_matchers + + success, before_all_instance_variables = run_before_all + success, after_all_instance_variables = execute_examples(success, before_all_instance_variables, examples) + success = run_after_all(success, after_all_instance_variables) + end + + def description + result = ExampleGroupMethods.description_text(*description_parts) + if result.nil? || result == "" + return to_s + else + result + end + end + + def described_type + description_parts.find {|part| part.is_a?(Module)} + end + + def description_parts #:nodoc: + parts = [] + execute_in_class_hierarchy do |example_group| + parts << example_group.description_args + end + parts.flatten.compact + end + + def set_description(*args) + args, options = args_and_options(*args) + @description_args = args + @description_options = options + @description_text = ExampleGroupMethods.description_text(*args) + @spec_path = File.expand_path(options[:spec_path]) if options[:spec_path] + if described_type.class == Module + include described_type + end + self + end + + def examples #:nodoc: + examples = example_objects.dup + add_method_examples(examples) + rspec_options.reverse ? examples.reverse : examples + end + + def number_of_examples #:nodoc: + examples.length + end + + # Registers a block to be executed before each example. + # This method prepends +block+ to existing before blocks. + def prepend_before(*args, &block) + scope, options = scope_and_options(*args) + parts = before_parts_from_scope(scope) + parts.unshift(block) + end + + # Registers a block to be executed before each example. + # This method appends +block+ to existing before blocks. + def append_before(*args, &block) + scope, options = scope_and_options(*args) + parts = before_parts_from_scope(scope) + parts << block + end + alias_method :before, :append_before + + # Registers a block to be executed after each example. + # This method prepends +block+ to existing after blocks. + def prepend_after(*args, &block) + scope, options = scope_and_options(*args) + parts = after_parts_from_scope(scope) + parts.unshift(block) + end + alias_method :after, :prepend_after + + # Registers a block to be executed after each example. + # This method appends +block+ to existing after blocks. + def append_after(*args, &block) + scope, options = scope_and_options(*args) + parts = after_parts_from_scope(scope) + parts << block + end + + def remove_after(scope, &block) + after_each_parts.delete(block) + end + + # Deprecated. Use before(:each) + def setup(&block) + before(:each, &block) + end + + # Deprecated. Use after(:each) + def teardown(&block) + after(:each, &block) + end + + def before_all_parts # :nodoc: + @before_all_parts ||= [] + end + + def after_all_parts # :nodoc: + @after_all_parts ||= [] + end + + def before_each_parts # :nodoc: + @before_each_parts ||= [] + end + + def after_each_parts # :nodoc: + @after_each_parts ||= [] + end + + # Only used from RSpec's own examples + def reset # :nodoc: + @before_all_parts = nil + @after_all_parts = nil + @before_each_parts = nil + @after_each_parts = nil + end + + def register + rspec_options.add_example_group self + end + + def unregister #:nodoc: + rspec_options.remove_example_group self + end + + def run_before_each(example) + execute_in_class_hierarchy do |example_group| + example.eval_each_fail_fast(example_group.before_each_parts) + end + end + + def run_after_each(example) + execute_in_class_hierarchy(:superclass_first) do |example_group| + example.eval_each_fail_slow(example_group.after_each_parts) + end + end + + private + def dry_run(examples) + examples.each do |example| + rspec_options.reporter.example_started(example) + rspec_options.reporter.example_finished(example) + end + return true + end + + def run_before_all + before_all = new("before(:all)") + begin + execute_in_class_hierarchy do |example_group| + before_all.eval_each_fail_fast(example_group.before_all_parts) + end + return [true, before_all.instance_variable_hash] + rescue Exception => e + reporter.failure(before_all, e) + return [false, before_all.instance_variable_hash] + end + end + + def execute_examples(success, instance_variables, examples) + return [success, instance_variables] unless success + + after_all_instance_variables = instance_variables + examples.each do |example_group_instance| + success &= example_group_instance.execute(rspec_options, instance_variables) + after_all_instance_variables = example_group_instance.instance_variable_hash + end + return [success, after_all_instance_variables] + end + + def run_after_all(success, instance_variables) + after_all = new("after(:all)") + after_all.set_instance_variables_from_hash(instance_variables) + execute_in_class_hierarchy(:superclass_first) do |example_group| + after_all.eval_each_fail_slow(example_group.after_all_parts) + end + return success + rescue Exception => e + reporter.failure(after_all, e) + return false + end + + def examples_to_run + all_examples = examples + return all_examples unless specified_examples? + all_examples.reject do |example| + matcher = ExampleMatcher.new(description.to_s, example.description) + !matcher.matches?(specified_examples) + end + end + + def specified_examples? + specified_examples && !specified_examples.empty? + end + + def specified_examples + rspec_options.examples + end + + def reporter + rspec_options.reporter + end + + def dry_run? + rspec_options.dry_run + end + + def example_objects + @example_objects ||= [] + end + + def execute_in_class_hierarchy(superclass_last=false) + classes = [] + current_class = self + while is_example_group?(current_class) + superclass_last ? classes << current_class : classes.unshift(current_class) + current_class = current_class.superclass + end + superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods) + + classes.each do |example_group| + yield example_group + end + end + + def is_example_group?(klass) + Module === klass && klass.kind_of?(ExampleGroupMethods) + end + + def plugin_mock_framework + case mock_framework = Spec::Runner.configuration.mock_framework + when Module + include mock_framework + else + require Spec::Runner.configuration.mock_framework + include Spec::Plugins::MockFramework + end + end + + def define_methods_from_predicate_matchers # :nodoc: + all_predicate_matchers = predicate_matchers.merge( + Spec::Runner.configuration.predicate_matchers + ) + all_predicate_matchers.each_pair do |matcher_method, method_on_object| + define_method matcher_method do |*args| + eval("be_#{method_on_object.to_s.gsub('?','')}(*args)") + end + end + end + + def scope_and_options(*args) + args, options = args_and_options(*args) + scope = (args[0] || :each), options + end + + def before_parts_from_scope(scope) + case scope + when :each; before_each_parts + when :all; before_all_parts + end + end + + def after_parts_from_scope(scope) + case scope + when :each; after_each_parts + when :all; after_all_parts + end + end + + def before_eval + end + + def add_method_examples(examples) + instance_methods.sort.each do |method_name| + if example_method?(method_name) + examples << new(method_name) do + __send__(method_name) + end + end + end + end + + def example_method?(method_name) + should_method?(method_name) + end + + def should_method?(method_name) + !(method_name =~ /^should(_not)?$/) && + method_name =~ /^should/ && ( + instance_method(method_name).arity == 0 || + instance_method(method_name).arity == -1 + ) + end + end + + end +end diff --git a/vendor/plugins/rspec/lib/spec/example/example_matcher.rb b/vendor/plugins/rspec/lib/spec/example/example_matcher.rb new file mode 100644 index 000000000..435eabf52 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/example_matcher.rb @@ -0,0 +1,42 @@ +module Spec + module Example + class ExampleMatcher + def initialize(example_group_description, example_name) + @example_group_description = example_group_description + @example_name = example_name + end + + def matches?(specified_examples) + specified_examples.each do |specified_example| + return true if matches_literal_example?(specified_example) || matches_example_not_considering_modules?(specified_example) + end + false + end + + protected + def matches_literal_example?(specified_example) + specified_example =~ /(^#{example_group_regex} #{example_regexp}$|^#{example_group_regex}$|^#{example_group_with_before_all_regexp}$|^#{example_regexp}$)/ + end + + def matches_example_not_considering_modules?(specified_example) + specified_example =~ /(^#{example_group_regex_not_considering_modules} #{example_regexp}$|^#{example_group_regex_not_considering_modules}$|^#{example_regexp}$)/ + end + + def example_group_regex + Regexp.escape(@example_group_description) + end + + def example_group_with_before_all_regexp + Regexp.escape("#{@example_group_description} before(:all)") + end + + def example_group_regex_not_considering_modules + Regexp.escape(@example_group_description.split('::').last) + end + + def example_regexp + Regexp.escape(@example_name) + end + end + end +end diff --git a/vendor/plugins/rspec/lib/spec/example/example_methods.rb b/vendor/plugins/rspec/lib/spec/example/example_methods.rb new file mode 100644 index 000000000..6dd4c9c72 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/example_methods.rb @@ -0,0 +1,102 @@ +module Spec + module Example + module ExampleMethods + extend ExampleGroupMethods + extend ModuleReopeningFix + + PENDING_EXAMPLE_BLOCK = lambda { + raise Spec::Example::ExamplePendingError.new("Not Yet Implemented") + } + + def execute(options, instance_variables) + options.reporter.example_started(self) + set_instance_variables_from_hash(instance_variables) + + execution_error = nil + Timeout.timeout(options.timeout) do + begin + before_example + run_with_description_capturing + rescue Exception => e + execution_error ||= e + end + begin + after_example + rescue Exception => e + execution_error ||= e + end + end + + options.reporter.example_finished(self, execution_error) + success = execution_error.nil? || ExamplePendingError === execution_error + end + + def instance_variable_hash + instance_variables.inject({}) do |variable_hash, variable_name| + variable_hash[variable_name] = instance_variable_get(variable_name) + variable_hash + end + end + + def violated(message="") + raise Spec::Expectations::ExpectationNotMetError.new(message) + end + + def eval_each_fail_fast(procs) #:nodoc: + procs.each do |proc| + instance_eval(&proc) + end + end + + def eval_each_fail_slow(procs) #:nodoc: + first_exception = nil + procs.each do |proc| + begin + instance_eval(&proc) + rescue Exception => e + first_exception ||= e + end + end + raise first_exception if first_exception + end + + def description + @_defined_description || @_matcher_description || "NO NAME" + end + + def set_instance_variables_from_hash(ivars) + ivars.each do |variable_name, value| + # Ruby 1.9 requires variable.to_s on the next line + unless ['@_implementation', '@_defined_description', '@_matcher_description', '@method_name'].include?(variable_name.to_s) + instance_variable_set variable_name, value + end + end + end + + def run_with_description_capturing + begin + return instance_eval(&(@_implementation || PENDING_EXAMPLE_BLOCK)) + ensure + @_matcher_description = Spec::Matchers.generated_description + Spec::Matchers.clear_generated_description + end + end + + protected + include Matchers + include Pending + + def before_example + setup_mocks_for_rspec + self.class.run_before_each(self) + end + + def after_example + self.class.run_after_each(self) + verify_mocks_for_rspec + ensure + teardown_mocks_for_rspec + end + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/example/module_reopening_fix.rb b/vendor/plugins/rspec/lib/spec/example/module_reopening_fix.rb new file mode 100644 index 000000000..dc01dd666 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/module_reopening_fix.rb @@ -0,0 +1,21 @@ +module Spec + module Example + # This is a fix for ...Something in Ruby 1.8.6??... (Someone fill in here please - Aslak) + module ModuleReopeningFix + def child_modules + @child_modules ||= [] + end + + def included(mod) + child_modules << mod + end + + def include(mod) + super + child_modules.each do |child_module| + child_module.__send__(:include, mod) + end + end + end + end +end
\ No newline at end of file diff --git a/vendor/plugins/rspec/lib/spec/example/pending.rb b/vendor/plugins/rspec/lib/spec/example/pending.rb new file mode 100644 index 000000000..b1f27c866 --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/pending.rb @@ -0,0 +1,18 @@ +module Spec + module Example + module Pending + def pending(message = "TODO") + if block_given? + begin + yield + rescue Exception => e + raise Spec::Example::ExamplePendingError.new(message) + end + raise Spec::Example::PendingExampleFixedError.new("Expected pending '#{message}' to fail. No Error was raised.") + else + raise Spec::Example::ExamplePendingError.new(message) + end + end + end + end +end diff --git a/vendor/plugins/rspec/lib/spec/example/shared_example_group.rb b/vendor/plugins/rspec/lib/spec/example/shared_example_group.rb new file mode 100644 index 000000000..a6fd6211c --- /dev/null +++ b/vendor/plugins/rspec/lib/spec/example/shared_example_group.rb @@ -0,0 +1,58 @@ +module Spec + module Example + class SharedExampleGroup < Module + class << self + def add_shared_example_group(new_example_group) + guard_against_redefining_existing_example_group(new_example_group) + shared_example_groups << new_example_group + end + + def find_shared_example_group(example_group_description) + shared_example_groups.find do |b| + b.description == example_group_description + end + end + + def shared_example_groups + # TODO - this needs to be global, or at least accessible from + # from subclasses of Example in a centralized place. I'm not loving + # this as a solution, but it works for now. + $shared_example_groups ||= [] + end + + private + def guard_against_redefining_existing_example_group(new_example_group) + existing_example_group = find_shared_example_group(new_example_group.description) + return unless existing_example_group + return if new_example_group.equal?(existing_example_group) + return if spec_path(new_example_group) == spec_path(existing_example_group) + raise ArgumentError.new("Shared Example '#{existing_example_group.description}' already exists") + end + + def spec_path(example_group) + File.expand_path(example_group.spec_path) + end + end + include ExampleGroupMethods + public :include + + def initialize(*args, &example_group_block) + describe(*args) + @example_group_block = example_group_block + self.class.add_shared_example_group(self) + end + + def included(mod) # :nodoc: + mod.module_eval(&@example_group_block) + end + + def execute_in_class_hierarchy(superclass_last=false) + classes = [self] + superclass_last ? classes << ExampleMethods : classes.unshift(ExampleMethods) + classes.each do |example_group| + yield example_group + end + end + end + end +end |