Skip to content

Commit

Permalink
Initial code.
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviershay committed Sep 3, 2011
1 parent 28a4e4c commit a212d5d
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
rspec-fire-0.1.gem
3 changes: 3 additions & 0 deletions Gemfile
@@ -0,0 +1,3 @@
source :rubygems

gemspec
26 changes: 26 additions & 0 deletions 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!
2 changes: 2 additions & 0 deletions HISTORY
@@ -0,0 +1,2 @@
0.1 - 3 September 2011
* Initial release
7 changes: 7 additions & 0 deletions 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
81 changes: 81 additions & 0 deletions 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
23 changes: 23 additions & 0 deletions 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
13 changes: 13 additions & 0 deletions 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

0 comments on commit a212d5d

Please sign in to comment.