rspec 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +28 -17
- data/README +25 -0
- data/Rakefile.rb +63 -3
- data/TODO +9 -0
- data/bin/spec +10 -0
- data/examples/craps_spec.rb +2 -7
- data/lib/spec.rb +1 -0
- data/lib/spec/collector.rb +17 -0
- data/lib/spec/context.rb +46 -25
- data/lib/spec/exceptions.rb +0 -2
- data/lib/spec/expectations.rb +1 -1
- data/lib/spec/mock.rb +80 -47
- data/lib/spec/text_runner.rb +5 -14
- data/test/craps_collector_test.rb +17 -0
- data/test/error_reporting_test.rb +4 -4
- data/test/expectations_test.rb +2 -2
- data/test/get_classes.rb +6 -0
- data/test/mock_test.rb +34 -19
- data/test/movie_collector_test.rb +19 -0
- data/test/rspec_craps_and_movie_test.rb +32 -0
- data/test/rspec_craps_test.rb +35 -0
- data/test/rspec_movie_test.rb +33 -0
- data/test/text_runner_test.rb +10 -0
- metadata +14 -7
- data/lib/rspec.rb +0 -9
- data/test/rspec_test.rb +0 -35
data/CHANGES
CHANGED
@@ -13,51 +13,62 @@
|
|
13
13
|
* Make sure the PKG_VERSION constant in Rakefile.rb is
|
14
14
|
consistent with the latest version in this document.
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
== Version 0.1.7
|
17
|
+
|
18
|
+
This release improves installation and documentation, mock integration and error reporting.
|
19
|
+
|
20
|
+
* Comparison errors now print the class name too.
|
21
|
+
* Mocks now take an optional +options+ parameter to specify behaviour.
|
22
|
+
* Removed __expects in favour of should_receive
|
23
|
+
* Added line number reporting in mock error messages for unreceived message expectations (AH).
|
24
|
+
* Added should_match and should_not_match (AH).
|
25
|
+
* Added a +mock+ method to Spec::Context which will create mocks that autoverify (no need to call __verify) (AH).
|
26
|
+
* Mocks now require names in the constructor to ensure sensible error messages (AH).
|
27
|
+
* Made 'spec' executable and updated usage instructions in README accordingly (AH).
|
28
|
+
* Made more parts of the Spec::Context API private to avoid accidental usage (AH).
|
29
|
+
* Added more RDoc to Spec::Context.
|
19
30
|
|
20
31
|
== Version 0.1.6
|
21
32
|
|
22
33
|
More should methods.
|
23
34
|
|
24
|
-
* Added should_match and should_not_match
|
35
|
+
* Added should_match and should_not_match (AH).
|
25
36
|
|
26
37
|
== Version 0.1.5
|
27
38
|
|
28
|
-
Included examples and tests in gem.
|
39
|
+
Included examples and tests in gem (AH).
|
29
40
|
|
30
41
|
== Version 0.1.4
|
31
42
|
|
32
|
-
More tests on block based Mock expectations
|
43
|
+
More tests on block based Mock expectations.
|
33
44
|
|
34
45
|
== Version 0.1.3
|
35
46
|
|
36
47
|
Improved mocking:
|
37
48
|
|
38
|
-
* block based Mock expectations
|
49
|
+
* block based Mock expectations.
|
39
50
|
|
40
51
|
== Version 0.1.2
|
41
52
|
|
42
53
|
This release adds some improvements to the mock API and minor syntax improvements
|
43
54
|
|
44
|
-
* Added Mock.should_expect for a more consistent DSL
|
45
|
-
* Added MockExpectation.and_returns for a better DSL
|
46
|
-
* Made Mock behave as a null object after a call to Mock.ignore_missing
|
47
|
-
* Internal syntax improvements
|
48
|
-
* Improved exception trace by adding exception class name to error message
|
49
|
-
* Renamed some tests for better consistency
|
55
|
+
* Added Mock.should_expect for a more consistent DSL (AH).
|
56
|
+
* Added MockExpectation.and_returns for a better DSL (AH).
|
57
|
+
* Made Mock behave as a null object after a call to Mock.ignore_missing (AH)
|
58
|
+
* Internal syntax improvements (AH).
|
59
|
+
* Improved exception trace by adding exception class name to error message (AH).
|
60
|
+
* Renamed some tests for better consistency (AH).
|
50
61
|
|
51
62
|
== Version 0.1.1
|
52
63
|
|
53
64
|
This release adds some shoulds and improves error reporting
|
54
65
|
|
55
|
-
* Added should_be_same_as and should_not_be_same_as
|
56
|
-
* Improved error reporting for comparison expectations
|
66
|
+
* Added should_be_same_as and should_not_be_same_as (AH).
|
67
|
+
* Improved error reporting for comparison expectations (AH).
|
57
68
|
|
58
69
|
== Version 0.1.0
|
59
70
|
|
60
71
|
This is the first preview release of RSpec, a Behaviour-Driven Development library for Ruby
|
61
72
|
|
62
|
-
* Added Rake script with tasks for gems, rdoc etc.
|
63
|
-
* Added an XForge task to make release go easier.
|
73
|
+
* Added Rake script with tasks for gems, rdoc etc (AH).
|
74
|
+
* Added an XForge task to make release go easier (AH).
|
data/README
CHANGED
@@ -11,10 +11,35 @@ from Dave himself.
|
|
11
11
|
|
12
12
|
== Download/Installation
|
13
13
|
|
14
|
+
=== Using RubyGems
|
15
|
+
|
16
|
+
sudo gem install rspec
|
17
|
+
|
18
|
+
=== Getting the latest sources
|
19
|
+
|
14
20
|
RSpec is currently being hosted in the Monotone distributed version control system. To checkout RSpec, please download and install Monotone according to the documentation on the monotone website. Then use the following set of commands to grab the latest RSpec sources.
|
15
21
|
|
16
22
|
* monotone --db=database db init
|
17
23
|
* monotone --db=database pull goliath.fundynet.ca org.rubyforge.rspec
|
18
24
|
* monotone --db=database --branch=org.rubyforge.rspec checkout RSpec
|
19
25
|
|
26
|
+
The gem can be created and installed from sources as follows:
|
27
|
+
|
28
|
+
rake gem; sudo gem install pkg/rspec_x.y.z.gem
|
29
|
+
|
20
30
|
Please visit this page periodically, it will be updated with more information as it is made available including documentation, mailing lists, bug tracking, and more. Special thanks to RubyForge for hosting this project site.
|
31
|
+
|
32
|
+
== Usage
|
33
|
+
|
34
|
+
This will also install a new executable for you, 'spec'. Now you
|
35
|
+
|
36
|
+
Do a fun dance.
|
37
|
+
|
38
|
+
spec movie_spec.rb
|
39
|
+
|
40
|
+
Do another dance.
|
41
|
+
|
42
|
+
spec *_spec.rb
|
43
|
+
|
44
|
+
This is the coolest part. Dance harder. Now drink.
|
45
|
+
|
data/Rakefile.rb
CHANGED
@@ -19,7 +19,7 @@ PKG_NAME = "rspec"
|
|
19
19
|
# (This is subject to change - AH)
|
20
20
|
#
|
21
21
|
# REMEMBER TO KEEP PKG_VERSION IN SYNC WITH CHANGELOG
|
22
|
-
PKG_VERSION = "0.1.
|
22
|
+
PKG_VERSION = "0.1.7"
|
23
23
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
24
24
|
PKG_FILES = FileList[
|
25
25
|
'[A-Z]*',
|
@@ -29,14 +29,66 @@ PKG_FILES = FileList[
|
|
29
29
|
'doc/**/*'
|
30
30
|
]
|
31
31
|
|
32
|
-
task :default => [:test
|
32
|
+
task :default => [:test, :test_craps_collector, :test_movie_collector,
|
33
|
+
:test_rspec_craps, :test_rspec_movie, :test_rspec_craps_and_movie,
|
34
|
+
:test_text_runner]
|
33
35
|
|
34
36
|
Rake::TestTask.new do |t|
|
35
37
|
t.libs << "test"
|
36
|
-
t.test_files = FileList['**/*_test.rb']
|
38
|
+
t.test_files = FileList['**/*_test.rb'].exclude("test/*_collector_test.rb",
|
39
|
+
"test/rspec_*.rb", "test/text_runner_test.rb")
|
37
40
|
t.verbose = true
|
38
41
|
end
|
39
42
|
|
43
|
+
# collector tests need to run individually
|
44
|
+
|
45
|
+
Rake::TestTask.new(:test_craps_collector) do |t|
|
46
|
+
t.libs << "test"
|
47
|
+
t.libs << "examples"
|
48
|
+
t.test_files = FileList['test/craps_collector_test.rb']
|
49
|
+
t.verbose = true
|
50
|
+
end
|
51
|
+
|
52
|
+
Rake::TestTask.new(:test_movie_collector) do |t|
|
53
|
+
t.libs << "test"
|
54
|
+
t.libs << "examples"
|
55
|
+
t.test_files = FileList['test/movie_collector_test.rb']
|
56
|
+
t.verbose = true
|
57
|
+
end
|
58
|
+
|
59
|
+
# rspec tests need to run individually
|
60
|
+
|
61
|
+
Rake::TestTask.new(:test_rspec_craps) do |t|
|
62
|
+
t.libs << "test"
|
63
|
+
t.libs << "examples"
|
64
|
+
t.test_files = FileList['test/rspec_craps_test.rb']
|
65
|
+
t.verbose = true
|
66
|
+
end
|
67
|
+
|
68
|
+
Rake::TestTask.new(:test_rspec_movie) do |t|
|
69
|
+
t.libs << "test"
|
70
|
+
t.libs << "examples"
|
71
|
+
t.test_files = FileList['test/rspec_movie_test.rb']
|
72
|
+
t.verbose = true
|
73
|
+
end
|
74
|
+
|
75
|
+
Rake::TestTask.new(:test_rspec_craps_and_movie) do |t|
|
76
|
+
t.libs << "test"
|
77
|
+
t.libs << "examples"
|
78
|
+
t.test_files = FileList['test/rspec_craps_and_movie_test.rb']
|
79
|
+
t.verbose = true
|
80
|
+
end
|
81
|
+
|
82
|
+
# text runner tests need to run individually
|
83
|
+
|
84
|
+
Rake::TestTask.new(:test_text_runner) do |t|
|
85
|
+
t.libs << "test"
|
86
|
+
t.libs << "examples"
|
87
|
+
t.test_files = FileList['test/text_runner_test.rb']
|
88
|
+
t.verbose = true
|
89
|
+
end
|
90
|
+
|
91
|
+
|
40
92
|
# Create a task to build the RDOC documentation tree.
|
41
93
|
rd = Rake::RDocTask.new("rdoc") do |rdoc|
|
42
94
|
rdoc.rdoc_dir = 'html'
|
@@ -79,6 +131,14 @@ spec = Gem::Specification.new do |s|
|
|
79
131
|
|
80
132
|
s.test_files = Dir.glob('test/tc_*.rb')
|
81
133
|
|
134
|
+
#### Make executable
|
135
|
+
s.require_path = 'lib'
|
136
|
+
s.autorequire = 'spec'
|
137
|
+
|
138
|
+
s.bindir = "bin"
|
139
|
+
s.executables = ["spec"]
|
140
|
+
s.default_executable = "spec"
|
141
|
+
|
82
142
|
#### Author and project details.
|
83
143
|
|
84
144
|
s.author = "Steven Baker"
|
data/TODO
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
- Rakefile should have an install target.
|
2
|
+
- Spec CLI needs to have a way to specify a runner.
|
3
|
+
- Rake tasks for spec running (see TestTask).
|
4
|
+
- Write specifications for the spec CLI.
|
5
|
+
- Avoid using both the 'rspec' and 'spec' names in sources and doco. It's confusing. Consider how to align with Dan North's JBehave effort in terms of name and vocabulary (AH).
|
6
|
+
- Decide whether mocks should expect messages in a particular order or not. -Or make it configurable. Ex: mock("foo", :order => "strict") (AH).
|
7
|
+
- Do we want to use an issue tracker? The one at RubyForge maybe?
|
8
|
+
- Create first class result objects instead of just Strings. This can be used to generate XML/YAML reports
|
9
|
+
which in turn can be transformed to e.g. HTML reports.
|
data/bin/spec
ADDED
data/examples/craps_spec.rb
CHANGED
@@ -4,16 +4,11 @@ require 'craps'
|
|
4
4
|
class CrapsSpecification < Spec::Context
|
5
5
|
|
6
6
|
def setup
|
7
|
-
@die1 =
|
8
|
-
@die2 =
|
7
|
+
@die1 = mock "die1"
|
8
|
+
@die2 = mock "die2"
|
9
9
|
@game = Craps.new(@die1, @die2)
|
10
10
|
end
|
11
11
|
|
12
|
-
def teardown
|
13
|
-
@die1.__verify
|
14
|
-
@die2.__verify
|
15
|
-
end
|
16
|
-
|
17
12
|
# coming out roll of 7
|
18
13
|
|
19
14
|
def come_out_roll_of_1_6_wins
|
data/lib/spec.rb
CHANGED
data/lib/spec/context.rb
CHANGED
@@ -1,32 +1,33 @@
|
|
1
1
|
require 'spec'
|
2
2
|
|
3
3
|
module Spec
|
4
|
+
# TODO: Could we try to make this a mixin (Module) instead? It would make it easier to
|
5
|
+
# create extensions that can be mixed and matched (AH).
|
4
6
|
class Context
|
5
7
|
|
6
8
|
def initialize(specification=nil)
|
7
9
|
@specification = specification
|
10
|
+
@mocks = []
|
8
11
|
end
|
9
12
|
|
10
|
-
def
|
11
|
-
result = false
|
12
|
-
|
13
|
-
result_listener.spec(@specification)
|
14
|
-
setup
|
15
|
-
begin
|
16
|
-
__send__(@specification)
|
17
|
-
result_listener.pass(@specification)
|
18
|
-
rescue Exception
|
19
|
-
result_listener.failure(@specification, $!)
|
20
|
-
end
|
21
|
-
teardown
|
22
|
-
|
23
|
-
return result
|
13
|
+
def setup
|
24
14
|
end
|
25
15
|
|
26
|
-
def
|
16
|
+
def teardown
|
27
17
|
end
|
28
18
|
|
29
|
-
|
19
|
+
# Creates a new named mock that will be automatically verified after #teardown
|
20
|
+
# has run. By using this method instead of Mock#new you don't have to worry about
|
21
|
+
# forgetting to verify your mocks.
|
22
|
+
def mock(name)
|
23
|
+
mock = Mock.new(name)
|
24
|
+
@mocks << mock
|
25
|
+
mock
|
26
|
+
end
|
27
|
+
|
28
|
+
# Immediately violates the current specification with +message+.
|
29
|
+
def violated(message="")
|
30
|
+
raise Spec::Exceptions::ExpectationNotMetError.new(message)
|
30
31
|
end
|
31
32
|
|
32
33
|
def self.collection
|
@@ -34,26 +35,46 @@ module Spec
|
|
34
35
|
self.specifications.each do |spec|
|
35
36
|
specs << self.new(spec.to_sym)
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
return specs
|
39
40
|
end
|
40
|
-
|
41
|
-
def
|
42
|
-
|
41
|
+
|
42
|
+
def run(result_listener)
|
43
|
+
result = false
|
44
|
+
|
45
|
+
result_listener.spec(@specification)
|
46
|
+
setup
|
47
|
+
begin
|
48
|
+
__send__(@specification)
|
49
|
+
result_listener.pass(@specification)
|
50
|
+
rescue Exception
|
51
|
+
result_listener.failure(@specification, $!)
|
52
|
+
ensure
|
53
|
+
teardown
|
54
|
+
verify_mocks
|
55
|
+
end
|
56
|
+
|
57
|
+
return result
|
43
58
|
end
|
44
59
|
|
60
|
+
private
|
61
|
+
|
45
62
|
def self.my_methods
|
46
63
|
self.instance_methods - self.superclass.instance_methods
|
47
64
|
end
|
48
65
|
|
49
66
|
def self.specification_name?(name)
|
50
|
-
return false
|
67
|
+
return false unless self.new.method(name).arity == 0
|
51
68
|
return false if name[0..0] == '_'
|
52
|
-
|
69
|
+
true
|
53
70
|
end
|
54
|
-
|
55
|
-
def
|
56
|
-
|
71
|
+
|
72
|
+
def self.specifications
|
73
|
+
return self.my_methods.select {|spec| self.specification_name?(spec)}
|
74
|
+
end
|
75
|
+
|
76
|
+
def verify_mocks
|
77
|
+
@mocks.each{|m| m.__verify}
|
57
78
|
end
|
58
79
|
|
59
80
|
end
|
data/lib/spec/exceptions.rb
CHANGED
data/lib/spec/expectations.rb
CHANGED
data/lib/spec/mock.rb
CHANGED
@@ -1,97 +1,127 @@
|
|
1
1
|
require 'spec'
|
2
2
|
|
3
|
-
|
4
3
|
class Mock
|
5
4
|
|
6
|
-
|
7
|
-
|
5
|
+
DEFAULT_OPTIONS = {
|
6
|
+
:null_object => false
|
7
|
+
}
|
8
|
+
# Creates a new mock with a +name+ (that will be used in error messages only)
|
9
|
+
# Options:
|
10
|
+
# * :null_object - if true, the mock object acts as a forgiving null object allowing any message to be sent to it.
|
11
|
+
def initialize(name, options={})
|
12
|
+
@name = name
|
13
|
+
@options = DEFAULT_OPTIONS.dup.merge(options)
|
14
|
+
@expectations = []
|
8
15
|
end
|
9
|
-
|
10
|
-
# How about renaming this to
|
11
|
-
#
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
|
17
|
+
# AH: How about renaming this to should_receive. This would be:
|
18
|
+
# * well aligned with the rest of the API (should)
|
19
|
+
# * emphasize the dynamic oo lingo from smalltalk using 'message' instead of 'method'
|
20
|
+
def should_receive(sym, &block)
|
21
|
+
expected_from = caller(1)[0]
|
22
|
+
expectation = MessageExpectation.new(@name, expected_from, sym, block_given? ? block : nil)
|
23
|
+
@expectations << expectation
|
24
|
+
expectation
|
15
25
|
end
|
16
|
-
alias :should_expect :__expects
|
17
26
|
|
18
27
|
def __verify
|
19
|
-
@expectations.
|
20
|
-
|
28
|
+
@expectations.each do |expectation|
|
29
|
+
expectation.verify_messages_received
|
21
30
|
end
|
22
31
|
end
|
23
|
-
|
24
|
-
# Tell the mock to act as a forgiving null object on missing methods, in which
|
25
|
-
# case it will return itself.
|
26
|
-
def ignore_missing
|
27
|
-
@ignore_missing = true
|
28
|
-
end
|
29
32
|
|
30
33
|
def method_missing(sym, *args, &block)
|
31
|
-
|
32
|
-
|
34
|
+
# TODO: use find_expectation(sym, args) which will lookup based on sym, args and strict mode.
|
35
|
+
if expectation = find_matching_expectation(sym, *args)
|
36
|
+
expectation.verify_message(args, block)
|
33
37
|
else
|
34
38
|
begin
|
35
39
|
# act as null object if method is missing and we ignore them. return value too!
|
36
|
-
@
|
40
|
+
@options[:null_object] ? self : super(sym, *args, &block)
|
37
41
|
rescue NoMethodError
|
38
|
-
raise Spec::Exceptions::MockExpectationError, "
|
42
|
+
raise Spec::Exceptions::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}'"
|
39
43
|
end
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
47
|
+
private
|
48
|
+
|
49
|
+
def find_matching_expectation(sym, *args)
|
50
|
+
expectation = @expectations.find {|expectation| expectation.matches(sym, *args)}
|
51
|
+
expectation
|
52
|
+
end
|
53
|
+
|
43
54
|
end
|
44
55
|
|
56
|
+
# Represents the expection of the reception of a message
|
57
|
+
class MessageExpectation
|
45
58
|
|
46
|
-
|
59
|
+
def initialize(mock_name, expected_from, sym, block)
|
60
|
+
@mock_name = mock_name
|
61
|
+
@expected_from = expected_from
|
62
|
+
@sym = sym
|
63
|
+
@method_block = block
|
64
|
+
@block = proc {}
|
65
|
+
@received_count = 0
|
66
|
+
@expected_received_count = 1
|
67
|
+
@expected_params = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def matches(sym, *args)
|
71
|
+
@sym == sym
|
72
|
+
end
|
47
73
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
74
|
+
# This method is called at the end of a spec, after teardown.
|
75
|
+
def verify_messages_received
|
76
|
+
# TODO: this doesn't provide good enough error messages to fix the error.
|
77
|
+
# Error msg should tell exactly what went wrong. (AH).
|
78
|
+
unless @expected_received_count == @received_count
|
79
|
+
expected_signature = nil
|
80
|
+
if @expected_params.nil?
|
81
|
+
expected_signature = @sym
|
82
|
+
else
|
83
|
+
params = @expected_params.collect{|param| "<#{param}:#{param.class.name}>"}.join(", ")
|
84
|
+
expected_signature = "#{@sym}(#{params})"
|
85
|
+
end
|
86
|
+
message = "#{@expected_from}: Mock '#{@mock_name}' expected #{expected_signature} #{@expected_received_count} times, but received it #{@received_count} times"
|
87
|
+
|
88
|
+
raise Spec::Exceptions::MockExpectationError, message
|
52
89
|
end
|
53
90
|
end
|
54
|
-
|
55
|
-
|
91
|
+
|
92
|
+
# This method is called when a method is invoked on a mock
|
93
|
+
def verify_message(args, block)
|
56
94
|
unless @method_block.nil?
|
57
95
|
begin
|
58
96
|
result = @method_block.call(*args)
|
59
97
|
rescue Spec::Exceptions::ExpectationNotMetError => detail
|
60
98
|
raise Spec::Exceptions::MockExpectationError, "Call expectation violated with: " + $!
|
61
99
|
end
|
62
|
-
@
|
100
|
+
@received_count += 1
|
63
101
|
return result
|
64
102
|
end
|
65
103
|
|
66
104
|
unless @expected_params.nil? or @expected_params == args
|
67
105
|
raise Spec::Exceptions::MockExpectationError,
|
68
|
-
|
106
|
+
"#{@sym}: Parameter mismatch: Expected <#{@expected_params}>, got <#{@args}>"
|
69
107
|
end
|
70
108
|
args << block unless block.nil?
|
71
|
-
@
|
109
|
+
@received_count += 1
|
72
110
|
@block.call(*args)
|
73
111
|
end
|
74
112
|
|
75
|
-
def initialize(block)
|
76
|
-
@method_block = block
|
77
|
-
@block = proc {}
|
78
|
-
@expected_call_count = 1
|
79
|
-
@call_count = 0
|
80
|
-
@expected_params = nil
|
81
|
-
end
|
82
|
-
|
83
113
|
def with(*args)
|
84
114
|
@expected_params = args
|
85
115
|
self
|
86
116
|
end
|
87
|
-
|
117
|
+
|
88
118
|
def with_no_args
|
89
119
|
@expected_params = []
|
90
120
|
self
|
91
121
|
end
|
92
122
|
|
93
123
|
def with_any_args
|
94
|
-
@expected_params =
|
124
|
+
@expected_params = nil
|
95
125
|
self
|
96
126
|
end
|
97
127
|
|
@@ -100,25 +130,28 @@ class MockExpectation
|
|
100
130
|
end
|
101
131
|
|
102
132
|
def never
|
103
|
-
@
|
133
|
+
@expected_received_count = 0
|
104
134
|
self
|
105
135
|
end
|
106
136
|
|
107
137
|
def once
|
108
|
-
@
|
138
|
+
@expected_received_count = 1
|
109
139
|
self
|
110
140
|
end
|
111
141
|
|
112
142
|
def twice
|
113
|
-
@
|
143
|
+
@expected_received_count = 2
|
114
144
|
self
|
115
145
|
end
|
116
146
|
|
117
147
|
def returns(value=nil,&block)
|
118
148
|
@block = block_given? ? block : proc { value }
|
119
149
|
end
|
150
|
+
# this reads better in English IMHO: (AH)
|
151
|
+
# uri_specs.should_receive(:[]).with(:overview).and_return("http://some.host/look_here/\#{path}")
|
120
152
|
alias :and_return :returns
|
121
|
-
# this reads better: (AH)
|
122
|
-
# uri_specs.should_expect(:[]).with(:overview).and_return("http://some.host/look_here/\#{path}")
|
123
153
|
|
124
154
|
end
|
155
|
+
|
156
|
+
class Counter
|
157
|
+
end
|
data/lib/spec/text_runner.rb
CHANGED
@@ -1,24 +1,15 @@
|
|
1
1
|
module Spec
|
2
2
|
class TextRunner
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
common_initialization
|
6
|
-
@output = $stdout
|
7
|
-
end
|
8
|
-
|
9
|
-
def initialize(appendable)
|
10
|
-
common_initialization
|
11
|
-
@output = appendable
|
12
|
-
end
|
13
|
-
|
14
|
-
def common_initialization
|
3
|
+
|
4
|
+
def initialize(appendable = $stdout)
|
15
5
|
@failures = Array.new
|
16
6
|
@specification_count = 0
|
17
7
|
@expectation_count = 0
|
18
8
|
@failure_count = 0
|
9
|
+
@output = appendable
|
19
10
|
end
|
20
|
-
|
21
|
-
def run(context_or_collection)
|
11
|
+
|
12
|
+
def run(context_or_collection = Spec::Collector)
|
22
13
|
start_run
|
23
14
|
context_or_collection.collection.each {|context| context.run(self)}
|
24
15
|
end_run
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
|
6
|
+
class CrapsCollectorTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
require 'examples/craps_spec'
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_collect_only_craps_specification
|
13
|
+
assert_equal CrapsSpecification.specifications.length, Spec::Collector.collection.length
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
@@ -171,21 +171,21 @@ class ErrorReportingTest < Test::Unit::TestCase
|
|
171
171
|
# should_equal
|
172
172
|
|
173
173
|
def test_should_report_standard_message_for_should_equal
|
174
|
-
assert @runner.dump_failures.include?("<Object>\nshould be equal to:\n<Class>")
|
174
|
+
assert @runner.dump_failures.include?("<Object:Class>\nshould be equal to:\n<Class:Class>"), @runner.dump_failures
|
175
175
|
end
|
176
176
|
|
177
177
|
def test_should_report_provided_message_for_should_equal
|
178
|
-
assert @runner.dump_failures.include?("provided for should_equal")
|
178
|
+
assert @runner.dump_failures.include?("provided for should_equal"), @runner.dump_failures
|
179
179
|
end
|
180
180
|
|
181
181
|
# should_not_equal
|
182
182
|
|
183
183
|
def test_should_report_standard_message_for_should_not_equal
|
184
|
-
assert @runner.dump_failures.include?("<Object>\nshould not be equal to:\n<Object>")
|
184
|
+
assert @runner.dump_failures.include?("<Object:Class>\nshould not be equal to:\n<Object:Class>"), @runner.dump_failures
|
185
185
|
end
|
186
186
|
|
187
187
|
def test_should_report_provided_message_for_should_not_equal
|
188
|
-
assert @runner.dump_failures.include?("provided for should_not_equal")
|
188
|
+
assert @runner.dump_failures.include?("provided for should_not_equal"), @runner.dump_failures
|
189
189
|
end
|
190
190
|
|
191
191
|
# should_be_nil
|
data/test/expectations_test.rb
CHANGED
@@ -342,9 +342,9 @@ class ExpectationsTest < Test::Unit::TestCase
|
|
342
342
|
# violated
|
343
343
|
|
344
344
|
def test_violated_should_raise
|
345
|
-
assert_raise
|
345
|
+
assert_raise(Spec::Exceptions::ExpectationNotMetError) do
|
346
346
|
c = Spec::Context.new
|
347
|
-
c.violated
|
347
|
+
c.violated "boo"
|
348
348
|
end
|
349
349
|
end
|
350
350
|
|
data/test/get_classes.rb
ADDED
data/test/mock_test.rb
CHANGED
@@ -1,39 +1,51 @@
|
|
1
|
+
require 'test/unit'
|
1
2
|
require 'spec'
|
2
3
|
|
3
|
-
|
4
4
|
class MockTest < Test::Unit::TestCase
|
5
5
|
|
6
6
|
def setup
|
7
|
-
@mock = Mock.new
|
7
|
+
@mock = Mock.new("test mock")
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_should_report_line_number_of_expectaion_of_unreceived_message
|
11
|
+
@mock.should_receive(:wont_happen).with("x", 3)
|
12
|
+
|
13
|
+
begin
|
14
|
+
@mock.__verify
|
15
|
+
rescue Spec::Exceptions::MockExpectationError => e
|
16
|
+
e.message.should_equal "./test/mock_test.rb:11:in `test_should_report_line_number_of_expectaion_of_unreceived_message': Mock 'test mock' expected wont_happen(<x:String>, <3:Fixnum>) 1 times, but received it 0 times"
|
17
|
+
end
|
18
|
+
|
8
19
|
end
|
9
20
|
|
10
21
|
def test_should_allow_block_to_calculate_return_values
|
11
|
-
@mock.
|
12
|
-
assert_equal "cba"
|
22
|
+
@mock.should_receive(:random_call).with("a","b","c").and_return { |a,b,c| c+b+a }
|
23
|
+
assert_equal "cba", @mock.random_call("a","b","c")
|
24
|
+
# TODO: remove __verify when migrating to self-hosting. Verify happens transparently in teardown. (AH)
|
13
25
|
@mock.__verify
|
14
26
|
end
|
15
27
|
|
16
28
|
def test_should_allow_parameter_as_return_value
|
17
|
-
@mock.
|
18
|
-
assert_equal "booh"
|
29
|
+
@mock.should_receive(:random_call).with("a","b","c").and_return("booh")
|
30
|
+
assert_equal "booh", @mock.random_call("a","b","c")
|
19
31
|
@mock.__verify
|
20
32
|
end
|
21
33
|
|
22
34
|
def test_return_nil_if_no_return_value_set
|
23
|
-
@mock.
|
35
|
+
@mock.should_receive(:random_call).with("a","b","c")
|
24
36
|
assert_nil @mock.random_call("a","b","c")
|
25
37
|
@mock.__verify
|
26
38
|
end
|
27
39
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
40
|
+
def test_should_test_multiple_calls_to_method_with_same_parameters
|
41
|
+
@mock.should_receive(:random_call).twice.with("a","b","c")
|
42
|
+
@mock.random_call("a","b","c")
|
43
|
+
@mock.random_call("a","b","c")
|
44
|
+
@mock.__verify
|
45
|
+
end
|
34
46
|
|
35
47
|
def test_should_raise_exception_if_parameters_dont_match_when_method_called
|
36
|
-
@mock.
|
48
|
+
@mock.should_receive(:random_call).with("a","b","c").and_return("booh")
|
37
49
|
assert_raise(Spec::Exceptions::MockExpectationError) {
|
38
50
|
@mock.random_call("a","d","c")
|
39
51
|
}
|
@@ -46,12 +58,14 @@ class MockTest < Test::Unit::TestCase
|
|
46
58
|
end
|
47
59
|
|
48
60
|
def test_should_allow_unexpected_methods_if_ignore_missing_set
|
49
|
-
|
50
|
-
|
61
|
+
m = Mock.new("null_object", :null_object=>true)
|
62
|
+
m.random_call("a","d","c")
|
63
|
+
m.__verify
|
51
64
|
end
|
52
65
|
|
66
|
+
# TODO: rename to should_raise_exception_telling_what_message_was_not_received
|
53
67
|
def test_should_raise_exception_on_verify_if_call_counts_not_as_expected
|
54
|
-
@mock.
|
68
|
+
@mock.should_receive(:random_call).twice.with("a","b","c").and_return("booh")
|
55
69
|
@mock.random_call("a","b","c")
|
56
70
|
assert_raise(Spec::Exceptions::MockExpectationError) do
|
57
71
|
@mock.__verify
|
@@ -59,16 +73,17 @@ class MockTest < Test::Unit::TestCase
|
|
59
73
|
end
|
60
74
|
|
61
75
|
def test_should_use_block_for_expectation_if_provided
|
62
|
-
@mock.
|
76
|
+
@mock.should_receive(:random_call) do | a, b |
|
63
77
|
a.should_equal("a")
|
64
78
|
b.should_equal("b")
|
65
79
|
"booh"
|
66
80
|
end
|
67
81
|
assert_equal("booh", @mock.random_call("a", "b"))
|
82
|
+
@mock.__verify
|
68
83
|
end
|
69
84
|
|
70
85
|
def test_failing_expectation_block_throws
|
71
|
-
@mock.
|
86
|
+
@mock.should_receive(:random_call) {| a | a.should_be_true}
|
72
87
|
assert_raise(Spec::Exceptions::MockExpectationError) do
|
73
88
|
@mock.random_call false
|
74
89
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
|
6
|
+
class MovieCollectorTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
require 'examples/movie_spec'
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_collect_only_movie_specs
|
13
|
+
specifications = EmptyMovieList.specifications.length
|
14
|
+
specifications += OneMovieList.specifications.length
|
15
|
+
assert_equal specifications, Spec::Collector.collection.length
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
require 'get_classes'
|
5
|
+
|
6
|
+
class RSpecCrapsAndMovieTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@rspec = RSpec.new(["examples/craps_spec.rb", "examples/movie_spec.rb"])
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_load_craps_and_movie_specs
|
13
|
+
assert_equal true, get_classes.include?('CrapsSpecification')
|
14
|
+
assert_equal true, get_classes.include?('EmptyMovieList')
|
15
|
+
assert_equal true, get_classes.include?('OneMovieList')
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_include_all_specifications
|
19
|
+
specifications = CrapsSpecification.collection.length
|
20
|
+
specifications += EmptyMovieList.collection.length
|
21
|
+
specifications += OneMovieList.collection.length
|
22
|
+
assert_equal specifications, Spec::Collector.collection.length
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_should_run_all_specifications
|
26
|
+
buffer = ""
|
27
|
+
@rspec.run(Spec::TextRunner.new(buffer))
|
28
|
+
assert_equal true, buffer.include?("16 specifications, 16 expectations, 0 failures")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
require 'rspec'
|
6
|
+
|
7
|
+
require 'get_classes'
|
8
|
+
|
9
|
+
class RSpecCrapsTest < Test::Unit::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@rspec = RSpec.new(["examples/craps_spec.rb"])
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_load_craps_spec
|
16
|
+
assert_equal true, get_classes.include?('CrapsSpecification')
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_not_load_movie_specs
|
20
|
+
assert_equal false, get_classes.include?('OneMovieList')
|
21
|
+
assert_equal false, get_classes.include?('EmptyMovieList')
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_include_craps_specifications
|
25
|
+
assert_equal CrapsSpecification.collection.length, Spec::Collector.collection.length
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_should_run_craps_specifications
|
29
|
+
buffer = ""
|
30
|
+
@rspec.run(Spec::TextRunner.new(buffer))
|
31
|
+
assert_equal true, buffer.include?("12 specifications, 12 expectations, 0 failures")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
require 'get_classes'
|
5
|
+
|
6
|
+
class RSpecMovieTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@rspec = RSpec.new(["examples/movie_spec.rb"])
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_load_movie_spec
|
13
|
+
assert_equal true, get_classes.include?('EmptyMovieList')
|
14
|
+
assert_equal true, get_classes.include?('OneMovieList')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_not_load_craps_spec
|
18
|
+
assert_equal false, get_classes.include?('CrapsSpecification')
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_should_include_movie_specifications
|
22
|
+
specifications = EmptyMovieList.collection.length + OneMovieList.collection.length
|
23
|
+
assert_equal specifications, Spec::Collector.collection.length
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_should_run_movie_specifications
|
27
|
+
buffer = ""
|
28
|
+
@rspec.run(Spec::TextRunner.new(buffer))
|
29
|
+
assert_equal true, buffer.include?("4 specifications, 4 expectations, 0 failures")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
data/test/text_runner_test.rb
CHANGED
@@ -100,6 +100,16 @@ class TestTextRunner < Test::Unit::TestCase
|
|
100
100
|
assert_buffer_includes "3 specifications, 3 expectations, 0 failures"
|
101
101
|
end
|
102
102
|
|
103
|
+
def test_should_run_all_specifications
|
104
|
+
@runner.run(Spec::Collector)
|
105
|
+
assert_buffer_includes "9 specifications, 9 expectations, 6 failures"
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_should_run_all_specifications_when_no_args_provided
|
109
|
+
@runner.run
|
110
|
+
assert_buffer_includes "9 specifications, 9 expectations, 6 failures"
|
111
|
+
end
|
112
|
+
|
103
113
|
def assert_buffer_includes(substring)
|
104
114
|
assert(@buffer.include?(substring), _buffer_message(substring))
|
105
115
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rspec
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2005-08-
|
6
|
+
version: 0.1.7
|
7
|
+
date: 2005-08-30 00:00:00 -04:00
|
8
8
|
summary: Behaviour Specification Framework for Ruby
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -15,8 +15,8 @@ description: "RSpec is a behaviour specification framework for Ruby. RSpec was
|
|
15
15
|
response to Dave Astels' article _A New Look at Test Driven Development_ which
|
16
16
|
can be read at: http://daveastels.com/index.php?p=5 RSpec is intended to
|
17
17
|
provide the features discussed in Dave's article."
|
18
|
-
autorequire:
|
19
|
-
default_executable:
|
18
|
+
autorequire: spec
|
19
|
+
default_executable: spec
|
20
20
|
bindir: bin
|
21
21
|
has_rdoc: true
|
22
22
|
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
@@ -36,8 +36,9 @@ files:
|
|
36
36
|
- MT
|
37
37
|
- Rakefile.rb
|
38
38
|
- README
|
39
|
-
-
|
39
|
+
- TODO
|
40
40
|
- lib/spec.rb
|
41
|
+
- lib/spec/collector.rb
|
41
42
|
- lib/spec/context.rb
|
42
43
|
- lib/spec/exceptions.rb
|
43
44
|
- lib/spec/expectations.rb
|
@@ -45,10 +46,15 @@ files:
|
|
45
46
|
- lib/spec/text_runner.rb
|
46
47
|
- test/context_fixtures_test.rb
|
47
48
|
- test/context_run_test.rb
|
49
|
+
- test/craps_collector_test.rb
|
48
50
|
- test/error_reporting_test.rb
|
49
51
|
- test/expectations_test.rb
|
52
|
+
- test/get_classes.rb
|
50
53
|
- test/mock_test.rb
|
51
|
-
- test/
|
54
|
+
- test/movie_collector_test.rb
|
55
|
+
- test/rspec_craps_and_movie_test.rb
|
56
|
+
- test/rspec_craps_test.rb
|
57
|
+
- test/rspec_movie_test.rb
|
52
58
|
- test/spec_collection_test.rb
|
53
59
|
- test/specification_identification_test.rb
|
54
60
|
- test/test_unit_ext_spec.rb
|
@@ -68,7 +74,8 @@ rdoc_options:
|
|
68
74
|
extra_rdoc_files:
|
69
75
|
- README
|
70
76
|
- CHANGES
|
71
|
-
executables:
|
77
|
+
executables:
|
78
|
+
- spec
|
72
79
|
extensions: []
|
73
80
|
requirements: []
|
74
81
|
dependencies: []
|
data/lib/rspec.rb
DELETED
data/test/rspec_test.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
|
3
|
-
require 'rspec'
|
4
|
-
|
5
|
-
$: << 'examples/'
|
6
|
-
|
7
|
-
class RSpecTest < Test::Unit::TestCase
|
8
|
-
|
9
|
-
def test_should_load_craps_spec
|
10
|
-
rspec = RSpec.new(["examples/craps_spec.rb"])
|
11
|
-
assert_equal true, get_classes.include?('CrapsSpecification')
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_should_load_movie_spec
|
15
|
-
rspec = RSpec.new(["examples/movie_spec.rb"])
|
16
|
-
assert_equal true, get_classes.include?('EmptyMovieList')
|
17
|
-
assert_equal true, get_classes.include?('OneMovieList')
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_should_load_craps_and_movie_specs
|
21
|
-
rspec = RSpec.new(["examples/craps_spec.rb", "examples/movie_spec.rb"])
|
22
|
-
assert_equal true, get_classes.include?('CrapsSpecification')
|
23
|
-
assert_equal true, get_classes.include?('EmptyMovieList')
|
24
|
-
assert_equal true, get_classes.include?('OneMovieList')
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def get_classes
|
30
|
-
classes = []
|
31
|
-
ObjectSpace.each_object(Class) {|cls| classes << cls.to_s}
|
32
|
-
classes
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|