Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial code.

  • Loading branch information...
commit a212d5d229445513686d02c1bc4836dbc36e1aa6 1 parent 28a4e4c
@xaviershay authored
View
1  .gitignore
@@ -0,0 +1 @@
+rspec-fire-0.1.gem
View
3  Gemfile
@@ -0,0 +1,3 @@
+source :rubygems
+
+gemspec
View
26 Gemfile.lock
@@ -0,0 +1,26 @@
+PATH
+ remote: .
+ specs:
+ rspec-fire (0.1)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ diff-lcs (1.1.3)
+ rake (0.9.2)
+ rspec (2.6.0)
+ rspec-core (~> 2.6.0)
+ rspec-expectations (~> 2.6.0)
+ rspec-mocks (~> 2.6.0)
+ rspec-core (2.6.4)
+ rspec-expectations (2.6.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.6.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ rake
+ rspec (~> 2.5)
+ rspec-fire!
View
2  HISTORY
@@ -0,0 +1,2 @@
+0.1 - 3 September 2011
+ * Initial release
View
7 Rakefile
@@ -0,0 +1,7 @@
+require 'rspec/core/rake_task'
+RSpec::Core::RakeTask.new(:spec) do |opts|
+ opts.rspec_opts = '--format documentation'
+end
+
+desc 'Default: run specs.'
+task :default => :spec
View
81 lib/rspec/fire.rb
@@ -0,0 +1,81 @@
+require 'rspec/mocks'
+
+module RSpec
+ module Fire
+ class FireDouble < RSpec::Mocks::Mock
+ def initialize(doubled_class, *args)
+ args << {} unless Hash === args.last
+
+ @__doubled_class_name = doubled_class
+ @__checked_methods = :public_instance_methods
+
+ # __declared_as copied from rspec/mocks definition of `double`
+ args.last[:__declared_as] = 'FireDouble'
+ super(doubled_class, *args)
+ end
+
+ def should_receive(method_name)
+ ensure_implemented(method_name)
+ super
+ end
+
+ def should_not_receive(method_name)
+ ensure_implemented(method_name)
+ super
+ end
+
+ def stub(method_name)
+ ensure_implemented(method_name)
+ super
+ end
+
+ protected
+
+ def ensure_implemented(*method_names)
+ if recursive_const_defined?(Object, @__doubled_class_name)
+ recursive_const_get(Object, @__doubled_class_name).
+ should implement(method_names, @__checked_methods)
+ end
+ end
+
+ def recursive_const_get object, name
+ name.split('::').inject(Object) {|klass,name| klass.const_get name }
+ end
+
+ def recursive_const_defined? object, name
+ !!name.split('::').inject(Object) {|klass,name|
+ if klass && klass.const_defined?(name)
+ klass.const_get name
+ end
+ }
+ end
+
+ def implement(expected_methods, checked_methods)
+ RSpec::Matchers::Matcher.new(:implement, expected_methods, checked_methods) do |expected_methods, checked_methods|
+ unimplemented_methods = lambda {|doubled_class|
+ implemented_methods = doubled_class.send(checked_methods)
+ expected_methods - implemented_methods
+ }
+
+ match do |doubled_class|
+ unimplemented_methods[ doubled_class ].empty?
+ end
+
+ failure_message_for_should do |doubled_class|
+ implemented_methods = Object.public_methods - doubled_class.send(checked_methods)
+ "%s does not implement:\n%s" % [
+ doubled_class,
+ unimplemented_methods[ doubled_class ].sort.map {|x|
+ " #{x}"
+ }.join("\n")
+ ]
+ end
+ end
+ end
+ end
+
+ def fire_double(*args)
+ FireDouble.new(*args)
+ end
+ end
+end
View
23 rspec-fire.gemspec
@@ -0,0 +1,23 @@
+Gem::Specification.new do |s|
+ s.name = 'rspec-fire'
+ s.version = '0.1'
+ s.summary = 'More resilient test doubles for RSpec.'
+ s.platform = Gem::Platform::RUBY
+ s.authors = ["Xavier Shay"]
+ s.email = ["hello@xaviershay.com"]
+ s.homepage = "http://github.com/xaviershay/rspec-fire"
+ s.has_rdoc = false
+
+ s.require_path = 'lib'
+ s.files = Dir.glob("{spec,lib}/**/*.rb") +
+ %w(
+ Gemfile
+ README.md
+ HISTORY
+ Rakefile
+ rspec-fire.gemspec
+ )
+
+ s.add_development_dependency 'rake'
+ s.add_development_dependency 'rspec', '~> 2.5'
+end
View
13 spec/spec_helper.rb
@@ -0,0 +1,13 @@
+require 'rspec/fire'
+
+RSpec.configure do |config|
+ config.include(RSpec::Fire)
+
+ def fail_matching(*messages)
+ raise_error(RSpec::Expectations::ExpectationNotMetError) {|error|
+ messages.all? {|message|
+ error.message =~ /#{Regexp.escape(message)}/
+ }
+ }
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.