MacSpec 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|