rspec 1.2.9 → 1.3.0
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/History.rdoc +34 -1
- data/License.txt +1 -1
- data/Manifest.txt +11 -4
- data/README.rdoc +2 -3
- data/Rakefile +17 -13
- data/Upgrade.rdoc +63 -2
- data/features/formatters/nested_formatter.feature +32 -0
- data/features/interop/cucumber_stubs_dont_leak.feature +11 -0
- data/features/matchers/define_matcher_with_fluent_interface.feature +21 -0
- data/features/matchers/define_wrapped_matcher.feature +28 -1
- data/features/matchers/match_unless_raises.feature +60 -0
- data/features/matchers/match_unless_raises_unexpected_error.feature +39 -0
- data/features/mocks/block_local_expectations.feature +62 -0
- data/features/step_definitions/running_rspec_steps.rb +9 -0
- data/features/step_definitions/stubbing_steps.rb +16 -0
- data/features/support/env.rb +1 -0
- data/features/support/matchers/smart_match.rb +23 -4
- data/geminstaller.yml +28 -0
- data/lib/autotest/rspec.rb +14 -7
- data/lib/spec/dsl/main.rb +1 -1
- data/lib/spec/example/example_methods.rb +4 -0
- data/lib/spec/{matchers/extensions → extensions}/instance_exec.rb +0 -0
- data/lib/spec/interop/test.rb +1 -1
- data/lib/spec/matchers.rb +21 -2
- data/lib/spec/matchers/be.rb +167 -128
- data/lib/spec/matchers/has.rb +3 -3
- data/lib/spec/matchers/have.rb +1 -0
- data/lib/spec/matchers/matcher.rb +55 -10
- data/lib/spec/matchers/method_missing.rb +2 -2
- data/lib/spec/matchers/raise_exception.rb +131 -0
- data/lib/spec/matchers/throw_symbol.rb +16 -20
- data/lib/spec/mocks/message_expectation.rb +63 -48
- data/lib/spec/mocks/methods.rb +13 -8
- data/lib/spec/mocks/proxy.rb +43 -22
- data/lib/spec/runner/differs/default.rb +1 -1
- data/lib/spec/runner/drb_command_line.rb +8 -2
- data/lib/spec/runner/example_group_runner.rb +1 -2
- data/lib/spec/runner/formatter/nested_text_formatter.rb +6 -3
- data/lib/spec/runner/option_parser.rb +2 -0
- data/lib/spec/runner/options.rb +6 -1
- data/lib/spec/stubs/cucumber.rb +2 -2
- data/lib/spec/version.rb +2 -2
- data/spec/autotest/autotest_helper.rb +1 -1
- data/spec/autotest/discover_spec.rb +2 -2
- data/spec/autotest/failed_results_re_spec.rb +2 -2
- data/spec/autotest/rspec_spec.rb +21 -6
- data/spec/spec/example/example_group_methods_spec.rb +2 -1
- data/spec/spec/interop/test/unit/spec_spec.rb +7 -7
- data/spec/spec/interop/test/unit/testcase_spec.rb +7 -7
- data/spec/spec/interop/test/unit/testsuite_adapter_spec.rb +1 -1
- data/spec/spec/matchers/be_spec.rb +159 -10
- data/spec/spec/matchers/has_spec.rb +109 -0
- data/spec/spec/matchers/matcher_spec.rb +70 -9
- data/spec/spec/matchers/raise_exception_spec.rb +345 -0
- data/spec/spec/matchers/throw_symbol_spec.rb +83 -58
- data/spec/spec/mocks/and_yield_spec.rb +117 -0
- data/spec/spec/mocks/mock_spec.rb +2 -2
- data/spec/spec/runner/command_line_spec.rb +26 -5
- data/spec/spec/runner/drb_command_line_spec.rb +39 -0
- data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +35 -11
- data/spec/spec/runner/option_parser_spec.rb +12 -6
- data/spec/spec/runner/options_spec.rb +7 -0
- data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +23 -5
- metadata +17 -10
- data/lib/spec/matchers/raise_error.rb +0 -129
- data/spec/spec/matchers/matcher_methods_spec.rb +0 -63
- data/spec/spec/matchers/raise_error_spec.rb +0 -333
@@ -0,0 +1,62 @@
|
|
1
|
+
Feature: block local expectations
|
2
|
+
|
3
|
+
In order to set message expectations on ...
|
4
|
+
As an RSpec user
|
5
|
+
I want to configure the evaluation context
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given a file named "account.rb" with:
|
9
|
+
"""
|
10
|
+
class Account
|
11
|
+
def self.create
|
12
|
+
yield new
|
13
|
+
end
|
14
|
+
|
15
|
+
def opening_balance(amount, currency)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
"""
|
19
|
+
|
20
|
+
Scenario: passing example
|
21
|
+
Given a file named "account_dsl.rb" with:
|
22
|
+
"""
|
23
|
+
require 'spec_helper'
|
24
|
+
require 'account'
|
25
|
+
|
26
|
+
describe "account DSL" do
|
27
|
+
it " .... " do
|
28
|
+
account = Account.new
|
29
|
+
Account.should_receive(:create).and_yield do |account|
|
30
|
+
account.should_receive(:opening_balance).with(100, :USD)
|
31
|
+
end
|
32
|
+
Account.create do
|
33
|
+
opening_balance 100, :USD
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
"""
|
38
|
+
When I run "spec account_dsl.rb"
|
39
|
+
Then the stdout should include "1 example, 0 failures"
|
40
|
+
|
41
|
+
Scenario: failing example
|
42
|
+
|
43
|
+
Given a file named "account_dsl.rb" with:
|
44
|
+
"""
|
45
|
+
require 'spec_helper'
|
46
|
+
require 'account'
|
47
|
+
|
48
|
+
describe "account DSL" do
|
49
|
+
it " .... " do
|
50
|
+
account = Account.new
|
51
|
+
Account.should_receive(:create).and_yield do |account|
|
52
|
+
account.should_receive(:opening_balance).with(100, :USD)
|
53
|
+
end
|
54
|
+
Account.create do
|
55
|
+
# opening_balance is not called here
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
"""
|
60
|
+
|
61
|
+
When I run "spec account_dsl.rb"
|
62
|
+
Then the stdout should include "1 example, 1 failure"
|
@@ -27,6 +27,15 @@ Then /^the (.*) should include (.*)$/ do |stream, string_or_regex|
|
|
27
27
|
written.should smart_match(string_or_regex)
|
28
28
|
end
|
29
29
|
|
30
|
+
Then /^the (.*) should include$/ do |stream, string_or_regex|
|
31
|
+
written = case(stream)
|
32
|
+
when 'stdout' then last_stdout
|
33
|
+
when 'stderr' then last_stderr
|
34
|
+
else raise "Unknown stream: #{stream}"
|
35
|
+
end
|
36
|
+
written.should smart_match(string_or_regex)
|
37
|
+
end
|
38
|
+
|
30
39
|
Then /^the (.*) should not match (.*)$/ do |stream, string_or_regex|
|
31
40
|
written = case(stream)
|
32
41
|
when 'stdout' then last_stdout
|
@@ -0,0 +1,16 @@
|
|
1
|
+
When /^I stub "([^\"]*)" on "([^\"]*)" to "([^\"]*)"$/ do |method_name, const_name, value|
|
2
|
+
const = Object.const_get(const_name)
|
3
|
+
const.stub!(method_name.to_sym).and_return(value)
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^calling "([^\"]*)" on "([^\"]*)" should return "([^\"]*)"$/ do |method_name, const_name, value|
|
7
|
+
const = Object.const_get(const_name)
|
8
|
+
const.send(method_name.to_sym).should == value
|
9
|
+
end
|
10
|
+
|
11
|
+
Then /^"([^\"]*)" should not be defined on "([^\"]*)"$/ do |method_name, const_name|
|
12
|
+
const = Object.const_get(const_name)
|
13
|
+
lambda {
|
14
|
+
const.send(method_name.to_sym)
|
15
|
+
}.should raise_error(NameError, /#{method_name}/)
|
16
|
+
end
|
data/features/support/env.rb
CHANGED
@@ -1,12 +1,31 @@
|
|
1
1
|
Spec::Matchers.define :smart_match do |expected|
|
2
|
+
def regexp?
|
3
|
+
/^\/.*\/?$/
|
4
|
+
end
|
5
|
+
|
6
|
+
def quoted?
|
7
|
+
/^".*"$/
|
8
|
+
end
|
9
|
+
|
2
10
|
match do |actual|
|
3
11
|
case expected
|
4
|
-
when
|
12
|
+
when regexp?
|
5
13
|
actual =~ eval(expected)
|
6
|
-
when
|
14
|
+
when quoted?
|
7
15
|
actual.index(eval(expected))
|
8
|
-
else
|
9
|
-
|
16
|
+
else # multi-line string
|
17
|
+
actual.index(expected)
|
10
18
|
end
|
11
19
|
end
|
20
|
+
|
21
|
+
failure_message_for_should do |actual|
|
22
|
+
<<-MESSAGE
|
23
|
+
#{'*'*50}
|
24
|
+
got:
|
25
|
+
#{'*'*30}
|
26
|
+
#{actual}
|
27
|
+
#{'*'*50}
|
28
|
+
MESSAGE
|
29
|
+
end
|
12
30
|
end
|
31
|
+
|
data/geminstaller.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Basics needed to run 'rake' from this directory
|
2
|
+
gems:
|
3
|
+
- name: cucumber
|
4
|
+
version: '>= 0.3.101'
|
5
|
+
- name: diff-lcs
|
6
|
+
version: '>= 1.1.2'
|
7
|
+
- name: fakefs
|
8
|
+
version: '>= 0.2'
|
9
|
+
- name: flexmock
|
10
|
+
version: '>= 0.8.6'
|
11
|
+
- name: heckle
|
12
|
+
version: '>= 1.4.2'
|
13
|
+
- name: hoe
|
14
|
+
version: '>= 2.0'
|
15
|
+
- name: nokogiri
|
16
|
+
version: '>= 1.2.3'
|
17
|
+
- name: mocha
|
18
|
+
version: '>= 0.9.5'
|
19
|
+
- name: rake
|
20
|
+
version: '>= 0.8.4'
|
21
|
+
- name: spicycode-rcov
|
22
|
+
version: '>= 0.8.2.1'
|
23
|
+
- name: syntax
|
24
|
+
version: '>= 1.0.0'
|
25
|
+
- name: rr
|
26
|
+
version: '>= 0.10.0'
|
27
|
+
- name: ruby-debug
|
28
|
+
version: '>= 0.10.3'
|
data/lib/autotest/rspec.rb
CHANGED
@@ -2,9 +2,8 @@ require 'autotest'
|
|
2
2
|
|
3
3
|
Autotest.add_hook :initialize do |at|
|
4
4
|
at.clear_mappings
|
5
|
-
# watch out
|
6
|
-
|
7
|
-
at.add_mapping(%r%^spec/.*_spec.rb$%) { |filename, _|
|
5
|
+
# watch out for Ruby bug (1.8.6): %r(/) != /\//
|
6
|
+
at.add_mapping(%r%^spec/.*_spec\.rb$%) { |filename, _|
|
8
7
|
filename
|
9
8
|
}
|
10
9
|
at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m|
|
@@ -18,6 +17,8 @@ end
|
|
18
17
|
class RspecCommandError < StandardError; end
|
19
18
|
|
20
19
|
class Autotest::Rspec < Autotest
|
20
|
+
|
21
|
+
SPEC_PROGRAM = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec'))
|
21
22
|
|
22
23
|
def initialize
|
23
24
|
super
|
@@ -36,12 +37,18 @@ class Autotest::Rspec < Autotest
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def make_test_cmd(files_to_test)
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
files_to_test.empty? ? '' :
|
41
|
+
"#{ruby} #{SPEC_PROGRAM} --autospec #{normalize(files_to_test).keys.flatten.join(' ')} #{add_options_if_present}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def normalize(files_to_test)
|
45
|
+
files_to_test.keys.inject({}) do |result, filename|
|
46
|
+
result[File.expand_path(filename)] = []
|
47
|
+
result
|
48
|
+
end
|
42
49
|
end
|
43
50
|
|
44
51
|
def add_options_if_present # :nodoc:
|
45
|
-
File.exist?("spec/spec.opts") ? "-O spec
|
52
|
+
File.exist?("spec/spec.opts") ? "-O #{File.join('spec','spec.opts')} " : ""
|
46
53
|
end
|
47
54
|
end
|
data/lib/spec/dsl/main.rb
CHANGED
@@ -27,7 +27,7 @@ module Spec
|
|
27
27
|
set_location(args.options, caller(0)[1])
|
28
28
|
Spec::Example::ExampleGroupFactory.create_example_group(*args, &block)
|
29
29
|
end
|
30
|
-
alias :context :describe
|
30
|
+
alias :context :describe unless defined?(IRB::Context)
|
31
31
|
|
32
32
|
# Creates an example group that can be shared by other example groups
|
33
33
|
#
|
@@ -38,11 +38,15 @@ module Spec
|
|
38
38
|
begin
|
39
39
|
before_each_example
|
40
40
|
instance_eval(&@_implementation)
|
41
|
+
rescue Interrupt
|
42
|
+
exit 1
|
41
43
|
rescue Exception => e
|
42
44
|
execution_error ||= e
|
43
45
|
end
|
44
46
|
begin
|
45
47
|
after_each_example
|
48
|
+
rescue Interrupt
|
49
|
+
exit 1
|
46
50
|
rescue Exception => e
|
47
51
|
execution_error ||= e
|
48
52
|
end
|
File without changes
|
data/lib/spec/interop/test.rb
CHANGED
@@ -23,7 +23,7 @@ Unfortunately, test-unit-#{Test::Unit::VERSION} was loaded anyway. While we are
|
|
23
23
|
aware of this bug we have not been able to track down its source.
|
24
24
|
Until we do, you have two alternatives:
|
25
25
|
|
26
|
-
* uninstall test-unit
|
26
|
+
* uninstall test-unit-#{Test::Unit::VERSION}
|
27
27
|
* use 'script/spec' instead of 'rake spec'
|
28
28
|
#{'*' * 50}
|
29
29
|
MESSAGE
|
data/lib/spec/matchers.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'spec/
|
1
|
+
require 'spec/extensions/instance_exec'
|
2
2
|
require 'spec/matchers/pretty'
|
3
3
|
require 'spec/matchers/matcher'
|
4
4
|
require 'spec/matchers/operator_matcher'
|
@@ -18,7 +18,7 @@ require 'spec/matchers/include'
|
|
18
18
|
require 'spec/matchers/match'
|
19
19
|
require 'spec/matchers/match_array'
|
20
20
|
require 'spec/matchers/method_missing'
|
21
|
-
require 'spec/matchers/
|
21
|
+
require 'spec/matchers/raise_exception'
|
22
22
|
require 'spec/matchers/respond_to'
|
23
23
|
require 'spec/matchers/satisfy'
|
24
24
|
require 'spec/matchers/simple_matcher'
|
@@ -139,6 +139,25 @@ module Spec
|
|
139
139
|
# <tt>failure_message_for_should_not</tt>) are passed the actual value (the
|
140
140
|
# receiver of <tt>should</tt> or <tt>should_not</tt>).
|
141
141
|
#
|
142
|
+
# You can also create matchers that obey a fluent interface using the
|
143
|
+
# <tt>chain</tt> method:
|
144
|
+
#
|
145
|
+
# Spec::Matchers.define :tip do |expected_tip|
|
146
|
+
# chain :on do |bill|
|
147
|
+
# @bill = bill
|
148
|
+
# end
|
149
|
+
#
|
150
|
+
# match do |person|
|
151
|
+
# person.tip_for(bill) == expected_tip
|
152
|
+
# end
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# This matcher can be used as follows:
|
156
|
+
#
|
157
|
+
# describe Customer do
|
158
|
+
# it { should tip(10).on(50 }
|
159
|
+
# end
|
160
|
+
#
|
142
161
|
# === Custom Matcher from scratch
|
143
162
|
#
|
144
163
|
# You could also write a custom matcher from scratch, as follows:
|
data/lib/spec/matchers/be.rb
CHANGED
@@ -1,169 +1,206 @@
|
|
1
|
+
require 'spec/matchers/dsl'
|
2
|
+
|
3
|
+
Spec::Matchers.define :be_true do
|
4
|
+
match do |actual|
|
5
|
+
!!actual
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
Spec::Matchers.define :be_false do
|
10
|
+
match do |actual|
|
11
|
+
!actual
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Spec::Matchers.define :be_nil do
|
16
|
+
match do |actual|
|
17
|
+
actual.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
failure_message_for_should do |actual|
|
21
|
+
"expected nil, got #{actual.inspect}"
|
22
|
+
end
|
23
|
+
|
24
|
+
failure_message_for_should_not do
|
25
|
+
"expected not nil, got nil"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
1
29
|
module Spec
|
2
30
|
module Matchers
|
3
|
-
|
31
|
+
|
4
32
|
class Be #:nodoc:
|
5
33
|
include Spec::Matchers::Pretty
|
6
34
|
|
7
|
-
def initialize(*args)
|
8
|
-
@expected = args.empty? ? true : set_expected(args.shift)
|
35
|
+
def initialize(*args, &block)
|
9
36
|
@args = args
|
10
|
-
@comparison_method = nil
|
11
37
|
end
|
12
38
|
|
13
39
|
def matches?(actual)
|
14
40
|
@actual = actual
|
15
|
-
|
41
|
+
!!@actual
|
42
|
+
end
|
43
|
+
|
44
|
+
def failure_message_for_should
|
45
|
+
"expected #{@actual.inspect} to evaluate to true"
|
46
|
+
end
|
47
|
+
|
48
|
+
def failure_message_for_should_not
|
49
|
+
"expected #{@actual.inspect} to evaluate to false"
|
50
|
+
end
|
51
|
+
|
52
|
+
def description
|
53
|
+
"be"
|
54
|
+
end
|
55
|
+
|
56
|
+
[:==, :<, :<=, :>=, :>, :===].each do |operator|
|
57
|
+
define_method operator do |operand|
|
58
|
+
BeComparedTo.new(operand, operator)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def args_to_s
|
65
|
+
@args.empty? ? "" : parenthesize(inspected_args.join(', '))
|
66
|
+
end
|
67
|
+
|
68
|
+
def parenthesize(string)
|
69
|
+
return "(#{string})"
|
70
|
+
end
|
71
|
+
|
72
|
+
def inspected_args
|
73
|
+
@args.collect{|a| a.inspect}
|
74
|
+
end
|
75
|
+
|
76
|
+
def expected_to_sentence
|
77
|
+
split_words(@expected)
|
78
|
+
end
|
79
|
+
|
80
|
+
def args_to_sentence
|
81
|
+
to_sentence(@args)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
class BeComparedTo < Be
|
87
|
+
|
88
|
+
def initialize(operand, operator)
|
89
|
+
@expected, @operator = operand, operator
|
90
|
+
@args = []
|
91
|
+
end
|
92
|
+
|
93
|
+
def matches?(actual)
|
94
|
+
@actual = actual
|
95
|
+
@actual.__send__(@operator, @expected)
|
96
|
+
end
|
97
|
+
|
98
|
+
def failure_message_for_should
|
99
|
+
"expected #{@operator} #{@expected}, got #{@actual.inspect}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def failure_message_for_should_not
|
103
|
+
message = <<-MESSAGE
|
104
|
+
'should_not be #{@operator} #{@expected}' not only FAILED,
|
105
|
+
it is a bit confusing.
|
106
|
+
MESSAGE
|
107
|
+
|
108
|
+
raise message << ([:===,:==].include?(@operator) ?
|
109
|
+
"It might be more clearly expressed without the \"be\"?" :
|
110
|
+
"It might be more clearly expressed in the positive?")
|
111
|
+
end
|
112
|
+
|
113
|
+
def description
|
114
|
+
"be #{@operator} #{expected_to_sentence}#{args_to_sentence}"
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
class BePredicate < Be
|
120
|
+
|
121
|
+
def initialize(*args, &block)
|
122
|
+
@expected = parse_expected(args.shift)
|
123
|
+
@args = args
|
124
|
+
@block = block
|
16
125
|
end
|
17
126
|
|
18
|
-
def
|
127
|
+
def matches?(actual)
|
128
|
+
@actual = actual
|
19
129
|
begin
|
20
|
-
return @result = actual.__send__(predicate, *@args)
|
130
|
+
return @result = actual.__send__(predicate, *@args, &@block)
|
21
131
|
rescue NameError => predicate_missing_error
|
22
132
|
"this needs to be here or rcov will not count this branch even though it's executed in a code example"
|
23
133
|
end
|
24
134
|
|
25
135
|
begin
|
26
|
-
return @result = actual.__send__(present_tense_predicate, *@args)
|
136
|
+
return @result = actual.__send__(present_tense_predicate, *@args, &@block)
|
27
137
|
rescue NameError
|
28
138
|
raise predicate_missing_error
|
29
139
|
end
|
30
140
|
end
|
31
141
|
|
32
142
|
def failure_message_for_should
|
33
|
-
|
34
|
-
if predicate == :nil?
|
35
|
-
"expected nil, got #{@actual.inspect}"
|
36
|
-
else
|
37
|
-
"expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}"
|
38
|
-
end
|
39
|
-
else
|
40
|
-
"expected #{@comparison_method} #{expected}, got #{@actual.inspect}".gsub(' ',' ')
|
41
|
-
end
|
143
|
+
"expected #{predicate}#{args_to_s} to return true, got #{@result.inspect}"
|
42
144
|
end
|
43
145
|
|
44
146
|
def failure_message_for_should_not
|
45
|
-
|
46
|
-
if predicate == :nil?
|
47
|
-
"expected not nil, got nil"
|
48
|
-
else
|
49
|
-
"expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}"
|
50
|
-
end
|
51
|
-
else
|
52
|
-
message = <<-MESSAGE
|
53
|
-
'should_not be #{@comparison_method} #{expected}' not only FAILED,
|
54
|
-
it is a bit confusing.
|
55
|
-
MESSAGE
|
56
|
-
|
57
|
-
raise message << ([:===,:==].include?(@comparison_method) ?
|
58
|
-
"It might be more clearly expressed without the \"be\"?" :
|
59
|
-
"It might be more clearly expressed in the positive?")
|
60
|
-
end
|
147
|
+
"expected #{predicate}#{args_to_s} to return false, got #{@result.inspect}"
|
61
148
|
end
|
62
|
-
|
149
|
+
|
63
150
|
def description
|
64
|
-
"#{prefix_to_sentence}#{
|
151
|
+
"#{prefix_to_sentence}#{expected_to_sentence}#{args_to_sentence}"
|
65
152
|
end
|
66
153
|
|
67
|
-
|
68
|
-
define_method method do |expected|
|
69
|
-
compare_to(expected, :using => method)
|
70
|
-
self
|
71
|
-
end
|
72
|
-
end
|
154
|
+
private
|
73
155
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
156
|
+
def predicate
|
157
|
+
"#{@expected}?".to_sym
|
158
|
+
end
|
78
159
|
|
79
|
-
|
80
|
-
|
81
|
-
|
160
|
+
def present_tense_predicate
|
161
|
+
"#{@expected}s?".to_sym
|
162
|
+
end
|
82
163
|
|
83
|
-
|
84
|
-
|
85
|
-
|
164
|
+
def parse_expected(expected)
|
165
|
+
@prefix, expected = prefix_and_expected(expected)
|
166
|
+
expected
|
167
|
+
end
|
86
168
|
|
87
|
-
|
88
|
-
|
89
|
-
|
169
|
+
def prefix_and_expected(symbol)
|
170
|
+
symbol.to_s =~ /^(be_(an?_)?)(.*)/
|
171
|
+
return $1, $3
|
172
|
+
end
|
90
173
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
def parse_expected(expected)
|
96
|
-
["be_an_","be_a_","be_"].each do |prefix|
|
97
|
-
handling_predicate!
|
98
|
-
if expected.to_s =~ /^#{prefix}/
|
99
|
-
set_prefix(prefix)
|
100
|
-
expected = expected.to_s.sub(prefix,"")
|
101
|
-
[true, false, nil].each do |val|
|
102
|
-
return val if val.to_s == expected
|
103
|
-
end
|
104
|
-
return expected.to_sym
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def set_prefix(prefix)
|
110
|
-
@prefix = prefix
|
111
|
-
end
|
112
|
-
|
113
|
-
def prefix
|
114
|
-
# FIXME - this is a bit goofy - but we get failures
|
115
|
-
# if just defining @prefix = nil in initialize
|
116
|
-
@prefix = nil unless defined?(@prefix)
|
117
|
-
@prefix
|
118
|
-
end
|
174
|
+
def prefix_to_sentence
|
175
|
+
split_words(@prefix)
|
176
|
+
end
|
119
177
|
|
120
|
-
|
121
|
-
@handling_predicate = true
|
122
|
-
end
|
123
|
-
|
124
|
-
def handling_predicate?
|
125
|
-
return false if [true, false, nil].include?(expected)
|
126
|
-
# FIXME - this is a bit goofy - but we get failures
|
127
|
-
# if just defining @handling_predicate = nil or false in initialize
|
128
|
-
return defined?(@handling_predicate) ? @handling_predicate : nil
|
129
|
-
end
|
178
|
+
end
|
130
179
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
def expected_to_sentence
|
156
|
-
split_words(expected)
|
157
|
-
end
|
158
|
-
|
159
|
-
def prefix_to_sentence
|
160
|
-
split_words(prefix)
|
161
|
-
end
|
180
|
+
class BeSameAs < Be
|
181
|
+
|
182
|
+
def initialize(*args, &block)
|
183
|
+
@expected = args.shift
|
184
|
+
@args = args
|
185
|
+
end
|
186
|
+
|
187
|
+
def matches?(actual)
|
188
|
+
@actual = actual
|
189
|
+
@actual.equal?(@expected)
|
190
|
+
end
|
191
|
+
|
192
|
+
def failure_message_for_should
|
193
|
+
"expected #{@expected}, got #{@actual.inspect}"
|
194
|
+
end
|
195
|
+
|
196
|
+
def failure_message_for_should_not
|
197
|
+
"expected not #{@expected}, got #{@actual.inspect}"
|
198
|
+
end
|
199
|
+
|
200
|
+
def description
|
201
|
+
"be #{expected_to_sentence}#{args_to_sentence}"
|
202
|
+
end
|
162
203
|
|
163
|
-
def args_to_sentence
|
164
|
-
to_sentence(@args)
|
165
|
-
end
|
166
|
-
|
167
204
|
end
|
168
205
|
|
169
206
|
# :call-seq:
|
@@ -197,7 +234,9 @@ it is a bit confusing.
|
|
197
234
|
# target.should_not be_empty #passes unless target.empty?
|
198
235
|
# target.should_not be_old_enough(16) #passes unless target.old_enough?(16)
|
199
236
|
def be(*args)
|
200
|
-
|
237
|
+
args.empty? ?
|
238
|
+
Matchers::Be.new :
|
239
|
+
Matchers::BeSameAs.new(*args)
|
201
240
|
end
|
202
241
|
|
203
242
|
# passes if target.kind_of?(klass)
|