MacSpec 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +20 -0
- data/Rakefile +53 -0
- data/lib/mac_spec.rb +59 -0
- data/lib/mac_spec/matcher_system.rb +19 -0
- data/lib/mac_spec/matcher_system/built_in/change_expectations.rb +36 -0
- data/lib/mac_spec/matcher_system/built_in/enumerable_expectations.rb +43 -0
- data/lib/mac_spec/matcher_system/built_in/error_expectations.rb +68 -0
- data/lib/mac_spec/matcher_system/built_in/operator_expectations.rb +45 -0
- data/lib/mac_spec/matcher_system/built_in/truth_expectations.rb +148 -0
- data/lib/mac_spec/matcher_system/core/def_matcher.rb +14 -0
- data/lib/mac_spec/matcher_system/core/exceptions.rb +7 -0
- data/lib/mac_spec/matcher_system/core/expectation_builder.rb +11 -0
- data/lib/mac_spec/matcher_system/core/matcher_builder.rb +53 -0
- data/lib/mac_spec/matcher_system/core/modals.rb +36 -0
- data/lib/mac_spec/mocking_framework.rb +13 -0
- data/lib/mac_spec/mocking_framework/extensions/kernel_extension.rb +14 -0
- data/lib/mac_spec/mocking_framework/extensions/object_extension.rb +74 -0
- data/lib/mac_spec/mocking_framework/message_expectation.rb +127 -0
- data/lib/mac_spec/mocking_framework/mock.rb +20 -0
- data/lib/mac_spec/testing_framework.rb +13 -0
- data/lib/mac_spec/testing_framework/core/functions.rb +26 -0
- data/lib/mac_spec/testing_framework/core/kernel_extension.rb +27 -0
- data/lib/mac_spec/testing_framework/core/test_case_class_methods.rb +90 -0
- data/lib/mac_spec/version.rb +3 -0
- data/test/all.rb +6 -0
- data/test/mac_spec/matcher_system/built_in/change_expectations_test.rb +68 -0
- data/test/mac_spec/matcher_system/built_in/enumerable_expectations_test.rb +91 -0
- data/test/mac_spec/matcher_system/built_in/error_expectations_test.rb +144 -0
- data/test/mac_spec/matcher_system/built_in/operator_expectations_test.rb +136 -0
- data/test/mac_spec/matcher_system/built_in/truth_expectations_test.rb +373 -0
- data/test/mac_spec/matcher_system/core/def_matcher_test.rb +100 -0
- data/test/mac_spec/matcher_system/core/expectation_builder_test.rb +34 -0
- data/test/mac_spec/matcher_system/core/matcher_builder_test.rb +72 -0
- data/test/mac_spec/matcher_system/core/modals_test.rb +39 -0
- data/test/mac_spec/matcher_system/script.rb +29 -0
- data/test/mac_spec/matcher_system/test_helper.rb +2 -0
- data/test/mac_spec/mocking_framework/extensions/kernel_extension_test.rb +37 -0
- data/test/mac_spec/mocking_framework/extensions/object_extension_test.rb +9 -0
- data/test/mac_spec/mocking_framework/message_expectation_test.rb +9 -0
- data/test/mac_spec/mocking_framework/mock_test.rb +9 -0
- data/test/mac_spec/mocking_framework/regression/mocking_class_methods_test.rb +96 -0
- data/test/mac_spec/mocking_framework/regression/negative_expectation_test.rb +33 -0
- data/test/mac_spec/mocking_framework/regression/stub_test.rb +19 -0
- data/test/mac_spec/mocking_framework/test_helper.rb +1 -0
- data/test/mac_spec/test_helper.rb +1 -0
- data/test/mac_spec/testing_framework/performance/x_test_performance.rb +125 -0
- data/test/mac_spec/testing_framework/regression/before_test.rb +32 -0
- data/test/mac_spec/testing_framework/regression/deep_nested_example_groups_test.rb +20 -0
- data/test/mac_spec/testing_framework/regression/description_string_test.rb +13 -0
- data/test/mac_spec/testing_framework/regression/example_name_test.rb +11 -0
- data/test/mac_spec/testing_framework/regression/inherit_not_double_test.rb +39 -0
- data/test/mac_spec/testing_framework/regression/surrounding_module_scope_test.rb +31 -0
- data/test/mac_spec/testing_framework/regression/testing_functions_test.rb +66 -0
- data/test/mac_spec/testing_framework/test_helper.rb +1 -0
- data/test/test_helper.rb +1 -0
- metadata +150 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Matthias Hennemeyer
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
= MacSpec
|
2
|
+
|
3
|
+
MacSpec is a (yet) feature minimal RSpec clone that is specifically built to work with MacRuby.
|
4
|
+
It is built ontop of MiniTest that ships with MacRuby and works out of the box with the MacRuby App
|
5
|
+
Template for Xcode. All you have to do is to replace two lines of code and start writing your tests.
|
6
|
+
No special command for running tests required. Just set your active Target to Test and hit Cmd-B.
|
7
|
+
|
8
|
+
MacSpec ships with a testing framework similar to RSpec's.
|
9
|
+
|
10
|
+
The matchy matcher system is built in. (-> http://github.com/jm/matchy)
|
11
|
+
|
12
|
+
Even a mocking framework is built in.
|
13
|
+
|
14
|
+
== Philosophy
|
15
|
+
|
16
|
+
The highest priority feature will always be MacRuby compatibility. We will expand MacSpec's feature set towards RSpec's feature set step by step.
|
17
|
+
|
18
|
+
== Copyright
|
19
|
+
|
20
|
+
Copyright (c) 2010 Matthias Hennemeyer. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'lib/mac_spec/version.rb'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.version = MacSpec::VERSION
|
9
|
+
gem.name = "MacSpec"
|
10
|
+
gem.summary = %Q{MacSpec is a feature minimal RSpec clone that is specifically built to work with MacRuby.}
|
11
|
+
gem.description = %Q{MacSpec is a feature minimal RSpec clone that is specifically built to work with MacRuby.}
|
12
|
+
gem.email = "mhennemeyer@me.com"
|
13
|
+
gem.homepage = "http://github.com/mhennemeyer/MacSpec"
|
14
|
+
gem.authors = ["Matthias Hennemeyer"]
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/*_test.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :test => :check_dependencies
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "MacSpec #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/lib/mac_spec.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "minitest/unit"
|
3
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
4
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
5
|
+
|
6
|
+
module MacSpec
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def assert(bool=false)
|
10
|
+
@current_test_case.assert(bool)
|
11
|
+
end
|
12
|
+
|
13
|
+
def flunk(msg="No Error Message given.")
|
14
|
+
@current_test_case.flunk(msg)
|
15
|
+
end
|
16
|
+
|
17
|
+
def current_test_case
|
18
|
+
@current_test_case
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_test_case=(tc)
|
22
|
+
@current_test_case = tc
|
23
|
+
end
|
24
|
+
|
25
|
+
def assertions_module
|
26
|
+
MiniTest::Assertions
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_case_class
|
30
|
+
MiniTest::Unit::TestCase
|
31
|
+
end
|
32
|
+
|
33
|
+
def assertion_failed_error
|
34
|
+
MiniTest::Assertion
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
MiniTest::Unit.autorun unless defined?(MacSpecNoAutoRun)
|
39
|
+
require 'mac_spec/version'
|
40
|
+
require 'mac_spec/matcher_system'
|
41
|
+
require 'mac_spec/testing_framework'
|
42
|
+
require 'mac_spec/mocking_framework'
|
43
|
+
unless defined?(LOADED)
|
44
|
+
# Track the current testcase and
|
45
|
+
# provide it to the operator matchers and mocking framework.
|
46
|
+
# Otherwise expectations won't be counted as assertions
|
47
|
+
# todo no global
|
48
|
+
MacSpec.test_case_class.class_eval do
|
49
|
+
alias_method :old_run_method_aliased_by_macspec, :run
|
50
|
+
def run(whatever, *args, &block)
|
51
|
+
MacSpec.current_test_case = self
|
52
|
+
old_run_method_aliased_by_macspec(whatever, *args, &block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
LOADED = true
|
56
|
+
end
|
57
|
+
|
58
|
+
MacSpec.test_case_class.send(:include, MacSpec::MatcherSystem::Expectations::TestCaseExtensions)
|
59
|
+
include MacSpec::MatcherSystem::DefMatcher
|
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
require 'matcher_system/core/expectation_builder'
|
4
|
+
require 'matcher_system/core/modals'
|
5
|
+
require 'matcher_system/core/matcher_builder'
|
6
|
+
require 'matcher_system/core/def_matcher'
|
7
|
+
require 'matcher_system/core/exceptions'
|
8
|
+
|
9
|
+
require 'matcher_system/built_in/enumerable_expectations'
|
10
|
+
require 'matcher_system/built_in/error_expectations'
|
11
|
+
require 'matcher_system/built_in/truth_expectations'
|
12
|
+
require 'matcher_system/built_in/operator_expectations'
|
13
|
+
require 'matcher_system/built_in/change_expectations'
|
14
|
+
|
15
|
+
module MacSpec
|
16
|
+
module MatcherSystem
|
17
|
+
# todo doc
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module Expectations
|
4
|
+
module TestCaseExtensions
|
5
|
+
# Checks if the given block alters the value of the block attached to change
|
6
|
+
#
|
7
|
+
# ==== Examples
|
8
|
+
# lambda {var += 1}.should change {var}.by(1)
|
9
|
+
# lambda {var += 2}.should change {var}.by_at_least(1)
|
10
|
+
# lambda {var += 1}.should change {var}.by_at_most(1)
|
11
|
+
# lambda {var += 2}.should change {var}.from(1).to(3) if var = 1
|
12
|
+
def change(&block)
|
13
|
+
build_matcher(:change) do |receiver, matcher, args|
|
14
|
+
before, done, after = block.call, receiver.call, block.call
|
15
|
+
comparison = (after != before)
|
16
|
+
specifiers = matcher.chained_messages
|
17
|
+
if specifiers
|
18
|
+
comparison = case specifiers[0].name
|
19
|
+
# todo: provide meaningful messages
|
20
|
+
when :by then (after == before + specifiers[0].args[0] || after == before - specifiers[0].args[0])
|
21
|
+
when :by_at_least then (after >= before + specifiers[0].args[0] || after <= before - specifiers[0].args[0])
|
22
|
+
when :by_at_most then (after <= before + specifiers[0].args[0] && after >= before - specifiers[0].args[0])
|
23
|
+
when :from then (before == specifiers[0].args[0]) && (after == specifiers[1].args[0])
|
24
|
+
else raise MacSpec::MatcherSystem::Exceptions::UnsupportedMessageSentToMatcher.new(
|
25
|
+
"Message: #{specifiers[0].name} sent to change matcher.")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
matcher.positive_msg = "given block shouldn't alter the block attached to change"
|
29
|
+
matcher.negative_msg = "given block should alter the block attached to change"
|
30
|
+
comparison
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module Expectations
|
4
|
+
module TestCaseExtensions
|
5
|
+
|
6
|
+
# Calls +include?+ on the receiver for any object. You can also provide
|
7
|
+
# multiple arguments to see if all of them are included.
|
8
|
+
#
|
9
|
+
# ==== Examples
|
10
|
+
#
|
11
|
+
# [1,2,3].should include(1)
|
12
|
+
# [7,8,8].should_not include(3)
|
13
|
+
# ['a', 'b', 'c'].should include('a', 'c')
|
14
|
+
#
|
15
|
+
def include(*obj)
|
16
|
+
_clude(:include, obj)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Expects the receiver to exclude the given object(s). You can provide
|
20
|
+
# multiple arguments to see if all of them are included.
|
21
|
+
#
|
22
|
+
# ==== Examples
|
23
|
+
#
|
24
|
+
# [1,2,3].should exclude(16)
|
25
|
+
# [7,8,8].should_not exclude(7)
|
26
|
+
# ['a', 'b', 'c'].should exclude('e', 'f', 'g')
|
27
|
+
#
|
28
|
+
def exclude(*obj)
|
29
|
+
_clude(:exclude, obj)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def _clude(sym, obj)
|
34
|
+
build_matcher(sym, obj) do |given, matcher, args|
|
35
|
+
matcher.positive_msg = "Expected #{given.inspect} to #{sym} #{args.inspect}."
|
36
|
+
matcher.negative_msg = "Expected #{given.inspect} to not #{sym} #{args.inspect}."
|
37
|
+
args.inject(true) {|m,o| m && (given.include?(o) == (sym == :include)) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module Expectations
|
4
|
+
module TestCaseExtensions
|
5
|
+
# Expects a lambda to raise an error. You can specify the error or leave it blank to encompass
|
6
|
+
# any error.
|
7
|
+
#
|
8
|
+
# ==== Examples
|
9
|
+
#
|
10
|
+
# lambda { raise "FAILURE." }.should raise_error
|
11
|
+
# lambda { puts i_dont_exist }.should raise_error(NameError)
|
12
|
+
#
|
13
|
+
def raise_error(*obj)
|
14
|
+
build_matcher(:raise_error, obj) do |receiver, matcher, args|
|
15
|
+
expected = args[0] || Exception
|
16
|
+
raised = false
|
17
|
+
error = nil
|
18
|
+
begin
|
19
|
+
receiver.call
|
20
|
+
rescue Exception => e
|
21
|
+
raised = true
|
22
|
+
error = e
|
23
|
+
end
|
24
|
+
if expected.respond_to?(:ancestors) && expected.ancestors.include?(Exception)
|
25
|
+
matcher.positive_msg = "Expected #{receiver.inspect} to raise #{expected.name}, " +
|
26
|
+
(error ? "but #{error.class.name} was raised instead." : "but none was raised.")
|
27
|
+
matcher.negative_msg = "Expected #{receiver.inspect} to not raise #{expected.name}."
|
28
|
+
comparison = (raised && error.class.ancestors.include?(expected))
|
29
|
+
else
|
30
|
+
message = error ? error.message : "none"
|
31
|
+
matcher.positive_msg = "Expected #{receiver.inspect} to raise error with message matching '#{expected}', but '#{message}' was raised."
|
32
|
+
matcher.negative_msg = "Expected #{receiver.inspect} to raise error with message not matching '#{expected}', but '#{message}' was raised."
|
33
|
+
comparison = (raised && (expected.kind_of?(Regexp) ? ((error.message =~ expected) ? true : false) : expected == error.message))
|
34
|
+
end
|
35
|
+
comparison
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Expects a lambda to throw an error.
|
40
|
+
#
|
41
|
+
# ==== Examples
|
42
|
+
#
|
43
|
+
# lambda { throw :thing }.should throw_symbol(:thing)
|
44
|
+
# lambda { "not this time" }.should_not throw_symbol(:hello)
|
45
|
+
#
|
46
|
+
def throw_symbol(*obj)
|
47
|
+
build_matcher(:throw_symbol, obj) do |receiver, matcher, args|
|
48
|
+
raised, thrown_symbol, expected = false, nil, args[0]
|
49
|
+
begin
|
50
|
+
receiver.call
|
51
|
+
rescue NameError => e
|
52
|
+
raise e unless e.message =~ /uncaught throw/
|
53
|
+
raised = true
|
54
|
+
thrown_symbol = e.name.to_sym if e.respond_to?(:name)
|
55
|
+
rescue ArgumentError => e
|
56
|
+
raise e unless e.message =~ /uncaught throw/
|
57
|
+
thrown_symbol = e.message.match(/uncaught throw :(.+)/)[1].to_sym
|
58
|
+
end
|
59
|
+
matcher.positive_msg = "Expected #{receiver.inspect} to throw :#{expected}, but " +
|
60
|
+
"#{thrown_symbol ? ':' + thrown_symbol.to_s + ' was thrown instead' : 'no symbol was thrown'}."
|
61
|
+
matcher.negative_msg = "Expected #{receiver.inspect} to not throw :#{expected}."
|
62
|
+
expected == thrown_symbol
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module Expectations
|
4
|
+
# Class to handle operator expectations.
|
5
|
+
#
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# 13.should == 13
|
9
|
+
# "hello".length.should_not == 2
|
10
|
+
#
|
11
|
+
class OperatorExpectation #< Base
|
12
|
+
include ::MacSpec.assertions_module
|
13
|
+
|
14
|
+
def initialize(receiver, match)
|
15
|
+
@receiver, @match = receiver, match
|
16
|
+
end
|
17
|
+
|
18
|
+
['==', '===', '=~', '>', '>=', '<', '<='].each do |op|
|
19
|
+
define_method(op) do |expected|
|
20
|
+
@expected = expected
|
21
|
+
(@receiver.send(op,expected) ? true : false) == @match ? pass! : fail!(op)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
def pass!
|
27
|
+
MacSpec.assert(true)
|
28
|
+
end
|
29
|
+
|
30
|
+
def fail!(operator)
|
31
|
+
msg = @match ? failure_message(operator) : negative_failure_message(operator)
|
32
|
+
MacSpec.flunk msg
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure_message(operator)
|
36
|
+
"Expected #{@receiver.inspect} to #{operator} #{@expected.inspect}."
|
37
|
+
end
|
38
|
+
|
39
|
+
def negative_failure_message(operator)
|
40
|
+
"Expected #{@receiver.inspect} to not #{operator} #{@expected.inspect}."
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module MacSpec
|
2
|
+
module MatcherSystem
|
3
|
+
module Expectations
|
4
|
+
module TestCaseExtensions
|
5
|
+
# Simply checks if the receiver matches the expected object.
|
6
|
+
# TODO: Fill this out to implement much of the RSpec functionality (and then some)
|
7
|
+
#
|
8
|
+
# ==== Examples
|
9
|
+
#
|
10
|
+
# "hello".should be("hello")
|
11
|
+
# (13 < 20).should be(true)
|
12
|
+
#
|
13
|
+
def be(*obj)
|
14
|
+
build_matcher(:be, obj) do |receiver, matcher, args|
|
15
|
+
@receiver, expected = receiver, args[0]
|
16
|
+
matcher.positive_msg = "Expected #{@receiver.inspect} to be #{expected.inspect}."
|
17
|
+
matcher.negative_msg = "Expected #{@receiver.inspect} to not be #{expected.inspect}."
|
18
|
+
expected == @receiver
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Checks if the given object is within a given object and delta.
|
23
|
+
#
|
24
|
+
# ==== Examples
|
25
|
+
#
|
26
|
+
# (20.0 - 2.0).should be_close(18.0)
|
27
|
+
# (13.0 - 4.0).should be_close(9.0, 0.5)
|
28
|
+
#
|
29
|
+
def be_close(obj, delta = 0.3)
|
30
|
+
build_matcher(:be_close, [obj, delta]) do |receiver, matcher, args|
|
31
|
+
@receiver, expected, delta = receiver, args[0], args[1]
|
32
|
+
matcher.positive_msg = "Expected #{@receiver.inspect} to be close to #{expected.inspect} (delta: #{delta})."
|
33
|
+
matcher.negative_msg = "Expected #{@receiver.inspect} to not be close to #{expected.inspect} (delta: #{delta})."
|
34
|
+
(@receiver - expected).abs < delta
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Calls +exist?+ on the given object.
|
39
|
+
#
|
40
|
+
# ==== Examples
|
41
|
+
#
|
42
|
+
# # found_user.exist?
|
43
|
+
# found_user.should exist
|
44
|
+
#
|
45
|
+
def exist
|
46
|
+
ask_for(:exist, :with_arg => nil)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Calls +eql?+ on the given object (i.e., are the objects the same value?)
|
50
|
+
#
|
51
|
+
# ==== Examples
|
52
|
+
#
|
53
|
+
# 1.should_not eql(1.0)
|
54
|
+
# (12 / 6).should eql(6)
|
55
|
+
#
|
56
|
+
def eql(*obj)
|
57
|
+
ask_for(:eql, :with_arg => obj)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Calls +equal?+ on the given object (i.e., do the two objects have the same +object_id+?)
|
61
|
+
#
|
62
|
+
# ==== Examples
|
63
|
+
#
|
64
|
+
# x = [1,2,3]
|
65
|
+
# y = [1,2,3]
|
66
|
+
#
|
67
|
+
# # Different object_id's...
|
68
|
+
# x.should_not equal(y)
|
69
|
+
#
|
70
|
+
# # The same object_id
|
71
|
+
# x[0].should equal(y[0])
|
72
|
+
#
|
73
|
+
def equal(*obj)
|
74
|
+
ask_for(:equal, :with_arg => obj)
|
75
|
+
end
|
76
|
+
|
77
|
+
# A last ditch way to implement your testing logic. You probably shouldn't use this unless you
|
78
|
+
# have to.
|
79
|
+
#
|
80
|
+
# ==== Examples
|
81
|
+
#
|
82
|
+
# (13 - 4).should satisfy(lambda {|i| i < 20})
|
83
|
+
# "hello".should_not satisfy(lambda {|s| s =~ /hi/})
|
84
|
+
#
|
85
|
+
def satisfy(*obj)
|
86
|
+
build_matcher(:satisfy, obj) do |receiver, matcher, args|
|
87
|
+
@receiver, expected = receiver, args[0]
|
88
|
+
matcher.positive_msg = "Expected #{@receiver.inspect} to satisfy given block."
|
89
|
+
matcher.negative_msg = "Expected #{@receiver.inspect} to not satisfy given block."
|
90
|
+
expected.call(@receiver) == true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Checks if the given object responds to the given method
|
95
|
+
#
|
96
|
+
# ==== Examples
|
97
|
+
#
|
98
|
+
# "foo".should respond_to(:length)
|
99
|
+
# {}.should respond_to(:has_key?)
|
100
|
+
def respond_to(*meth)
|
101
|
+
ask_for(:respond_to, :with_arg => meth)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Asks given for success?().
|
105
|
+
# This is necessary because Rails Integration::Session
|
106
|
+
# overides method_missing without grace.
|
107
|
+
#
|
108
|
+
# ==== Examples
|
109
|
+
#
|
110
|
+
# @response.should be_success
|
111
|
+
def be_success
|
112
|
+
ask_for(:success, :with_arg => nil)
|
113
|
+
end
|
114
|
+
|
115
|
+
alias_method :old_missing, :method_missing
|
116
|
+
# ==be_*something(*args)
|
117
|
+
#
|
118
|
+
# ===This method_missing acts as a matcher builder.
|
119
|
+
# If a call to be_xyz() reaches this method_missing (say: obj.should be_xyz),
|
120
|
+
# a matcher with the name xyz will be built, whose defining property
|
121
|
+
# is that it returns the value of obj.xyz? for matches?.
|
122
|
+
# ==== Examples
|
123
|
+
#
|
124
|
+
# nil.should be_nil
|
125
|
+
# 17.should be_kind_of(Fixnum)
|
126
|
+
# obj.something? #=> true
|
127
|
+
# obj.should be_something
|
128
|
+
def method_missing(name, *args, &block)
|
129
|
+
if (name.to_s =~ /^be_(.+)/)
|
130
|
+
ask_for($1, :with_arg => args)
|
131
|
+
else
|
132
|
+
old_missing(name, *args, &block)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
def ask_for(sym, option={})
|
138
|
+
build_matcher(sym, (option[:with_arg] || [])) do |receiver, matcher, args|
|
139
|
+
expected, meth = args[0], (sym.to_s + "?" ).to_sym
|
140
|
+
matcher.positive_msg = "Expected #{receiver.inspect} to return true for #{sym}?, with '#{(expected && expected.inspect) || 'no args'}'."
|
141
|
+
matcher.negative_msg = "Expected #{receiver.inspect} to not return true for #{sym}?, with '#{(expected && expected.inspect) || 'no args'}'."
|
142
|
+
expected ? receiver.send(meth, expected) : receiver.send(meth)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|