bacon 0.9.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/COPYING +18 -0
- data/RDOX +35 -0
- data/README +227 -0
- data/Rakefile +133 -0
- data/bin/bacon +110 -0
- data/lib/bacon.rb +298 -0
- data/test/spec_bacon.rb +310 -0
- metadata +53 -0
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/RDOX
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
Bacon
|
2
|
+
- should have should.satisfy
|
3
|
+
- should have should.equal
|
4
|
+
- should have should.raise
|
5
|
+
- should have should.raise with a block
|
6
|
+
- should have a should.raise should return the exception
|
7
|
+
- should have should.be.an.instance_of
|
8
|
+
- should have should.be.nil
|
9
|
+
- should have should.include
|
10
|
+
- should have should.be.a.kind_of
|
11
|
+
- should have should.match
|
12
|
+
- should have should.not.raise
|
13
|
+
- should have should.throw
|
14
|
+
- should have should.not.satisfy
|
15
|
+
- should have should.not.equal
|
16
|
+
- should have should.not.match
|
17
|
+
- should have should.be.identical_to/same_as
|
18
|
+
- should have should.respond_to
|
19
|
+
- should have should.be.close
|
20
|
+
- should support multiple negation
|
21
|
+
- should have should.<predicate>
|
22
|
+
- should have should <operator> (>, >=, <, <=, ===)
|
23
|
+
- should allow for custom shoulds
|
24
|
+
- should have should.flunk
|
25
|
+
|
26
|
+
before/after
|
27
|
+
- should run in the right order
|
28
|
+
|
29
|
+
shared/behaves_like
|
30
|
+
- gets called where it is included
|
31
|
+
- raises NameError when the context is not found
|
32
|
+
- gets called where it is included
|
33
|
+
- can access data
|
34
|
+
|
35
|
+
28 specifications (288 requirements), 0 failures, 0 errors
|
data/README
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
= Bacon -- small RSpec clone.
|
2
|
+
|
3
|
+
"Truth will sooner come out from error than from confusion."
|
4
|
+
---Francis Bacon
|
5
|
+
|
6
|
+
Bacon is a small RSpec clone weighing less than 300 LoC but
|
7
|
+
nevertheless providing all essential features.
|
8
|
+
|
9
|
+
== Whirl-wind tour
|
10
|
+
|
11
|
+
require 'bacon'
|
12
|
+
|
13
|
+
describe 'A new array' do
|
14
|
+
before do
|
15
|
+
@ary = Array.new
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should be empty' do
|
19
|
+
@ary.should.be.empty
|
20
|
+
@ary.should.not.include 1
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have zero size' do
|
24
|
+
@ary.size.should.equal 0
|
25
|
+
@ary.size.should.be.close 0.1, 0.5
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should raise on trying fetch any index' do
|
29
|
+
lambda { @ary.fetch 0 }.
|
30
|
+
should.raise(IndexError).
|
31
|
+
message.should.match(/out of array/)
|
32
|
+
|
33
|
+
# Alternatively:
|
34
|
+
should.raise(IndexError) { @ary.fetch 0 }
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should have an object identity' do
|
38
|
+
@ary.should.not.be.same_as Array.new
|
39
|
+
end
|
40
|
+
|
41
|
+
# Custom assertions are trivial to do, they are lambdas returning a
|
42
|
+
# boolean vale:
|
43
|
+
palindrome = lambda { |obj| obj == obj.reverse }
|
44
|
+
it 'should be a palindrome' do
|
45
|
+
@ary.should.be.a palindrome
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should have super powers' do
|
49
|
+
should.flunk "no super powers found"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
Now run it:
|
54
|
+
|
55
|
+
$ bacon whirlwind.rb
|
56
|
+
A new array
|
57
|
+
- should be empty
|
58
|
+
- should have zero size
|
59
|
+
- should raise on trying fetch any index
|
60
|
+
- should have an object identity
|
61
|
+
- should be a palindrome
|
62
|
+
- should have super powers [FAILED]
|
63
|
+
|
64
|
+
Bacon::Error: no super powers found
|
65
|
+
./whirlwind.rb:39: A new array - should have super powers
|
66
|
+
./whirlwind.rb:38
|
67
|
+
./whirlwind.rb:3
|
68
|
+
|
69
|
+
6 specifications (9 requirements), 1 failures, 0 errors
|
70
|
+
|
71
|
+
If you want shorter output, use the Test::Unit format:
|
72
|
+
|
73
|
+
$ bacon -q whirlwind.rb
|
74
|
+
.....F
|
75
|
+
Bacon::Error: no super powers found
|
76
|
+
./whirlwind.rb:39: A new array - should have super powers
|
77
|
+
./whirlwind.rb:38
|
78
|
+
./whirlwind.rb:3
|
79
|
+
|
80
|
+
6 tests, 9 assertions, 1 failures, 0 errors
|
81
|
+
|
82
|
+
It also supports TAP:
|
83
|
+
|
84
|
+
$ bacon -p whirlwind.rb
|
85
|
+
ok 1 - should be empty
|
86
|
+
ok 2 - should have zero size
|
87
|
+
ok 3 - should raise on trying fetch any index
|
88
|
+
ok 4 - should have an object identity
|
89
|
+
ok 5 - should be a palindrome
|
90
|
+
not ok 6 - should have super powers: FAILED
|
91
|
+
# Bacon::Error: no super powers found
|
92
|
+
# ./whirlwind.rb:39: A new array - should have super powers
|
93
|
+
# ./whirlwind.rb:38
|
94
|
+
# ./whirlwind.rb:3
|
95
|
+
1..6
|
96
|
+
# 6 tests, 9 assertions, 1 failures, 0 errors
|
97
|
+
|
98
|
+
$ bacon -p whirlwind.rb | taptap -q
|
99
|
+
Tests took 0.00 seconds.
|
100
|
+
FAILED tests 6
|
101
|
+
6) should have super powers: FAILED
|
102
|
+
|
103
|
+
Failed 1/6 tests, 83.33% okay.
|
104
|
+
|
105
|
+
(taptap is available from http://chneukirchen.org/repos/taptap/)
|
106
|
+
|
107
|
+
|
108
|
+
== Implemented assertions
|
109
|
+
|
110
|
+
* should.<predicate> and should.be.<predicate>
|
111
|
+
* should.equal
|
112
|
+
* should.match
|
113
|
+
* should.be.identical_to / should.be.same_as
|
114
|
+
* should.raise(*exceptions) { }
|
115
|
+
* should.change { }
|
116
|
+
* should.throw(symbol) { }
|
117
|
+
* should.satisfy { |object| }
|
118
|
+
|
119
|
+
|
120
|
+
== Added core predicates
|
121
|
+
|
122
|
+
* Object#true?
|
123
|
+
* Object#false?
|
124
|
+
* Proc#change?
|
125
|
+
* Proc#raise?
|
126
|
+
* Proc#throw?
|
127
|
+
* Numeric#close?
|
128
|
+
|
129
|
+
|
130
|
+
== before/after
|
131
|
+
|
132
|
+
before and after need to be defined before the first specification in
|
133
|
+
a context and are run before and after each specification.
|
134
|
+
|
135
|
+
|
136
|
+
== Shared contexts
|
137
|
+
|
138
|
+
You can define shared contexts in Bacon like this:
|
139
|
+
|
140
|
+
shared "an empty container" do
|
141
|
+
it "should have size zero" do
|
142
|
+
end
|
143
|
+
|
144
|
+
it "should be empty" do
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "A new array" do
|
149
|
+
behaves_like "an empty container"
|
150
|
+
end
|
151
|
+
|
152
|
+
These contexts are not executed on their own, but can be included with
|
153
|
+
behaves_like in other contexts. You can use shared contexts to
|
154
|
+
structure suites with many recurring specifications.
|
155
|
+
|
156
|
+
|
157
|
+
== Matchers
|
158
|
+
|
159
|
+
Custom matchers are simply lambdas returning a boolean value, for
|
160
|
+
example:
|
161
|
+
|
162
|
+
def shorter_than(max_size)
|
163
|
+
lambda { |obj| obj.size < max_size }
|
164
|
+
end
|
165
|
+
|
166
|
+
[1,2,3].should.be shorter_than(5)
|
167
|
+
|
168
|
+
You can use modules and extend to group matchers for use in multiple
|
169
|
+
contexts.
|
170
|
+
|
171
|
+
|
172
|
+
== bacon standalone runner
|
173
|
+
|
174
|
+
-s, --specdox do AgileDox-like output (default)
|
175
|
+
-q, --quiet do Test::Unit-like non-verbose output
|
176
|
+
-p, --tap do TAP (Test Anything Protocol) output
|
177
|
+
-o, --output FORMAT do FORMAT (SpecDox/TestUnit/Tap) output
|
178
|
+
-a, --automatic gather tests from ./test/, include ./lib/
|
179
|
+
-n, --name NAME runs tests matching regexp NAME
|
180
|
+
-t, --testcase TESTCASE runs tests in TestCases matching regexp TESTCASE
|
181
|
+
|
182
|
+
If you don't want to use the standalone runner, run
|
183
|
+
Bacon.summary_on_exit to install an exit handler showing the summary.
|
184
|
+
|
185
|
+
|
186
|
+
== Object#should
|
187
|
+
|
188
|
+
You can use Object#should outside of contexts, where the result of
|
189
|
+
assertion will be returned as a boolean. This is nice for
|
190
|
+
demonstrations, quick checks and doctest tests.
|
191
|
+
|
192
|
+
>> require 'bacon'
|
193
|
+
>> (1 + 1).should.equal 2
|
194
|
+
=> true
|
195
|
+
>> (6*9).should.equal 42
|
196
|
+
=> false
|
197
|
+
|
198
|
+
|
199
|
+
== Thanks to
|
200
|
+
|
201
|
+
* Michael Fellinger, for fixing Bacon for 1.9 and various improvements.
|
202
|
+
|
203
|
+
|
204
|
+
== Contact
|
205
|
+
|
206
|
+
Please mail bugs, suggestions and patches to
|
207
|
+
<mailto:chneukirchen@gmail.com>.
|
208
|
+
|
209
|
+
Darcs repository ("darcs send" is welcome for patches):
|
210
|
+
http://chneukirchen.org/repos/bacon
|
211
|
+
|
212
|
+
|
213
|
+
== Copying
|
214
|
+
|
215
|
+
Copyright (C) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
|
216
|
+
|
217
|
+
Bacon is freely distributable under the terms of an MIT-style license.
|
218
|
+
See COPYING or http://www.opensource.org/licenses/mit-license.php.
|
219
|
+
|
220
|
+
|
221
|
+
== Links
|
222
|
+
|
223
|
+
Behavior-Driven Development:: <http://behaviour-driven.org/>
|
224
|
+
RSpec:: <http://rspec.rubyforge.org/>
|
225
|
+
test/spec:: <http://test-spec.rubyforge.org/>
|
226
|
+
|
227
|
+
Christian Neukirchen:: <http://chneukirchen.org/>
|
data/Rakefile
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Rakefile for Bacon. -*-ruby-*-
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
|
6
|
+
desc "Run all the tests"
|
7
|
+
task :default => [:test]
|
8
|
+
|
9
|
+
desc "Do predistribution stuff"
|
10
|
+
task :predist => [:chmod, :changelog, :rdoc]
|
11
|
+
|
12
|
+
|
13
|
+
desc "Make an archive as .tar.gz"
|
14
|
+
task :dist => :test do
|
15
|
+
sh "export DARCS_REPO=#{File.expand_path "."}; " +
|
16
|
+
"darcs dist -d bacon-#{get_darcs_tree_version}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Helper to retrieve the "revision number" of the darcs tree.
|
20
|
+
def get_darcs_tree_version
|
21
|
+
unless File.directory? "_darcs"
|
22
|
+
$: << "lib"
|
23
|
+
require 'bacon'
|
24
|
+
return Bacon::VERSION
|
25
|
+
end
|
26
|
+
|
27
|
+
changes = `darcs changes`
|
28
|
+
count = 0
|
29
|
+
tag = "0.0"
|
30
|
+
|
31
|
+
changes.each("\n\n") { |change|
|
32
|
+
head, title, desc = change.split("\n", 3)
|
33
|
+
|
34
|
+
if title =~ /^ \*/
|
35
|
+
# Normal change.
|
36
|
+
count += 1
|
37
|
+
elsif title =~ /tagged (.*)/
|
38
|
+
# Tag. We look for these.
|
39
|
+
tag = $1
|
40
|
+
break
|
41
|
+
else
|
42
|
+
warn "Unparsable change: #{change}"
|
43
|
+
end
|
44
|
+
}
|
45
|
+
|
46
|
+
tag + "." + count.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
def manifest
|
50
|
+
`darcs query manifest 2>/dev/null`.split("\n").map { |f| f.gsub(/\A\.\//, '') }
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
desc "Make binaries executable"
|
55
|
+
task :chmod do
|
56
|
+
Dir["bin/*"].each { |binary| File.chmod(0775, binary) }
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Generate a ChangeLog"
|
60
|
+
task :changelog do
|
61
|
+
sh "darcs changes --repo=#{ENV["DARCS_REPO"] || "."} >ChangeLog"
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
desc "Generate RDox"
|
66
|
+
task "RDOX" do
|
67
|
+
sh "bin/bacon -Ilib --automatic --specdox >RDOX"
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Run all the fast tests"
|
71
|
+
task :test do
|
72
|
+
ruby "bin/bacon -Ilib --automatic --quiet"
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
begin
|
77
|
+
$" << "sources" if defined? FromSrc
|
78
|
+
require 'rubygems'
|
79
|
+
|
80
|
+
require 'rake'
|
81
|
+
require 'rake/clean'
|
82
|
+
require 'rake/packagetask'
|
83
|
+
require 'rake/gempackagetask'
|
84
|
+
require 'fileutils'
|
85
|
+
rescue LoadError
|
86
|
+
# Too bad.
|
87
|
+
else
|
88
|
+
spec = Gem::Specification.new do |s|
|
89
|
+
s.name = "bacon"
|
90
|
+
s.version = get_darcs_tree_version
|
91
|
+
s.platform = Gem::Platform::RUBY
|
92
|
+
s.summary = "a small RSpec clone"
|
93
|
+
|
94
|
+
s.description = <<-EOF
|
95
|
+
Bacon is a small RSpec clone weighing less than 300 LoC but
|
96
|
+
nevertheless providing all essential features.
|
97
|
+
|
98
|
+
http://chneukirchen.org/repos/bacon
|
99
|
+
EOF
|
100
|
+
|
101
|
+
s.files = manifest + %w(RDOX)
|
102
|
+
s.bindir = 'bin'
|
103
|
+
s.executables << 'bacon'
|
104
|
+
s.require_path = 'lib'
|
105
|
+
s.has_rdoc = true
|
106
|
+
s.extra_rdoc_files = ['README', 'RDOX']
|
107
|
+
s.test_files = []
|
108
|
+
|
109
|
+
s.author = 'Christian Neukirchen'
|
110
|
+
s.email = 'chneukirchen@gmail.com'
|
111
|
+
s.homepage = 'http://chneukirchen.org/repos/bacon'
|
112
|
+
end
|
113
|
+
|
114
|
+
Rake::GemPackageTask.new(spec) do |p|
|
115
|
+
p.gem_spec = spec
|
116
|
+
p.need_tar = false
|
117
|
+
p.need_zip = false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "Generate RDoc documentation"
|
122
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
123
|
+
rdoc.options << '--line-numbers' << '--inline-source' <<
|
124
|
+
'--main' << 'README' <<
|
125
|
+
'--title' << 'Bacon Documentation' <<
|
126
|
+
'--charset' << 'utf-8'
|
127
|
+
rdoc.rdoc_dir = "doc"
|
128
|
+
rdoc.rdoc_files.include 'README'
|
129
|
+
rdoc.rdoc_files.include 'COPYING'
|
130
|
+
rdoc.rdoc_files.include 'RDOX'
|
131
|
+
rdoc.rdoc_files.include('lib/bacon.rb')
|
132
|
+
end
|
133
|
+
task :rdoc => ["RDOX"]
|
data/bin/bacon
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
module Bacon; end
|
6
|
+
|
7
|
+
automatic = false
|
8
|
+
output = 'SpecDoxOutput'
|
9
|
+
|
10
|
+
opts = OptionParser.new("", 24, ' ') { |opts|
|
11
|
+
opts.banner = "Usage: bacon [options] [files | -a] [-- untouched arguments]"
|
12
|
+
|
13
|
+
opts.separator ""
|
14
|
+
opts.separator "Ruby options:"
|
15
|
+
|
16
|
+
lineno = 1
|
17
|
+
opts.on("-e", "--eval LINE", "evaluate a LINE of code") { |line|
|
18
|
+
eval line, TOPLEVEL_BINDING, "-e", lineno
|
19
|
+
lineno += 1
|
20
|
+
}
|
21
|
+
|
22
|
+
opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") {
|
23
|
+
$DEBUG = true
|
24
|
+
}
|
25
|
+
opts.on("-w", "--warn", "turn warnings on for your script") {
|
26
|
+
$-w = true
|
27
|
+
}
|
28
|
+
|
29
|
+
opts.on("-I", "--include PATH",
|
30
|
+
"specify $LOAD_PATH (may be used more than once)") { |path|
|
31
|
+
$LOAD_PATH.unshift(*path.split(":"))
|
32
|
+
}
|
33
|
+
|
34
|
+
opts.on("-r", "--require LIBRARY",
|
35
|
+
"require the library, before executing your script") { |library|
|
36
|
+
require library
|
37
|
+
}
|
38
|
+
|
39
|
+
opts.separator ""
|
40
|
+
opts.separator "bacon options:"
|
41
|
+
|
42
|
+
opts.on("-s", "--specdox", "do AgileDox-like output (default)") {
|
43
|
+
output = 'SpecDoxOutput'
|
44
|
+
}
|
45
|
+
opts.on("-q", "--quiet", "do Test::Unit-like non-verbose output") {
|
46
|
+
output = 'TestUnitOutput'
|
47
|
+
}
|
48
|
+
opts.on("-p", "--tap", "do TAP (Test Anything Protocol) output") {
|
49
|
+
output = 'TapOutput'
|
50
|
+
}
|
51
|
+
|
52
|
+
opts.on("-o", "--output FORMAT",
|
53
|
+
"do FORMAT (SpecDox/TestUnit/Tap) output") { |format|
|
54
|
+
output = format + "Output"
|
55
|
+
}
|
56
|
+
|
57
|
+
opts.on("-a", "--automatic", "gather tests from ./test/, include ./lib/") {
|
58
|
+
$LOAD_PATH.unshift "lib" if File.directory? "lib"
|
59
|
+
automatic = true
|
60
|
+
}
|
61
|
+
|
62
|
+
opts.on('-n', '--name NAME', String,
|
63
|
+
"runs tests matching regexp NAME") { |n|
|
64
|
+
Bacon.const_set :RestrictName, Regexp.new(n)
|
65
|
+
}
|
66
|
+
|
67
|
+
opts.on('-t', '--testcase TESTCASE', String,
|
68
|
+
"runs tests in TestCases matching regexp TESTCASE") { |t|
|
69
|
+
Bacon.const_set :RestrictContext, Regexp.new(t)
|
70
|
+
}
|
71
|
+
|
72
|
+
opts.separator ""
|
73
|
+
opts.separator "Common options:"
|
74
|
+
|
75
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
76
|
+
puts opts
|
77
|
+
exit
|
78
|
+
end
|
79
|
+
|
80
|
+
opts.on_tail("--version", "Show version") do
|
81
|
+
require 'bacon'
|
82
|
+
puts "bacon #{Bacon::VERSION}"
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
|
86
|
+
opts.parse! ARGV
|
87
|
+
}
|
88
|
+
|
89
|
+
files = ARGV
|
90
|
+
|
91
|
+
if automatic
|
92
|
+
files.concat Dir["test/test_*.rb"]
|
93
|
+
files.concat Dir["test/spec_*.rb"]
|
94
|
+
files.concat Dir["spec/spec_*.rb"]
|
95
|
+
end
|
96
|
+
|
97
|
+
if files.empty?
|
98
|
+
puts opts.banner
|
99
|
+
exit 1
|
100
|
+
end
|
101
|
+
|
102
|
+
require 'bacon'
|
103
|
+
|
104
|
+
Bacon.extend Bacon.const_get(output) rescue abort "No such formatter: #{output}"
|
105
|
+
Bacon.summary_on_exit
|
106
|
+
|
107
|
+
files.each { |file|
|
108
|
+
load file
|
109
|
+
}
|
110
|
+
|
data/lib/bacon.rb
ADDED
@@ -0,0 +1,298 @@
|
|
1
|
+
# Bacon -- small RSpec clone.
|
2
|
+
#
|
3
|
+
# "Truth will sooner come out from error than from confusion." ---Francis Bacon
|
4
|
+
|
5
|
+
# Copyright (C) 2007, 2008 Christian Neukirchen <purl.org/net/chneukirchen>
|
6
|
+
#
|
7
|
+
# Bacon is freely distributable under the terms of an MIT-style license.
|
8
|
+
# See COPYING or http://www.opensource.org/licenses/mit-license.php.
|
9
|
+
|
10
|
+
module Bacon
|
11
|
+
VERSION = "0.9"
|
12
|
+
|
13
|
+
Counter = Hash.new(0)
|
14
|
+
ErrorLog = ""
|
15
|
+
Shared = Hash.new { |_, name|
|
16
|
+
raise NameError, "no such context: #{name.inspect}"
|
17
|
+
}
|
18
|
+
|
19
|
+
RestrictName = // unless defined? RestrictName
|
20
|
+
RestrictContext = // unless defined? RestrictContext
|
21
|
+
|
22
|
+
def self.summary_on_exit
|
23
|
+
return if Counter[:installed_summary] > 0
|
24
|
+
at_exit {
|
25
|
+
handle_summary
|
26
|
+
if $!
|
27
|
+
raise $!
|
28
|
+
elsif Counter[:errors] + Counter[:failed] > 0
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
}
|
32
|
+
Counter[:installed_summary] += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
module SpecDoxOutput
|
36
|
+
def handle_specification(name)
|
37
|
+
puts name
|
38
|
+
yield
|
39
|
+
puts
|
40
|
+
end
|
41
|
+
|
42
|
+
def handle_requirement(description)
|
43
|
+
print "- #{description}"
|
44
|
+
error = yield
|
45
|
+
puts error.empty? ? "" : " [#{error}]"
|
46
|
+
end
|
47
|
+
|
48
|
+
def handle_summary
|
49
|
+
print ErrorLog
|
50
|
+
puts "%d specifications (%d requirements), %d failures, %d errors" %
|
51
|
+
Counter.values_at(:specifications, :requirements, :failed, :errors)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module TestUnitOutput
|
56
|
+
def handle_specification(name) yield end
|
57
|
+
|
58
|
+
def handle_requirement(description)
|
59
|
+
error = yield
|
60
|
+
if error.empty?
|
61
|
+
print "."
|
62
|
+
else
|
63
|
+
print error[0..0]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def handle_summary
|
68
|
+
puts "", ErrorLog
|
69
|
+
puts "%d tests, %d assertions, %d failures, %d errors" %
|
70
|
+
Counter.values_at(:specifications, :requirements, :failed, :errors)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module TapOutput
|
75
|
+
def handle_specification(name) yield end
|
76
|
+
|
77
|
+
def handle_requirement(description)
|
78
|
+
ErrorLog.replace ""
|
79
|
+
error = yield
|
80
|
+
if error.empty?
|
81
|
+
printf "ok %-3d - %s\n" % [Counter[:specifications], description]
|
82
|
+
else
|
83
|
+
printf "not ok %d - %s: %s\n" %
|
84
|
+
[Counter[:specifications], description, error]
|
85
|
+
puts ErrorLog.strip.gsub(/^/, '# ')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def handle_summary
|
90
|
+
puts "1..#{Counter[:specifications]}"
|
91
|
+
puts "# %d tests, %d assertions, %d failures, %d errors" %
|
92
|
+
Counter.values_at(:specifications, :requirements, :failed, :errors)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
extend SpecDoxOutput # default
|
97
|
+
|
98
|
+
class Error < RuntimeError
|
99
|
+
attr_accessor :count_as
|
100
|
+
|
101
|
+
def initialize(count_as, message)
|
102
|
+
@count_as = count_as
|
103
|
+
super message
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
class Context
|
108
|
+
def initialize(name, &block)
|
109
|
+
@name = name
|
110
|
+
@before, @after = [], []
|
111
|
+
|
112
|
+
return unless name =~ RestrictContext
|
113
|
+
Bacon.handle_specification(name) { instance_eval(&block) }
|
114
|
+
end
|
115
|
+
|
116
|
+
def before(&block); @before << block; end
|
117
|
+
def after(&block); @after << block; end
|
118
|
+
|
119
|
+
def behaves_like(*names)
|
120
|
+
names.each { |name| instance_eval(&Shared[name]) }
|
121
|
+
end
|
122
|
+
|
123
|
+
def it(description, &block)
|
124
|
+
return unless description =~ RestrictName
|
125
|
+
Counter[:specifications] += 1
|
126
|
+
run_requirement description, block
|
127
|
+
end
|
128
|
+
|
129
|
+
def run_requirement(description, spec)
|
130
|
+
Bacon.handle_requirement description do
|
131
|
+
begin
|
132
|
+
Counter[:depth] += 1
|
133
|
+
@before.each { |block| instance_eval(&block) }
|
134
|
+
instance_eval(&spec)
|
135
|
+
@after.each { |block| instance_eval(&block) }
|
136
|
+
rescue Object => e
|
137
|
+
ErrorLog << "#{e.class}: #{e.message}\n"
|
138
|
+
e.backtrace.find_all { |line| line !~ /bin\/bacon|\/bacon\.rb:\d+/ }.
|
139
|
+
each_with_index { |line, i|
|
140
|
+
ErrorLog << "\t#{line}#{i==0 ? ": #@name - #{description}" : ""}\n"
|
141
|
+
}
|
142
|
+
ErrorLog << "\n"
|
143
|
+
|
144
|
+
if e.kind_of? Error
|
145
|
+
Counter[e.count_as] += 1
|
146
|
+
e.count_as.to_s.upcase
|
147
|
+
else
|
148
|
+
Counter[:errors] += 1
|
149
|
+
"ERROR: #{e.class}"
|
150
|
+
end
|
151
|
+
else
|
152
|
+
""
|
153
|
+
ensure
|
154
|
+
Counter[:depth] -= 1
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def raise?(*args, &block); block.raise?(*args); end
|
160
|
+
def throw?(*args, &block); block.throw?(*args); end
|
161
|
+
def change?(*args, &block); block.change?(*args); end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
class Object
|
167
|
+
def true?; false; end
|
168
|
+
def false?; false; end
|
169
|
+
end
|
170
|
+
|
171
|
+
class TrueClass
|
172
|
+
def true?; true; end
|
173
|
+
end
|
174
|
+
|
175
|
+
class FalseClass
|
176
|
+
def false?; true; end
|
177
|
+
end
|
178
|
+
|
179
|
+
class Proc
|
180
|
+
def raise?(*exceptions)
|
181
|
+
exceptions << RuntimeError if exceptions.empty?
|
182
|
+
call
|
183
|
+
|
184
|
+
# Only to work in 1.9.0, rescue with splat doesn't work there right now
|
185
|
+
rescue Object => e
|
186
|
+
case e
|
187
|
+
when *exceptions
|
188
|
+
e
|
189
|
+
else
|
190
|
+
raise e
|
191
|
+
end
|
192
|
+
else
|
193
|
+
false
|
194
|
+
end
|
195
|
+
|
196
|
+
def throw?(sym)
|
197
|
+
catch(sym) {
|
198
|
+
call
|
199
|
+
return false
|
200
|
+
}
|
201
|
+
return true
|
202
|
+
end
|
203
|
+
|
204
|
+
def change?
|
205
|
+
pre_result = yield
|
206
|
+
called = call
|
207
|
+
post_result = yield
|
208
|
+
pre_result != post_result
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
class Numeric
|
213
|
+
def close?(to, delta)
|
214
|
+
(to.to_f - self).abs <= delta.to_f rescue false
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
class Object
|
220
|
+
def should(*args, &block) Should.new(self).be(*args, &block) end
|
221
|
+
end
|
222
|
+
|
223
|
+
module Kernel
|
224
|
+
private
|
225
|
+
|
226
|
+
def describe(name, &block) Bacon::Context.new(name, &block) end
|
227
|
+
def shared(name, &block) Bacon::Shared[name] = block end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
class Should
|
232
|
+
# Kills ==, ===, =~, eql?, equal?, frozen?, instance_of?, is_a?,
|
233
|
+
# kind_of?, nil?, respond_to?, tainted?
|
234
|
+
instance_methods.each { |method|
|
235
|
+
undef_method method if method =~ /\?|^\W+$/
|
236
|
+
}
|
237
|
+
|
238
|
+
def initialize(object)
|
239
|
+
@object = object
|
240
|
+
@negated = false
|
241
|
+
end
|
242
|
+
|
243
|
+
def not(*args, &block)
|
244
|
+
@negated = !@negated
|
245
|
+
|
246
|
+
if args.empty?
|
247
|
+
self
|
248
|
+
else
|
249
|
+
be(*args, &block)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def be(*args, &block)
|
254
|
+
if args.empty?
|
255
|
+
self
|
256
|
+
else
|
257
|
+
block = args.shift unless block_given?
|
258
|
+
satisfy(*args, &block)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
alias a be
|
263
|
+
alias an be
|
264
|
+
|
265
|
+
def satisfy(*args, &block)
|
266
|
+
if args.size == 1 && String === args.first
|
267
|
+
description = args.shift
|
268
|
+
else
|
269
|
+
description = ""
|
270
|
+
end
|
271
|
+
|
272
|
+
r = yield(@object, *args)
|
273
|
+
if Bacon::Counter[:depth] > 0
|
274
|
+
raise Bacon::Error.new(:failed, description) unless @negated ^ r
|
275
|
+
Bacon::Counter[:requirements] += 1
|
276
|
+
end
|
277
|
+
@negated ^ r ? r : false
|
278
|
+
end
|
279
|
+
|
280
|
+
def method_missing(name, *args, &block)
|
281
|
+
name = "#{name}?" if name.to_s =~ /\w[^?]\z/
|
282
|
+
|
283
|
+
desc = @negated ? "not " : ""
|
284
|
+
desc << @object.inspect << "." << name.to_s
|
285
|
+
desc << "(" << args.map{|x|x.inspect}.join(", ") << ") failed"
|
286
|
+
|
287
|
+
satisfy(desc) { |x| x.__send__(name, *args, &block) }
|
288
|
+
end
|
289
|
+
|
290
|
+
def equal(value) self == value end
|
291
|
+
def match(value) self =~ value end
|
292
|
+
def identical_to(value) self.equal? value end
|
293
|
+
alias same_as identical_to
|
294
|
+
|
295
|
+
def flunk(reason="Flunked")
|
296
|
+
raise Bacon::Error.new(:failed, reason)
|
297
|
+
end
|
298
|
+
end
|
data/test/spec_bacon.rb
ADDED
@@ -0,0 +1,310 @@
|
|
1
|
+
$: << File.dirname(__FILE__) + '/../lib/'
|
2
|
+
require 'bacon'
|
3
|
+
|
4
|
+
# Hooray for meta-testing.
|
5
|
+
module MetaTests
|
6
|
+
def succeed
|
7
|
+
lambda { |block|
|
8
|
+
block.should.not.raise Bacon::Error
|
9
|
+
true
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def fail
|
14
|
+
lambda { |block|
|
15
|
+
block.should.raise Bacon::Error
|
16
|
+
true
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def equal_string(x)
|
21
|
+
lambda { |s|
|
22
|
+
x == s.to_s
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "Bacon" do
|
28
|
+
extend MetaTests
|
29
|
+
|
30
|
+
it "should have should.satisfy" do
|
31
|
+
lambda { should.satisfy { 1 == 1 } }.should succeed
|
32
|
+
lambda { should.satisfy { 1 } }.should succeed
|
33
|
+
|
34
|
+
lambda { should.satisfy { 1 == 2 } }.should fail
|
35
|
+
lambda { should.satisfy { false } }.should fail
|
36
|
+
lambda { should.satisfy { false } }.should fail
|
37
|
+
|
38
|
+
lambda { 1.should.satisfy { |n| n % 2 == 0 } }.should fail
|
39
|
+
lambda { 2.should.satisfy { |n| n % 2 == 0 } }.should succeed
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should have should.equal" do
|
43
|
+
lambda { "string1".should == "string1" }.should succeed
|
44
|
+
lambda { "string1".should == "string2" }.should fail
|
45
|
+
lambda { "1".should == 1 }.should fail
|
46
|
+
|
47
|
+
lambda { "string1".should.equal "string1" }.should succeed
|
48
|
+
lambda { "string1".should.equal "string2" }.should fail
|
49
|
+
lambda { "1".should.equal 1 }.should fail
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should have should.raise" do
|
53
|
+
lambda { lambda { raise "Error" }.should.raise }.should succeed
|
54
|
+
lambda { lambda { raise "Error" }.should.raise RuntimeError }.should succeed
|
55
|
+
lambda { lambda { raise "Error" }.should.not.raise }.should fail
|
56
|
+
lambda { lambda { raise "Error" }.should.not.raise(RuntimeError) }.should fail
|
57
|
+
|
58
|
+
lambda { lambda { 1 + 1 }.should.raise }.should fail
|
59
|
+
lambda {
|
60
|
+
lambda { raise "Error" }.should.raise(Interrupt)
|
61
|
+
}.should.raise
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should have should.raise with a block" do
|
65
|
+
lambda { should.raise { raise "Error" } }.should succeed
|
66
|
+
lambda { should.raise(RuntimeError) { raise "Error" } }.should succeed
|
67
|
+
lambda { should.not.raise { raise "Error" } }.should fail
|
68
|
+
lambda { should.not.raise(RuntimeError) { raise "Error" } }.should fail
|
69
|
+
|
70
|
+
lambda { should.raise { 1 + 1 } }.should fail
|
71
|
+
lambda {
|
72
|
+
should.raise(Interrupt) { raise "Error" }
|
73
|
+
}.should.raise
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should have a should.raise should return the exception" do
|
77
|
+
ex = lambda { raise "foo!" }.should.raise
|
78
|
+
ex.should.be.kind_of RuntimeError
|
79
|
+
ex.message.should =~ /foo/
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should have should.be.an.instance_of" do
|
83
|
+
lambda { "string".should.be.instance_of String }.should succeed
|
84
|
+
lambda { "string".should.be.instance_of Hash }.should fail
|
85
|
+
|
86
|
+
lambda { "string".should.be.an.instance_of String }.should succeed
|
87
|
+
lambda { "string".should.be.an.instance_of Hash }.should fail
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should have should.be.nil" do
|
91
|
+
lambda { nil.should.be.nil }.should succeed
|
92
|
+
lambda { nil.should.not.be.nil }.should fail
|
93
|
+
lambda { "foo".should.be.nil }.should fail
|
94
|
+
lambda { "foo".should.not.be.nil }.should succeed
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should have should.include" do
|
98
|
+
lambda { [1,2,3].should.include 2 }.should succeed
|
99
|
+
lambda { [1,2,3].should.include 4 }.should fail
|
100
|
+
|
101
|
+
lambda { {1=>2, 3=>4}.should.include 1 }.should succeed
|
102
|
+
lambda { {1=>2, 3=>4}.should.include 2 }.should fail
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should have should.be.a.kind_of" do
|
106
|
+
lambda { Array.should.be.kind_of Module }.should succeed
|
107
|
+
lambda { "string".should.be.kind_of Object }.should succeed
|
108
|
+
lambda { 1.should.be.kind_of Comparable }.should succeed
|
109
|
+
|
110
|
+
lambda { Array.should.be.a.kind_of Module }.should succeed
|
111
|
+
|
112
|
+
lambda { "string".should.be.a.kind_of Class }.should fail
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should have should.match" do
|
116
|
+
lambda { "string".should.match(/strin./) }.should succeed
|
117
|
+
lambda { "string".should =~ /strin./ }.should succeed
|
118
|
+
|
119
|
+
lambda { "string".should.match(/slin./) }.should fail
|
120
|
+
lambda { "string".should =~ /slin./ }.should fail
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should have should.not.raise" do
|
124
|
+
lambda { lambda { 1 + 1 }.should.not.raise }.should succeed
|
125
|
+
lambda { lambda { 1 + 1 }.should.not.raise(Interrupt) }.should succeed
|
126
|
+
|
127
|
+
lambda {
|
128
|
+
lambda {
|
129
|
+
lambda {
|
130
|
+
Kernel.raise ZeroDivisionError.new("ArgumentError")
|
131
|
+
}.should.not.raise(RuntimeError, Comparable)
|
132
|
+
}.should.raise ZeroDivisionError
|
133
|
+
}.should succeed
|
134
|
+
|
135
|
+
lambda { lambda { raise "Error" }.should.not.raise }.should fail
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should have should.throw" do
|
139
|
+
lambda { lambda { throw :foo }.should.throw(:foo) }.should succeed
|
140
|
+
lambda { lambda { :foo }.should.throw(:foo) }.should fail
|
141
|
+
|
142
|
+
should.throw(:foo) { throw :foo }
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should have should.not.satisfy" do
|
146
|
+
lambda { should.not.satisfy { 1 == 2 } }.should succeed
|
147
|
+
lambda { should.not.satisfy { 1 == 1 } }.should fail
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should have should.not.equal" do
|
151
|
+
lambda { "string1".should.not == "string2" }.should succeed
|
152
|
+
lambda { "string1".should.not == "string1" }.should fail
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should have should.not.match" do
|
156
|
+
lambda { "string".should.not.match(/sling/) }.should succeed
|
157
|
+
lambda { "string".should.not.match(/string/) }.should fail
|
158
|
+
# lambda { "string".should.not.match("strin") }.should fail
|
159
|
+
|
160
|
+
lambda { "string".should.not =~ /sling/ }.should succeed
|
161
|
+
lambda { "string".should.not =~ /string/ }.should fail
|
162
|
+
# lambda { "string".should.not =~ "strin" }.should fail
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should have should.be.identical_to/same_as" do
|
166
|
+
lambda { s = "string"; s.should.be.identical_to s }.should succeed
|
167
|
+
lambda { "string".should.be.identical_to "string" }.should fail
|
168
|
+
|
169
|
+
lambda { s = "string"; s.should.be.same_as s }.should succeed
|
170
|
+
lambda { "string".should.be.same_as "string" }.should fail
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should have should.respond_to" do
|
174
|
+
lambda { "foo".should.respond_to :to_s }.should succeed
|
175
|
+
lambda { 5.should.respond_to :to_str }.should fail
|
176
|
+
lambda { :foo.should.respond_to :nx }.should fail
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should have should.be.close" do
|
180
|
+
lambda { 1.4.should.be.close 1.4, 0 }.should succeed
|
181
|
+
lambda { 0.4.should.be.close 0.5, 0.1 }.should succeed
|
182
|
+
|
183
|
+
lambda { 0.4.should.be.close 0.5, 0.05 }.should fail
|
184
|
+
lambda { 0.4.should.be.close Object.new, 0.1 }.should fail
|
185
|
+
lambda { 0.4.should.be.close 0.5, -0.1 }.should fail
|
186
|
+
end
|
187
|
+
|
188
|
+
it "should support multiple negation" do
|
189
|
+
lambda { 1.should.equal 1 }.should succeed
|
190
|
+
lambda { 1.should.not.equal 1 }.should fail
|
191
|
+
lambda { 1.should.not.not.equal 1 }.should succeed
|
192
|
+
lambda { 1.should.not.not.not.equal 1 }.should fail
|
193
|
+
|
194
|
+
lambda { 1.should.equal 2 }.should fail
|
195
|
+
lambda { 1.should.not.equal 2 }.should succeed
|
196
|
+
lambda { 1.should.not.not.equal 2 }.should fail
|
197
|
+
lambda { 1.should.not.not.not.equal 2 }.should succeed
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should have should.<predicate>" do
|
201
|
+
lambda { [].should.be.empty }.should succeed
|
202
|
+
lambda { [1,2,3].should.not.be.empty }.should succeed
|
203
|
+
|
204
|
+
lambda { [].should.not.be.empty }.should fail
|
205
|
+
lambda { [1,2,3].should.be.empty }.should fail
|
206
|
+
|
207
|
+
lambda { {1=>2, 3=>4}.should.has_key 1 }.should succeed
|
208
|
+
lambda { {1=>2, 3=>4}.should.not.has_key 2 }.should succeed
|
209
|
+
|
210
|
+
lambda { nil.should.bla }.should.raise(NoMethodError)
|
211
|
+
lambda { nil.should.not.bla }.should.raise(NoMethodError)
|
212
|
+
end
|
213
|
+
|
214
|
+
it "should have should <operator> (>, >=, <, <=, ===)" do
|
215
|
+
lambda { 2.should.be > 1 }.should succeed
|
216
|
+
lambda { 1.should.be > 2 }.should fail
|
217
|
+
|
218
|
+
lambda { 1.should.be < 2 }.should succeed
|
219
|
+
lambda { 2.should.be < 1 }.should fail
|
220
|
+
|
221
|
+
lambda { 2.should.be >= 1 }.should succeed
|
222
|
+
lambda { 2.should.be >= 2 }.should succeed
|
223
|
+
lambda { 2.should.be >= 2.1 }.should fail
|
224
|
+
|
225
|
+
lambda { 2.should.be <= 1 }.should fail
|
226
|
+
lambda { 2.should.be <= 2 }.should succeed
|
227
|
+
lambda { 2.should.be <= 2.1 }.should succeed
|
228
|
+
|
229
|
+
lambda { Array.should === [1,2,3] }.should succeed
|
230
|
+
lambda { Integer.should === [1,2,3] }.should fail
|
231
|
+
|
232
|
+
lambda { /foo/.should === "foobar" }.should succeed
|
233
|
+
lambda { "foobar".should === /foo/ }.should fail
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should allow for custom shoulds" do
|
237
|
+
lambda { (1+1).should equal_string("2") }.should succeed
|
238
|
+
lambda { (1+2).should equal_string("2") }.should fail
|
239
|
+
|
240
|
+
lambda { (1+1).should.be equal_string("2") }.should succeed
|
241
|
+
lambda { (1+2).should.be equal_string("2") }.should fail
|
242
|
+
|
243
|
+
lambda { (1+1).should.not equal_string("2") }.should fail
|
244
|
+
lambda { (1+2).should.not equal_string("2") }.should succeed
|
245
|
+
lambda { (1+2).should.not.not equal_string("2") }.should fail
|
246
|
+
|
247
|
+
lambda { (1+1).should.not.be equal_string("2") }.should fail
|
248
|
+
lambda { (1+2).should.not.be equal_string("2") }.should succeed
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should have should.flunk" do
|
252
|
+
lambda { should.flunk }.should fail
|
253
|
+
lambda { should.flunk "yikes" }.should fail
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe "before/after" do
|
258
|
+
before do
|
259
|
+
@a = 1
|
260
|
+
@b = 2
|
261
|
+
end
|
262
|
+
|
263
|
+
before do
|
264
|
+
@a = 2
|
265
|
+
end
|
266
|
+
|
267
|
+
after do
|
268
|
+
@a.should.equal 2
|
269
|
+
@a = 3
|
270
|
+
end
|
271
|
+
|
272
|
+
after do
|
273
|
+
@a.should.equal 3
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should run in the right order" do
|
277
|
+
@a.should.equal 2
|
278
|
+
@b.should.equal 2
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
shared "a shared context" do
|
283
|
+
it "gets called where it is included" do
|
284
|
+
true.should.be.true
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
shared "another shared context" do
|
289
|
+
it "can access data" do
|
290
|
+
@magic.should.be.equal 42
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
describe "shared/behaves_like" do
|
295
|
+
behaves_like "a shared context"
|
296
|
+
|
297
|
+
ctx = self
|
298
|
+
it "raises NameError when the context is not found" do
|
299
|
+
lambda {
|
300
|
+
ctx.behaves_like "whoops"
|
301
|
+
}.should.raise NameError
|
302
|
+
end
|
303
|
+
|
304
|
+
behaves_like "a shared context"
|
305
|
+
|
306
|
+
before {
|
307
|
+
@magic = 42
|
308
|
+
}
|
309
|
+
behaves_like "another shared context"
|
310
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4
|
3
|
+
specification_version: 1
|
4
|
+
name: bacon
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.9.0
|
7
|
+
date: 2008-01-07 00:00:00 +01:00
|
8
|
+
summary: a small RSpec clone
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: chneukirchen@gmail.com
|
12
|
+
homepage: http://chneukirchen.org/repos/bacon
|
13
|
+
rubyforge_project:
|
14
|
+
description: Bacon is a small RSpec clone weighing less than 300 LoC but nevertheless providing all essential features. http://chneukirchen.org/repos/bacon
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Christian Neukirchen
|
31
|
+
files:
|
32
|
+
- bin/bacon
|
33
|
+
- COPYING
|
34
|
+
- lib/bacon.rb
|
35
|
+
- Rakefile
|
36
|
+
- README
|
37
|
+
- test/spec_bacon.rb
|
38
|
+
- RDOX
|
39
|
+
test_files: []
|
40
|
+
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
extra_rdoc_files:
|
44
|
+
- README
|
45
|
+
- RDOX
|
46
|
+
executables:
|
47
|
+
- bacon
|
48
|
+
extensions: []
|
49
|
+
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
dependencies: []
|
53
|
+
|