Created
April 3, 2011 18:16
-
-
Save h0rs3r4dish/900632 to your computer and use it in GitHub Desktop.
This is my <100-line spec framework, and some accompanying demo code that showcases all the features.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
module Spec | |
class AssertionError < Exception; end | |
class Should | |
def initialize(obj, invert=false) | |
@invert = invert | |
@self = obj | |
end | |
def ==(other) | |
test = (@self == other) | |
raise AssertionError unless (@invert ? !test : test) | |
end | |
def !=(other) | |
@invert = !@invert; self == other; @invert = !@invert | |
end | |
end | |
class MockObject | |
def initialize(vars) | |
@vars = vars | |
@calls = Hash.new | |
@accept_any_call = false | |
end | |
def method_missing(method, *a) | |
@calls[method] = true if @calls.key? method | |
return @vars[method] if @vars.key? method | |
return if @calls.key?(method) or @accept_any_call | |
raise "No method #{method}" | |
end | |
def should_receive(call) | |
@calls[call] = false | |
end | |
def received? | |
@calls.each_pair { |call,b| raise "Never got #{call}" if !b } | |
end | |
def as_null_object | |
@accept_any_call = true | |
self | |
end | |
end | |
class TestCase | |
attr_reader :subject | |
def initialize(const,block) | |
@const = const | |
@tests = @passed_tests = 0 | |
@start_time = Time.now | |
@exceptions = Array.new | |
instance_eval &block | |
end | |
def it(desc) | |
@subject = @const.new if @const.class == Class | |
@mocks = Array.new | |
@tests += 1 | |
begin | |
yield | |
@mocks.each { |m| m.received? } | |
print '.' | |
@passed_tests += 1 | |
rescue Exception => e | |
print 'F' | |
@exceptions.push e | |
end | |
end | |
def mock(properties) | |
(@mocks.push Spec::MockObject.new(properties)).last | |
end | |
def test_info | |
{ :tests => @tests, :passed => @passed_tests, | |
:time => (Time.now - @start_time), | |
:exceptions => @exceptions } | |
end | |
end | |
end | |
def describe(const, &block) | |
info = Spec::TestCase.new(const, block).test_info | |
puts "\n\n%d/%d tests passed in %0.5f seconds" % info.values[0..2] | |
puts "Problems:\n" + info[:exceptions].map { |e| | |
"- "+e.message+e.backtrace[0..6].select { |b| | |
!(b =~ /spec/) }.map { |b| "\n"+(" "*4)+b }.join | |
}.join("\n") unless info[:exceptions].empty? | |
end | |
class Object | |
def should; Spec::Should.new(self); end | |
def should_not; Spec::Should.new(self, true); end | |
end | |
ARGV.each { |file| require_relative file } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Walrus | |
def initialize | |
@full = false | |
end | |
def give_gift(obj) | |
if obj.edible then | |
@full = true | |
obj.digest! | |
else | |
obj.throw_away! | |
end | |
end | |
def full? | |
@full | |
end | |
end | |
describe Walrus do | |
it "starts its life hungry" do | |
subject.full?.should != true | |
end | |
it "eats food" do | |
milk = mock(:edible => true) | |
milk.should_receive :digest! | |
subject.give_gift(milk) | |
subject.full?.should == true | |
end | |
it "doesn't eat non-food" do | |
shoe = mock(:edible => false).as_null_object | |
subject.give_gift(shoe) | |
subject.full?.should_not == true | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment