clean_test 0.11.0 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +15 -8
- data/Rakefile +52 -6
- data/clean_test.gemspec +1 -0
- data/lib/clean_test/any.rb +45 -112
- data/lib/clean_test/given_when_then.rb +68 -98
- data/lib/clean_test/version.rb +1 -1
- data/test/test_any.rb +0 -51
- data/test/{test_simple_given.rb → test_given_when_then.rb} +23 -1
- metadata +99 -37
data/README.rdoc
CHANGED
@@ -8,6 +8,9 @@ Get your Test::Unit test cases readable and fluent, without RSpec, magic, or cra
|
|
8
8
|
|
9
9
|
This library is a set of small, simple tools to make your Test::Unit test cases easy to understand. This isn't a massive change in how you write tests, but simply some helpful things will make your tests easier to read.
|
10
10
|
|
11
|
+
* {Source}[http://www.github.com/davetron5000/clean_test]
|
12
|
+
* {RDoc}[http://davetron5000.github.com/clean_test/rdoc]
|
13
|
+
|
11
14
|
The main problems this library solves are:
|
12
15
|
|
13
16
|
* Understanding what part of a test method is setup, test, and evaluation
|
@@ -94,7 +97,7 @@ But, don't fret, this is not an all-or-nothing proposition. Use whichever parts
|
|
94
97
|
|
95
98
|
I'm tired of unreadable tests. Tests should be good, clean code, and it shoud be easy to see what's being tested. This is especially important when there is a lot of setup required to simulate something.
|
96
99
|
|
97
|
-
I also don't believe we need to resort
|
100
|
+
I also don't believe we need to resort to a lot of metaprogramming tricks just to get our tests in this shape. RSpec, for example, creates strange constructs for things that are much more straightforward in plain Ruby. I like Test::Unit, and with just a bit of helper methods, we can make nice, readable tests, using just Ruby.
|
98
101
|
|
99
102
|
=== But the test methods are longer!
|
100
103
|
|
@@ -260,11 +263,11 @@ In both cases, the language is the same, and the person is slightly different.
|
|
260
263
|
|
261
264
|
=== What did that have to do with this gem?
|
262
265
|
|
263
|
-
Nothing. That's the point. You have the power already.
|
266
|
+
Nothing. That's the point. You have the power already. That being said, +Given+ and friends can take a symbol representing the name of a method to call, in lieu of a block:
|
264
267
|
|
265
268
|
class SalutationTest << Clean::Test::TestCase
|
266
269
|
test_that "greeting works" do
|
267
|
-
Given english_salutation_for
|
270
|
+
Given :english_salutation_for,male_with_first_name("David")
|
268
271
|
When {
|
269
272
|
@greeting = @salutation.greeting
|
270
273
|
}
|
@@ -274,7 +277,7 @@ Nothing. That's the point. You have the power already. Note that, since +Give
|
|
274
277
|
end
|
275
278
|
|
276
279
|
test_that "greeting works for no first name" do
|
277
|
-
Given english_salutation_for(
|
280
|
+
Given :english_salutation_for,male_with_no_first_name("Copeland")
|
278
281
|
When {
|
279
282
|
@greeting = @salutation.greeting
|
280
283
|
}
|
@@ -293,13 +296,10 @@ Nothing. That's the point. You have the power already. Note that, since +Give
|
|
293
296
|
end
|
294
297
|
|
295
298
|
def english_salutation_for(person)
|
296
|
-
|
297
|
-
@salutation = Salutation.new(person,Language.new("English","en"))
|
298
|
-
}
|
299
|
+
@salutation = Salutation.new(person,Language.new("English","en"))
|
299
300
|
end
|
300
301
|
end
|
301
302
|
|
302
|
-
This sort of thing can get confusing, but sometimes works well.
|
303
303
|
|
304
304
|
=== Why Any instead of Faker?
|
305
305
|
|
@@ -314,6 +314,13 @@ Again, FactoryGirl goes through metaprogramming hoops to do something we can alr
|
|
314
314
|
|
315
315
|
Further, the +Any+ module is extensible, in that you can do stuff like <tt>any Person</tt>, but you can, and should, just use methods. Any helps out with primitives that we tend to use a lot: numbers and strings. It's just simpler and, with less moving parts, more predictable. This means you spend more time on your tests than on your test infrastructure.
|
316
316
|
|
317
|
+
=== Any uses random numbers and strings. Tests aren't repeatable!
|
318
|
+
|
319
|
+
You can make them repeatable by explicitly setting the random seed to a literal value. Also, including Any will record
|
320
|
+
the random seed used and output it. You can then set +RANDOM_SEED+ in the environment to re-run he tests using that seed.
|
321
|
+
|
322
|
+
Keep in mind that if _any_ value will work, random values shouldn't be a problem.
|
323
|
+
|
317
324
|
=== What about not using the base class?
|
318
325
|
|
319
326
|
To use Any on its own:
|
data/Rakefile
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'bundler'
|
2
|
-
gem 'rdoc' # I need to use the installed RDoc gem, not what comes with the system
|
3
2
|
require 'rake/clean'
|
4
3
|
require 'rake/testtask'
|
5
|
-
require '
|
4
|
+
require 'sdoc'
|
6
5
|
|
7
6
|
include Rake::DSL
|
8
7
|
|
@@ -17,12 +16,59 @@ Rake::TestTask.new do |t|
|
|
17
16
|
end
|
18
17
|
|
19
18
|
desc 'build rdoc'
|
20
|
-
|
19
|
+
task :rdoc => [:build_rdoc, :hack_css]
|
20
|
+
|
21
|
+
RDoc::Task.new(:build_rdoc) do |rd|
|
21
22
|
rd.main = "README.rdoc"
|
22
|
-
rd.
|
23
|
+
rd.options << '-f' << 'sdoc'
|
24
|
+
rd.template = 'direct'
|
23
25
|
rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
|
24
|
-
rd.title = 'Test
|
25
|
-
rd.markup =
|
26
|
+
rd.title = 'Clean Test - make your Test::Unit test cases clean and readable'
|
27
|
+
rd.markup = 'tomdoc'
|
28
|
+
end
|
29
|
+
CLOBBER << 'html'
|
30
|
+
|
31
|
+
FONT_FIX = {
|
32
|
+
"0.82em" => "16px",
|
33
|
+
"0.833em" => "16px",
|
34
|
+
"0.85em" => "16px",
|
35
|
+
"1.15em" => "20px",
|
36
|
+
"1.1em" => "20px",
|
37
|
+
"1.2em" => "20px",
|
38
|
+
"1.4em" => "24px",
|
39
|
+
"1.5em" => "24px",
|
40
|
+
"1.6em" => "32px",
|
41
|
+
"1em" => "16px",
|
42
|
+
"2.1em" => "38px",
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
task :hack_css do
|
47
|
+
maincss = File.open('html/css/main.css').readlines
|
48
|
+
File.open('html/css/main.css','w') do |file|
|
49
|
+
file.puts '@import url(https://fonts.googleapis.com/css?family=Lato:300italic,700italic,300,700);'
|
50
|
+
maincss.each do |line|
|
51
|
+
if line.strip == 'font-family: "Helvetica Neue", Arial, sans-serif;'
|
52
|
+
file.puts 'font-family: Lato, "Helvetica Neue", Arial, sans-serif;'
|
53
|
+
elsif line.strip == 'font-family: monospace;'
|
54
|
+
file.puts 'font-family: Monaco, monospace;'
|
55
|
+
elsif line =~ /^pre\s*$/
|
56
|
+
file.puts "pre {
|
57
|
+
font-family: Monaco, monospace;
|
58
|
+
margin-bottom: 1em;
|
59
|
+
}
|
60
|
+
pre.original"
|
61
|
+
elsif line =~ /^\s*font-size:\s*(.*)\s*;/
|
62
|
+
if FONT_FIX[$1]
|
63
|
+
file.puts "font-size: #{FONT_FIX[$1]};"
|
64
|
+
else
|
65
|
+
file.puts line.chomp
|
66
|
+
end
|
67
|
+
else
|
68
|
+
file.puts line.chomp
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
26
72
|
end
|
27
73
|
CLOBBER << 'coverage'
|
28
74
|
|
data/clean_test.gemspec
CHANGED
data/lib/clean_test/any.rb
CHANGED
@@ -3,14 +3,9 @@ require 'faker'
|
|
3
3
|
module Clean #:nodoc:
|
4
4
|
module Test #:nodoc:
|
5
5
|
# Public: Provides the ability to vend arbitrary values without using literals, or
|
6
|
-
# long calls to Faker. This
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# to make it clear what numbers, ints, and strings in your tests are
|
10
|
-
# relevant. Arbitrary values should use one of these any_ helpers.
|
11
|
-
#
|
12
|
-
# any sort of any - you can define your own "any" values by using #new_any, which allows you to
|
13
|
-
# extend things if you like. Of course, you could just make your own any_method as well.
|
6
|
+
# long calls to Faker. This produced random values, so you must be sure that your code truly
|
7
|
+
# should work with any value. The random seed used will be output, and you can use
|
8
|
+
# the environment variable +RANDOM_SEED+ to recreate the conditions of a particular test.
|
14
9
|
#
|
15
10
|
# Example:
|
16
11
|
#
|
@@ -46,6 +41,16 @@ module Clean #:nodoc:
|
|
46
41
|
# }
|
47
42
|
# }
|
48
43
|
module Any
|
44
|
+
def self.included(k)
|
45
|
+
seed = if ENV['RANDOM_SEED']
|
46
|
+
ENV['RANDOM_SEED'].to_i
|
47
|
+
else
|
48
|
+
srand() # generate random seed
|
49
|
+
seed = srand() # save it (but we've now generated another one)
|
50
|
+
end
|
51
|
+
srand(seed) # set it explicitly
|
52
|
+
puts "Random seed was #{seed}; re-use it via environment variable RANDOM_SEED"
|
53
|
+
end
|
49
54
|
MAX_RAND = 50000 #:nodoc:
|
50
55
|
|
51
56
|
# Public: Get any number; one that doesn't matter
|
@@ -54,12 +59,19 @@ module Clean #:nodoc:
|
|
54
59
|
# :positive - make sure that the number is greater than zero
|
55
60
|
# :negative - make sure that the number is less than zero
|
56
61
|
def any_number(*options)
|
57
|
-
|
62
|
+
number = (rand(2 * MAX_RAND) - MAX_RAND).to_f/100.0
|
63
|
+
if options.include? :positive
|
64
|
+
number + MAX_RAND
|
65
|
+
elsif options.include? :negative
|
66
|
+
number - MAX_RAND
|
67
|
+
else
|
68
|
+
number
|
69
|
+
end
|
58
70
|
end
|
59
71
|
|
60
72
|
# Public: Returns an integer. options is the same as for #any_number
|
61
73
|
def any_int(*options)
|
62
|
-
|
74
|
+
any_number(*options).to_i
|
63
75
|
end
|
64
76
|
|
65
77
|
# Public: Get an arbitrary string of any potential positive length
|
@@ -74,77 +86,6 @@ module Clean #:nodoc:
|
|
74
86
|
# any_string :min => 1024 # at least 1024 characters
|
75
87
|
#
|
76
88
|
def any_string(options = {})
|
77
|
-
any :string,options
|
78
|
-
end
|
79
|
-
|
80
|
-
# Public: Get an arbitrary symbol, for example to use as a Hash key. The symbol
|
81
|
-
# will be between 2 and 20 characters long. If you need super-long symbols for some reason,
|
82
|
-
# use <code>any_string.to_sym</code>.
|
83
|
-
def any_symbol
|
84
|
-
(any_string :min => 2, :max => 20).to_sym
|
85
|
-
end
|
86
|
-
|
87
|
-
# Public: Get an arbitrary sentence of arbitrary words of any potential length. Currently,
|
88
|
-
# this returns a sentence between 10 and 21 words, though you can control that with options
|
89
|
-
#
|
90
|
-
# options - options to control the returned sentence
|
91
|
-
# :max - the maximum number of words you want returned
|
92
|
-
# :min - the minimum number of words you want returned; the sentence will be between
|
93
|
-
# :min and (:min + 10) words
|
94
|
-
#
|
95
|
-
# Example
|
96
|
-
#
|
97
|
-
# any_sentence :min => 20 # at least a 20-word sentence
|
98
|
-
# any_sentence :max => 4 # no more than four words
|
99
|
-
#
|
100
|
-
def any_sentence(options = {})
|
101
|
-
any :sentence,options
|
102
|
-
end
|
103
|
-
|
104
|
-
# Public: Get a predefined, arbitrary any.
|
105
|
-
#
|
106
|
-
# sym - the any that has been defined already. By default, the following are defined:
|
107
|
-
# :string - does any_string
|
108
|
-
# String - does any_string
|
109
|
-
# :number - does any_number
|
110
|
-
# Numeric - does any_number
|
111
|
-
# Float - does any_number
|
112
|
-
# :int - does any_int
|
113
|
-
# Fixnum - does any_int
|
114
|
-
# Integer - does any_int
|
115
|
-
# options - whatever options are relevant to the user-defined any
|
116
|
-
#
|
117
|
-
# Example
|
118
|
-
#
|
119
|
-
# new_any(:foo) do |options|
|
120
|
-
# if options[:bar]
|
121
|
-
# 'bar'
|
122
|
-
# else
|
123
|
-
# 'quux'
|
124
|
-
# end
|
125
|
-
# end
|
126
|
-
#
|
127
|
-
# some_foo = any :foo
|
128
|
-
# some_other_foo = any :foo, :bar => true
|
129
|
-
def any(sym,options = {})
|
130
|
-
anies[sym].call(options)
|
131
|
-
end
|
132
|
-
|
133
|
-
# Public: Create a new any that can be retrieved via #any
|
134
|
-
#
|
135
|
-
# any - the identifer of your new any. Can be anything though a Symbol or classname would be appropriate
|
136
|
-
# block - the block that will be called whenever you #any your any.
|
137
|
-
def new_any(any,&block)
|
138
|
-
anies[any] = block
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
def anies
|
144
|
-
@anies ||= default_anies
|
145
|
-
end
|
146
|
-
|
147
|
-
ANY_STRING = Proc.new do |options| #:nodoc:
|
148
89
|
if options[:min] && options[:max]
|
149
90
|
raise ":min must be less than :max" if options[:min] > options[:max]
|
150
91
|
end
|
@@ -156,8 +97,8 @@ module Clean #:nodoc:
|
|
156
97
|
max_size = options[:max]
|
157
98
|
|
158
99
|
if min_size.nil? && max_size.nil?
|
159
|
-
min_size = rand(
|
160
|
-
max_size = min_size + rand(
|
100
|
+
min_size = rand(80) + 1
|
101
|
+
max_size = min_size + rand(80)
|
161
102
|
elsif min_size.nil?
|
162
103
|
min_size = max_size - rand(max_size)
|
163
104
|
min_size = 1 if min_size < 1
|
@@ -165,26 +106,35 @@ module Clean #:nodoc:
|
|
165
106
|
max_size = min_size + rand(min_size) + 1
|
166
107
|
end
|
167
108
|
|
168
|
-
string = Faker::Lorem.words(1).join('')
|
109
|
+
string = Faker::Lorem.words(1).join(' ')
|
169
110
|
while string.length < min_size
|
170
|
-
string += Faker::Lorem.words(1).join('')
|
111
|
+
string += Faker::Lorem.words(1).join(' ')
|
171
112
|
end
|
172
113
|
|
173
114
|
string[0..(max_size-1)]
|
174
115
|
end
|
175
116
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
number - MAX_RAND
|
182
|
-
else
|
183
|
-
number
|
184
|
-
end
|
117
|
+
# Public: Get an arbitrary symbol, for example to use as a Hash key. The symbol
|
118
|
+
# will be between 2 and 20 characters long. If you need super-long symbols for some reason,
|
119
|
+
# use <code>any_string.to_sym</code>.
|
120
|
+
def any_symbol
|
121
|
+
(any_string :min => 2, :max => 20).to_sym
|
185
122
|
end
|
186
123
|
|
187
|
-
|
124
|
+
# Public: Get an arbitrary sentence of arbitrary words of any potential length. Currently,
|
125
|
+
# this returns a sentence between 10 and 21 words, though you can control that with options
|
126
|
+
#
|
127
|
+
# options - options to control the returned sentence
|
128
|
+
# :max - the maximum number of words you want returned
|
129
|
+
# :min - the minimum number of words you want returned; the sentence will be between
|
130
|
+
# :min and (:min + 10) words
|
131
|
+
#
|
132
|
+
# Example
|
133
|
+
#
|
134
|
+
# any_sentence :min => 20 # at least a 20-word sentence
|
135
|
+
# any_sentence :max => 4 # no more than four words
|
136
|
+
#
|
137
|
+
def any_sentence(options = {})
|
188
138
|
min = 11
|
189
139
|
max = 21
|
190
140
|
|
@@ -198,23 +148,6 @@ module Clean #:nodoc:
|
|
198
148
|
|
199
149
|
Faker::Lorem.words(rand(max - min) + min).join(' ')
|
200
150
|
end
|
201
|
-
|
202
|
-
ANY_INT = Proc.new do |options| #:nodoc:
|
203
|
-
(ANY_NUMBER.call(options)).to_i
|
204
|
-
end
|
205
|
-
|
206
|
-
def default_anies
|
207
|
-
{ :string => ANY_STRING,
|
208
|
-
String => ANY_STRING,
|
209
|
-
:number => ANY_NUMBER,
|
210
|
-
Numeric => ANY_NUMBER,
|
211
|
-
Float => ANY_NUMBER,
|
212
|
-
:int => ANY_INT,
|
213
|
-
Fixnum => ANY_INT,
|
214
|
-
Integer => ANY_INT,
|
215
|
-
:sentence => ANY_SENTENCE,
|
216
|
-
}
|
217
|
-
end
|
218
151
|
end
|
219
152
|
end
|
220
153
|
end
|
@@ -21,117 +21,98 @@ module Clean #:nodoc:
|
|
21
21
|
# #mocks_shouldve_been_called to assist with creating readable tests that use mocks. See those
|
22
22
|
# methods for an example
|
23
23
|
module GivenWhenThen
|
24
|
-
# Public:
|
24
|
+
# Public: Declare a step in your test, based on the following conventions:
|
25
25
|
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
26
|
+
# Given - This sets up conditions for the test
|
27
|
+
# When - This executes the code under test
|
28
|
+
# Then - This asserts that that the code under test worked correctly
|
29
|
+
# And - Extend a Given/When/Then when using lambda/method form (see below)
|
30
|
+
# But - Extend a Given/When/Then when using lambda/method form (see below)
|
30
31
|
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
# Given {
|
34
|
-
# @foo = "bar"
|
35
|
-
# }
|
32
|
+
# There are three forms for calling this method, in order of preference:
|
36
33
|
#
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
# by this When. If existing_block is non-nil, this is ignored
|
47
|
-
#
|
48
|
-
# Examples
|
49
|
-
#
|
50
|
-
# When {
|
51
|
-
# @foo.go
|
52
|
-
# }
|
34
|
+
# block - in this form, you pass a block that contains the test code. This should be preferred as it
|
35
|
+
# keeps your test code in your test
|
36
|
+
# method - in this form, you pass a symbol that is the name of a method in your test class. This method
|
37
|
+
# should set up or perform or assert whatever is needed. This can be useful to re-use test helper
|
38
|
+
# methods in an expedient fashion. In this case, you can pass parameters by simply listing
|
39
|
+
# them after the symbol. See the example.
|
40
|
+
# lambda - in this form, you declare a method that returns a lambda and that is used as the
|
41
|
+
# block for this step of the test. This is least desirable, as it requires methods to return
|
42
|
+
# lambdas, which is an extra bit of indirection that adds noise.
|
53
43
|
#
|
54
|
-
#
|
55
|
-
def When(existing_block=nil,&block)
|
56
|
-
Given(existing_block,&block)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Public: Verify the results of the test
|
44
|
+
# Parameters:
|
60
45
|
#
|
61
46
|
# existing_block - a callable object (e.g. a Proc) that will be called immediately
|
62
|
-
# by this
|
47
|
+
# by this Given. If this is a Symbol, a method in the current scope will be converted into
|
48
|
+
# a block and used. If nil, &block is expected to be passed
|
49
|
+
# other_args - a list of arguments to be passed to the block. This is mostly useful when using method form.
|
63
50
|
# block - a block given to this call that will be executed immediately
|
64
|
-
# by this
|
51
|
+
# by this Given. If existing_block is non-nil, this is ignored
|
65
52
|
#
|
66
53
|
# Examples
|
67
54
|
#
|
68
|
-
#
|
69
|
-
#
|
55
|
+
# # block form
|
56
|
+
# Given {
|
57
|
+
# @foo = "bar"
|
70
58
|
# }
|
71
59
|
#
|
72
|
-
#
|
73
|
-
def
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
# Public: Continue the previous Given/When/Then in a new block. The reason
|
78
|
-
# you might do this is if you wanted to use the existing block form of a
|
79
|
-
# Given/When/Then, but also need to do something custom. This allows you to
|
80
|
-
# write your test more fluently.
|
81
|
-
#
|
82
|
-
# existing_block - a callable object (e.g. a Proc) that will be called immediately
|
83
|
-
# by this Then. If nil, &block is expected to be passed
|
84
|
-
# block - a block given to this call that will be executed immediately
|
85
|
-
# by this Then. If existing_block is non-nil, this is ignored
|
86
|
-
#
|
87
|
-
# Examples
|
88
|
-
#
|
89
|
-
# def circle(radius)
|
90
|
-
# lambda { @circle = Circle.new(radius) }
|
60
|
+
# # method form
|
61
|
+
# def assert_valid_person
|
62
|
+
# assert @person.valid?,"Person invalid: #{@person.errors.full_messages}"
|
91
63
|
# end
|
92
64
|
#
|
93
|
-
# Given
|
94
|
-
#
|
95
|
-
# @another_circle = Circle.new(30)
|
65
|
+
# Given {
|
66
|
+
# @person = Person.new(:last_name => 'Copeland', :first_name => 'Dave')
|
96
67
|
# }
|
68
|
+
# Then :assert_valid_person
|
97
69
|
#
|
98
|
-
#
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
# Public: Continue the previous Given/When/Then in a new block. The reason
|
104
|
-
# you might do this is if you wanted to use the existing block form of a
|
105
|
-
# Given/When/Then, but also need to do something custom, and that custom thing
|
106
|
-
# contradicts or overrides the flow, so an "And" wouldn't read properly. This allows you to
|
107
|
-
# write your test more fluently.
|
70
|
+
# # method form with arguments
|
71
|
+
# def assert_invalid_person(error_field)
|
72
|
+
# assert !@person.valid?
|
73
|
+
# assert @person.errors[error_field].present?
|
74
|
+
# end
|
108
75
|
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
76
|
+
# Given {
|
77
|
+
# @person = Person.new(:last_name => 'Copeland')
|
78
|
+
# }
|
79
|
+
# Then :assert_invalid_person,:first_name
|
113
80
|
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
# @options = {
|
119
|
-
# :foo => 'bar',
|
120
|
-
# :quux => 'baz',
|
121
|
-
# }
|
81
|
+
# # lambda form
|
82
|
+
# def assert_valid_person
|
83
|
+
# lambda {
|
84
|
+
# assert @person.valid?,"Person invalid: #{@person.errors.full_messages}"
|
122
85
|
# }
|
123
86
|
# end
|
124
87
|
#
|
125
|
-
# Given
|
126
|
-
#
|
127
|
-
# @options[:foo] = 'baz'
|
88
|
+
# Given {
|
89
|
+
# @person = Person.new(:last_name => 'Copeland', :first_name => 'Dave')
|
128
90
|
# }
|
91
|
+
# Then assert_valid_person
|
129
92
|
#
|
130
93
|
# Returns the block that was executed
|
131
|
-
def
|
132
|
-
|
94
|
+
def Given(existing_block=nil,*other_args,&block)
|
95
|
+
if existing_block.nil?
|
96
|
+
block.call(*other_args)
|
97
|
+
block
|
98
|
+
else
|
99
|
+
if existing_block.kind_of?(Symbol)
|
100
|
+
existing_block = method(existing_block)
|
101
|
+
end
|
102
|
+
existing_block.call(*other_args)
|
103
|
+
existing_block
|
104
|
+
end
|
133
105
|
end
|
134
106
|
|
107
|
+
# Public: Execute the code under test. Behavior identical to Given
|
108
|
+
alias :When :Given
|
109
|
+
# Public: Assert the results of the test. Behavior identical to Given
|
110
|
+
alias :Then :Given
|
111
|
+
# Public: Extend a Given/When/Then when using method or lambda form. Behavior identical to Given
|
112
|
+
alias :And :Given
|
113
|
+
# Public: Extend a Given/When/Then when using method or lambda form. Behavior identical to Given
|
114
|
+
alias :But :Given
|
115
|
+
|
135
116
|
# Public: Used to make clear the structure of tests using mocks.
|
136
117
|
# This returns a no-op, and is intended to be used with a "When"
|
137
118
|
# to delineate the creation of a mock in a Given, and the
|
@@ -165,22 +146,11 @@ module Clean #:nodoc:
|
|
165
146
|
# frameworks do not require an explicit "verify" step, you often have tests
|
166
147
|
# that have no explicit asserts, the assertions being simply that the mocks were called
|
167
148
|
# as expected. This step, which is a no-op, allows you to document that you are
|
168
|
-
# expecting mocks to be called
|
149
|
+
# expecting mocks to be called (rather than forgot to assert anything).
|
150
|
+
# See the example in #mocks_are_called for usage.
|
169
151
|
def mocks_shouldve_been_called
|
170
152
|
lambda {}
|
171
153
|
end
|
172
|
-
|
173
|
-
private
|
174
|
-
|
175
|
-
def call_block_param_or_block_given(existing_block,&block)
|
176
|
-
if existing_block.nil?
|
177
|
-
block.call
|
178
|
-
block
|
179
|
-
else
|
180
|
-
existing_block.call
|
181
|
-
existing_block
|
182
|
-
end
|
183
|
-
end
|
184
154
|
end
|
185
155
|
end
|
186
156
|
end
|
data/lib/clean_test/version.rb
CHANGED
data/test/test_any.rb
CHANGED
@@ -106,38 +106,6 @@ class TestAny < Clean::Test::TestCase
|
|
106
106
|
}
|
107
107
|
|
108
108
|
|
109
|
-
test_that "we can register custom anys" do
|
110
|
-
Given {
|
111
|
-
new_any :foo do
|
112
|
-
"bar"
|
113
|
-
end
|
114
|
-
}
|
115
|
-
When {
|
116
|
-
@result = any :foo
|
117
|
-
}
|
118
|
-
Then {
|
119
|
-
assert_equal 'bar',@result
|
120
|
-
}
|
121
|
-
end
|
122
|
-
|
123
|
-
test_that "custom anys can take options" do
|
124
|
-
Given {
|
125
|
-
new_any :foo do |options|
|
126
|
-
if options[:baaz]
|
127
|
-
'quux'
|
128
|
-
else
|
129
|
-
'bar'
|
130
|
-
end
|
131
|
-
end
|
132
|
-
}
|
133
|
-
When {
|
134
|
-
@result = any :foo, :baaz => true
|
135
|
-
}
|
136
|
-
Then {
|
137
|
-
assert_equal 'quux',@result
|
138
|
-
}
|
139
|
-
end
|
140
|
-
|
141
109
|
test_that "any_symbol works" do
|
142
110
|
When {
|
143
111
|
@symbol = any_symbol
|
@@ -148,23 +116,4 @@ class TestAny < Clean::Test::TestCase
|
|
148
116
|
assert @symbol.to_s.length < 20
|
149
117
|
}
|
150
118
|
end
|
151
|
-
|
152
|
-
[String,[Integer,Fixnum],Fixnum,Float,[Numeric,Float]].each do |klass|
|
153
|
-
test_that "can get an any #{klass}" do
|
154
|
-
Given {
|
155
|
-
@class = @expected_class = klass
|
156
|
-
if @class.kind_of? Array
|
157
|
-
@expected_class = @class[1]
|
158
|
-
@class = @class[0]
|
159
|
-
end
|
160
|
-
}
|
161
|
-
When {
|
162
|
-
@value = any @class
|
163
|
-
}
|
164
|
-
Then {
|
165
|
-
assert_not_nil @value
|
166
|
-
assert_equal @expected_class,@value.class
|
167
|
-
}
|
168
|
-
end
|
169
|
-
end
|
170
119
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test/unit'
|
2
2
|
require 'clean_test/test_case'
|
3
3
|
|
4
|
-
class
|
4
|
+
class TestGivenWhenThen < Clean::Test::TestCase
|
5
5
|
|
6
6
|
def test_basics
|
7
7
|
Given {
|
@@ -84,6 +84,20 @@ class TestSimpleGiven < Clean::Test::TestCase
|
|
84
84
|
}
|
85
85
|
end
|
86
86
|
|
87
|
+
def test_can_use_symbols_for_methods
|
88
|
+
Given :a_string
|
89
|
+
Then {
|
90
|
+
assert_equal "foo",@string
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_can_pass_params_to_symbols
|
95
|
+
Given :a_string, 4
|
96
|
+
Then {
|
97
|
+
assert_equal 4,@string.length
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
87
101
|
def test_invert_for_block_based_asserts
|
88
102
|
Given a_nil_x
|
89
103
|
Then {
|
@@ -97,6 +111,14 @@ class TestSimpleGiven < Clean::Test::TestCase
|
|
97
111
|
|
98
112
|
private
|
99
113
|
|
114
|
+
def a_string(length=3)
|
115
|
+
if length == 3
|
116
|
+
@string = "foo"
|
117
|
+
else
|
118
|
+
@string = "quux"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
100
122
|
def a_nil_x
|
101
123
|
Proc.new { @x = nil }
|
102
124
|
end
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clean_test
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0.rc1
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- David Copeland
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faker
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rdoc
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,31 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: sdoc
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
36
62
|
- !ruby/object:Gem::Dependency
|
37
63
|
name: rake
|
38
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
39
65
|
none: false
|
40
66
|
requirements:
|
41
67
|
- - ! '>='
|
@@ -43,10 +69,15 @@ dependencies:
|
|
43
69
|
version: '0'
|
44
70
|
type: :development
|
45
71
|
prerelease: false
|
46
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
47
78
|
- !ruby/object:Gem::Dependency
|
48
79
|
name: simplecov
|
49
|
-
requirement:
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
50
81
|
none: false
|
51
82
|
requirements:
|
52
83
|
- - ! '>='
|
@@ -54,7 +85,12 @@ dependencies:
|
|
54
85
|
version: '0'
|
55
86
|
type: :development
|
56
87
|
prerelease: false
|
57
|
-
version_requirements:
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
58
94
|
description: You can easily make your plain Ruby Test::Unit test cases clean and clear
|
59
95
|
with Given/When/Then, placeholder values, and textual descriptions without resorting
|
60
96
|
to metaprogramming or complex frameworks. Use as much or as little as you like
|
@@ -64,24 +100,42 @@ executables: []
|
|
64
100
|
extensions: []
|
65
101
|
extra_rdoc_files: []
|
66
102
|
files:
|
67
|
-
-
|
68
|
-
|
69
|
-
-
|
70
|
-
|
71
|
-
-
|
72
|
-
|
73
|
-
-
|
74
|
-
|
75
|
-
-
|
76
|
-
|
77
|
-
-
|
78
|
-
|
79
|
-
-
|
80
|
-
|
81
|
-
-
|
82
|
-
|
83
|
-
-
|
84
|
-
|
103
|
+
- !binary |-
|
104
|
+
LmdpdGlnbm9yZQ==
|
105
|
+
- !binary |-
|
106
|
+
LnJ2bXJj
|
107
|
+
- !binary |-
|
108
|
+
LnRyYXZpcy55bWw=
|
109
|
+
- !binary |-
|
110
|
+
R2VtZmlsZQ==
|
111
|
+
- !binary |-
|
112
|
+
TElDRU5TRS50eHQ=
|
113
|
+
- !binary |-
|
114
|
+
UkVBRE1FLnJkb2M=
|
115
|
+
- !binary |-
|
116
|
+
UmFrZWZpbGU=
|
117
|
+
- !binary |-
|
118
|
+
Y2xlYW5fdGVzdC5nZW1zcGVj
|
119
|
+
- !binary |-
|
120
|
+
bGliL2NsZWFuX3Rlc3QvYW55LnJi
|
121
|
+
- !binary |-
|
122
|
+
bGliL2NsZWFuX3Rlc3QvZ2l2ZW5fd2hlbl90aGVuLnJi
|
123
|
+
- !binary |-
|
124
|
+
bGliL2NsZWFuX3Rlc3QvdGVzdF9jYXNlLnJi
|
125
|
+
- !binary |-
|
126
|
+
bGliL2NsZWFuX3Rlc3QvdGVzdF90aGF0LnJi
|
127
|
+
- !binary |-
|
128
|
+
bGliL2NsZWFuX3Rlc3QvdmVyc2lvbi5yYg==
|
129
|
+
- !binary |-
|
130
|
+
dGVzdC9ib290c3RyYXAucmI=
|
131
|
+
- !binary |-
|
132
|
+
dGVzdC90ZXN0X2FueS5yYg==
|
133
|
+
- !binary |-
|
134
|
+
dGVzdC90ZXN0X2NpcmNsZS5yYg==
|
135
|
+
- !binary |-
|
136
|
+
dGVzdC90ZXN0X2dpdmVuX3doZW5fdGhlbi5yYg==
|
137
|
+
- !binary |-
|
138
|
+
dGVzdC90ZXN0X3Rlc3RfdGhhdC5yYg==
|
85
139
|
homepage: ''
|
86
140
|
licenses: []
|
87
141
|
post_install_message:
|
@@ -94,21 +148,29 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
148
|
- - ! '>='
|
95
149
|
- !ruby/object:Gem::Version
|
96
150
|
version: '0'
|
151
|
+
segments:
|
152
|
+
- 0
|
153
|
+
hash: -2779224397029811565
|
97
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
155
|
none: false
|
99
156
|
requirements:
|
100
|
-
- - ! '
|
157
|
+
- - ! '>'
|
101
158
|
- !ruby/object:Gem::Version
|
102
|
-
version:
|
159
|
+
version: 1.3.1
|
103
160
|
requirements: []
|
104
161
|
rubyforge_project: clean_test
|
105
|
-
rubygems_version: 1.8.
|
162
|
+
rubygems_version: 1.8.24
|
106
163
|
signing_key:
|
107
164
|
specification_version: 3
|
108
165
|
summary: Clean up your Test::Unit tests
|
109
166
|
test_files:
|
110
|
-
-
|
111
|
-
|
112
|
-
-
|
113
|
-
|
114
|
-
-
|
167
|
+
- !binary |-
|
168
|
+
dGVzdC9ib290c3RyYXAucmI=
|
169
|
+
- !binary |-
|
170
|
+
dGVzdC90ZXN0X2FueS5yYg==
|
171
|
+
- !binary |-
|
172
|
+
dGVzdC90ZXN0X2NpcmNsZS5yYg==
|
173
|
+
- !binary |-
|
174
|
+
dGVzdC90ZXN0X2dpdmVuX3doZW5fdGhlbi5yYg==
|
175
|
+
- !binary |-
|
176
|
+
dGVzdC90ZXN0X3Rlc3RfdGhhdC5yYg==
|