ZenTest 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +104 -0
- data/LinuxJournalArticle.txt +393 -0
- data/Manifest.txt +27 -0
- data/README.txt +123 -0
- data/Rakefile +98 -0
- data/bin/ZenTest +28 -0
- data/bin/autotest +12 -0
- data/bin/unit_diff +40 -0
- data/example.txt +41 -0
- data/example1.rb +7 -0
- data/example2.rb +15 -0
- data/lib/ZenTest.rb +536 -0
- data/lib/autotest.rb +202 -0
- data/lib/rails_autotest.rb +57 -0
- data/lib/unit_diff.rb +200 -0
- data/test/data/normal/lib/photo.rb +0 -0
- data/test/data/normal/test/test_camelcase.rb +0 -0
- data/test/data/normal/test/test_photo.rb +0 -0
- data/test/data/normal/test/test_route.rb +0 -0
- data/test/data/normal/test/test_user.rb +0 -0
- data/test/data/rails/test/fixtures/routes.yml +0 -0
- data/test/data/rails/test/functional/route_controller_test.rb +0 -0
- data/test/data/rails/test/unit/route_test.rb +0 -0
- data/test/test_autotest.rb +179 -0
- data/test/test_rails_autotest.rb +55 -0
- data/test/test_unit_diff.rb +95 -0
- data/test/test_zentest.rb +670 -0
- metadata +103 -0
data/History.txt
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
*** 3.0.0 / 2006-03-06
|
2
|
+
|
3
|
+
+ 2 major enhancements
|
4
|
+
+ Added autotest and rails_autotest. YAY for continous testing!
|
5
|
+
+ Repackaged and gemified. YAY for gemification!
|
6
|
+
+ 3 minor enhancements
|
7
|
+
+ Added non-mappable tests starting with test_integration_.
|
8
|
+
+ Lots of code and test refactoring and cleanup.
|
9
|
+
+ Massive improvement on unit tests.
|
10
|
+
+ 3 bug fixes
|
11
|
+
+ Cleaned up class method inheritence. Esp relevant for rails testing.
|
12
|
+
+ Finally fixed the unit_diff parse bug!
|
13
|
+
+ Fixed improper counting of errors if a class was missing, should be 1 + missing methods.
|
14
|
+
|
15
|
+
*** 2.4.0 / 2005-03-21
|
16
|
+
|
17
|
+
+ 3 minor enhancements
|
18
|
+
+ Able to audit standard class library (so now we can audit rubicon!).
|
19
|
+
+ Able to map against class methods (self.blah <=> test_class_blah).
|
20
|
+
+ Added -I=rubypath support
|
21
|
+
+ 4 bug fixes
|
22
|
+
+ bug:1151 Fixed stupid problem w/ unit_diff.
|
23
|
+
+ bug:1454 code generation correctly matches class/module for nested classes.
|
24
|
+
+ bug:1455 Updated method mapping to work on all operators listed in my quickref.
|
25
|
+
+ Realized I'm a moron and did NOT release in March like I thought...
|
26
|
+
|
27
|
+
*** 2.3.0 / 2004-11-18
|
28
|
+
|
29
|
+
+ 6 minor enhancements
|
30
|
+
+ Massively expanded the method name mappings.
|
31
|
+
+ Added -r flag to reverse map names, for Rails style testing.
|
32
|
+
+ Added -e to auto eval tests generated.
|
33
|
+
+ Added -b & -c flags in unit_diff (passed to diff)
|
34
|
+
+ Added install and uninstall rules to Makefile.
|
35
|
+
+ Added some more doco to README.txt
|
36
|
+
+ 7 bug fixes
|
37
|
+
+ Cleaned up and refactored tests.
|
38
|
+
+ Changed the way files are generated, to accomodate new flags.
|
39
|
+
+ Added some more tests.
|
40
|
+
+ Added $ZENTEST=true
|
41
|
+
+ Fixed the one-liner diff bug.
|
42
|
+
+ Cleaned up multi-line string diffs by unescaping \n
|
43
|
+
+ Cleaned result for flunks.
|
44
|
+
|
45
|
+
*** 2.2.0 / 2004-10-18
|
46
|
+
|
47
|
+
+ 4 minor enhancements
|
48
|
+
+ Added LinuxJournalArticle.txt! WOOT!
|
49
|
+
+ Added unit_diff.rb - a very cool filter for test output!
|
50
|
+
+ Extended ZenTest to work with standard input
|
51
|
+
+ Added "ZenTest FULL" to force ZenTest to analyze inherited methods, for subclasses of the standard library.
|
52
|
+
+ 3 bug fixes
|
53
|
+
+ Extended makefile to be more dynamic and stop diffing versions. ugh.
|
54
|
+
+ Expanded the method rename map to handle <<, *, +, and ==.
|
55
|
+
+ Added more test cases.
|
56
|
+
|
57
|
+
*** 2.1.2 / 2004-03-08
|
58
|
+
|
59
|
+
+ 3 bug fixes
|
60
|
+
+ Fixed yet another 1.8ism, results will be the same in 1.8 and 1.6.
|
61
|
+
+ Fixed code responsible for method name conversion.
|
62
|
+
+ I am a moron... didn't run tests after updating version.
|
63
|
+
+ Need to convert my diff-based tests to unit tests.
|
64
|
+
|
65
|
+
*** 2.1.1 / 2004-03-06
|
66
|
+
|
67
|
+
+ 3 bug fixes
|
68
|
+
+ Fixed a 1.8ism.
|
69
|
+
+ Removed zentestrunner. Older ruby users will just have to suffer.
|
70
|
+
+ Updated history to ZenWeb format.
|
71
|
+
|
72
|
+
*** 2.1.0 / 2003-01-07
|
73
|
+
|
74
|
+
+ 3 major enhancements
|
75
|
+
+ Output is runnable as-is thanks to zentestrunner.rb.
|
76
|
+
+ Wrapped up all running functionality into ZenTest.fix
|
77
|
+
+ Added simple statistic output... Thanks Dave & Andy!!!
|
78
|
+
+ 1 minor enhancement
|
79
|
+
+ Added zentestrunner.rb until Nathaniel accepts my changes!
|
80
|
+
+ 3 bug fixes
|
81
|
+
+ Removed at_exit override and avoided test/unit altogether.
|
82
|
+
+ Added a clean rule to Makefile
|
83
|
+
+ Extended README.txt to include some of the rules.
|
84
|
+
+ Fixed several tests and added assertions for new stats
|
85
|
+
|
86
|
+
*** 2.0.0 / 2002-10-29
|
87
|
+
|
88
|
+
+ 2 major enhancements
|
89
|
+
+ Rewrite of ZenTest.rb into actual OO design.
|
90
|
+
+ Added unit tests, finally...
|
91
|
+
|
92
|
+
*** 1.0.1 / 2002-09-28
|
93
|
+
|
94
|
+
+ 1 minor enhancements
|
95
|
+
+ Only loads when a class is detected, allows some scripts to be skipped.
|
96
|
+
+ 3 bug fixes
|
97
|
+
+ Cleaned up output. Verbose when $DEBUG is true.
|
98
|
+
+ Added an error count that is output at end.
|
99
|
+
+ Better filtering or conversion on some method names.
|
100
|
+
|
101
|
+
*** 1.0.0 / 2002-09-24
|
102
|
+
|
103
|
+
+ 1 major enhancements
|
104
|
+
+ Birthday!
|
@@ -0,0 +1,393 @@
|
|
1
|
+
How to Use ZenTest with Ruby
|
2
|
+
by Pat Eyler <pate@kohalabs.com>
|
3
|
+
http://linuxjournal.com/article.php?sid=7776
|
4
|
+
(included in this package with permission)
|
5
|
+
|
6
|
+
Refactoring and unit testing are a great pair of tools for every
|
7
|
+
programmer's workbench. Sadly, not every programmer knows how to use
|
8
|
+
them. My first exposure to them came when I started using Ruby,
|
9
|
+
refactoring and unit testing are a big part of the landscape in the
|
10
|
+
Ruby community.
|
11
|
+
|
12
|
+
Some time ago, I translated the refactoring example from the first
|
13
|
+
chapter of Martin Fowler's excellent book, Refactoring, out of Java
|
14
|
+
and into Ruby. I felt this would be a great way to learn more about
|
15
|
+
refactoring and brush up on my Ruby while I was at it. Recently, I
|
16
|
+
decided to update the translation for Ruby 1.8.X. One of the things I
|
17
|
+
needed to change was to convert the old unit tests to work with
|
18
|
+
Test::Unit, the new unit testing framework for Ruby.
|
19
|
+
|
20
|
+
I wasn't really looking forward to building a new test suite though.
|
21
|
+
Fortunately, help was available. Ryan Davis has written a great tool
|
22
|
+
called ZenTest, which creates test suites for existing bodies of
|
23
|
+
code. Since a lot of people are new to refactoring, unit testing, and
|
24
|
+
ZenTest, I thought this would be a great chance to introduce you to
|
25
|
+
this trio of tools.
|
26
|
+
|
27
|
+
Martin's example code is built around a video store application. In
|
28
|
+
his original code, there are three classes; Customer, Movie, and
|
29
|
+
Rental. I'll focus on just the Customer class in this article.
|
30
|
+
Here's the original code:
|
31
|
+
|
32
|
+
class Customer
|
33
|
+
attr_accessor :name
|
34
|
+
|
35
|
+
def initialize(name)
|
36
|
+
@name = name
|
37
|
+
@rentals = Array.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def addRental(aRental)
|
41
|
+
@rentals.push(aRental)
|
42
|
+
end
|
43
|
+
|
44
|
+
def statement
|
45
|
+
totalAmount = 0.0
|
46
|
+
frequentRenterPoints = 0
|
47
|
+
rentals = @rentals.length
|
48
|
+
result = "\nRental Record for #{@name}\n"
|
49
|
+
thisAmount = 0.0
|
50
|
+
@rentals.each do |rental|
|
51
|
+
# determine amounts for each line
|
52
|
+
case rental.aMovie.pricecode
|
53
|
+
when Movie::REGULAR
|
54
|
+
thisAmount += 2
|
55
|
+
if rental.daysRented > 2
|
56
|
+
thisAmount += (rental.daysRented - 2) * 1.5
|
57
|
+
end
|
58
|
+
|
59
|
+
when Movie::NEW_RELEASE
|
60
|
+
thisAmount += rental.daysRented * 3
|
61
|
+
|
62
|
+
when Movie::CHILDRENS
|
63
|
+
thisAmount += 1.5
|
64
|
+
if each.daysRented > 3
|
65
|
+
thisAmount += (rental.daysRented - 3) * 1.5
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
# add frequent renter points
|
71
|
+
frequentRenterPoints += 1
|
72
|
+
# add bonus for a two day new release rental
|
73
|
+
if ( rental.daysRented > 1) &&
|
74
|
+
(Movie::NEW_RELEASE == rental.aMovie.pricecode)
|
75
|
+
frequentRenterPoints += 1
|
76
|
+
end
|
77
|
+
|
78
|
+
# show figures for this rental
|
79
|
+
result +="\t#{rental.aMovie.title}\t#{thisAmount}\n"
|
80
|
+
totalAmount += thisAmount
|
81
|
+
end
|
82
|
+
result += "Amount owed is #{totalAmount}\n"
|
83
|
+
result += "You earned #{frequentRenterPoints} frequent renter points"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
Not the cleanest code in the world, but it is supposed to be that
|
89
|
+
way. This represents the code as you get it from the user. No
|
90
|
+
tests, poorly laid out, but working -- and it's your job to make it
|
91
|
+
better without breaking it. So, where to start? With unit tests of
|
92
|
+
course.
|
93
|
+
|
94
|
+
Time to grab ZenTest. You can run it like this:
|
95
|
+
|
96
|
+
$ zentest videostore.rb > test_videostore.rb
|
97
|
+
|
98
|
+
which produces a file full of tests. Running the test suite doesn't
|
99
|
+
do quite what we were hoping though:
|
100
|
+
|
101
|
+
$ ruby testVideoStore.rb Loaded suite testVideoStore
|
102
|
+
Started
|
103
|
+
EEEEEEEEEEE
|
104
|
+
Finished in 0.008974 seconds.
|
105
|
+
|
106
|
+
1) Error!!!
|
107
|
+
test_addRental(TestCustomer):
|
108
|
+
NotImplementedError: Need to write test_addRental
|
109
|
+
testVideoStore.rb:11:in `test_addRental'
|
110
|
+
testVideoStore.rb:54
|
111
|
+
|
112
|
+
2) Error!!!
|
113
|
+
test_name=(TestCustomer):
|
114
|
+
NotImplementedError: Need to write test_name=
|
115
|
+
testVideoStore.rb:15:in `test_name='
|
116
|
+
testVideoStore.rb:54
|
117
|
+
|
118
|
+
3) Error!!!
|
119
|
+
test_statement=(TestCustomer):
|
120
|
+
NotImplementedError: Need to write test_statement
|
121
|
+
testVideoStore.rb:19:in `test_statement'
|
122
|
+
testVideoStore.rb:54
|
123
|
+
.
|
124
|
+
.
|
125
|
+
.
|
126
|
+
|
127
|
+
11 tests, 0 assertions, 0 failures, 11 errors
|
128
|
+
$
|
129
|
+
|
130
|
+
So what exactly did we get out of this? Here's the portion of our
|
131
|
+
new test suite that matters for the Customer class:
|
132
|
+
|
133
|
+
# Code Generated by ZenTest v. 2.1.2
|
134
|
+
# classname: asrt / meth = ratio%
|
135
|
+
# Customer: 0 / 3 = 0.00%
|
136
|
+
|
137
|
+
require 'test/unit'
|
138
|
+
|
139
|
+
class TestCustomer < Test::Unit::TestCase
|
140
|
+
def test_addRental
|
141
|
+
raise NotImplementedError, 'Need to write test_addRental'
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_name=
|
145
|
+
raise NotImplementedError, 'Need to write test_name='
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_statement
|
149
|
+
raise NotImplementedError, 'Need to write test_statement'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
ZenTest built three test methods: one for the accessor method, one for
|
154
|
+
the addRental method, and one for the statement method. Why nothing
|
155
|
+
for the initializer? Well, initializers tend to be pretty bulletproof
|
156
|
+
(if they're not, it's pretty easy to add the test method yourself).
|
157
|
+
Besides, we'll be testing it indirectly when we write test_name= (the
|
158
|
+
tests for the accessor method). There's one other thing we'll need to
|
159
|
+
add, the test suite doesn't load the code we're testing. Changing the
|
160
|
+
beginning of the script to require the videostore.rb file will do the
|
161
|
+
trick for us.
|
162
|
+
|
163
|
+
|
164
|
+
# Code Generated by ZenTest v. 2.1.2
|
165
|
+
# classname: asrt / meth = ratio%
|
166
|
+
# Customer: 0 / 3 = 0.00%
|
167
|
+
|
168
|
+
require 'test/unit'
|
169
|
+
require 'videostore'
|
170
|
+
|
171
|
+
That little snippet of comments at the top lets us know that we have three
|
172
|
+
methods under test in the Customer class, zero assertions testing
|
173
|
+
them, and no coverage. Let's fix that. We'll start by writing some
|
174
|
+
tests for test_name= (no, it really doesn't matter what order we go in --
|
175
|
+
this is just a convenient place to start).
|
176
|
+
|
177
|
+
def test_name=
|
178
|
+
aCustomer = Customer.new("Fred Jones")
|
179
|
+
assert_equal("Fred Jones",aCustomer.name)
|
180
|
+
aCustomer.name = "Freddy Jones"
|
181
|
+
assert_equal("Freddy Jones",aCustomer.name
|
182
|
+
end
|
183
|
+
|
184
|
+
Running testVideoStore.rb again gives us:
|
185
|
+
|
186
|
+
$ ruby testVideoStore.rb
|
187
|
+
Loaded suite testVideoStore
|
188
|
+
Started
|
189
|
+
E.EEEEEEEEE
|
190
|
+
Finished in 0.011233 seconds.
|
191
|
+
|
192
|
+
1) Error!!!
|
193
|
+
test_addRental(TestCustomer):
|
194
|
+
NotImplementedError: Need to write test_addRental
|
195
|
+
testVideoStore.rb:13:in `test_addRental'
|
196
|
+
testVideoStore.rb:58
|
197
|
+
|
198
|
+
2) Error!!!
|
199
|
+
test_statement(TestCustomer):
|
200
|
+
NotImplementedError: Need to write test_statement
|
201
|
+
testVideoStore.rb:23:in `test_statement'
|
202
|
+
testVideoStore.rb:58
|
203
|
+
.
|
204
|
+
.
|
205
|
+
.
|
206
|
+
11 tests, 2 assertions, 0 failures, 10 errors
|
207
|
+
$
|
208
|
+
|
209
|
+
So far, so good. The line of 'E's (which shows errors in the test run)
|
210
|
+
has been reduced by one, and the summary line at the bottom tells us
|
211
|
+
roughly the same thing.
|
212
|
+
|
213
|
+
We really don't have a way to test addRental directly, so we'll just
|
214
|
+
write an stub test for now.
|
215
|
+
|
216
|
+
def test_addRental
|
217
|
+
assert(1) # stub test, since there is nothing in the method to test
|
218
|
+
end
|
219
|
+
|
220
|
+
When we run the tests again, we get:
|
221
|
+
|
222
|
+
$ ruby testVideoStore.rb
|
223
|
+
Loaded suite testVideoStore
|
224
|
+
Started
|
225
|
+
..EEEEEEEEE
|
226
|
+
Finished in 0.008682 seconds.
|
227
|
+
|
228
|
+
1) Error!!!
|
229
|
+
test_statement(TestCustomer):
|
230
|
+
NotImplementedError: Need to write test_statement
|
231
|
+
testVideoStore.rb:22:in `test_statement'
|
232
|
+
testVideoStore.rb:57
|
233
|
+
.
|
234
|
+
.
|
235
|
+
.
|
236
|
+
11 tests, 3 assertions, 0 failures, 9 errors
|
237
|
+
$
|
238
|
+
|
239
|
+
Better and better, just one error left in the TestCustomer class.
|
240
|
+
Let's finish up with a test that will clear our test_statement error
|
241
|
+
and verify that addRental works correctly:
|
242
|
+
|
243
|
+
def test_statement
|
244
|
+
aMovie = Movie.new("Legacy",0)
|
245
|
+
|
246
|
+
aRental = Rental.new(aMovie,2)
|
247
|
+
|
248
|
+
aCustomer = Customer.new("Fred Jones")
|
249
|
+
aCustomer.addRental(aRental)
|
250
|
+
aStatement = "\nRental Record for Fred Jones\n\tLegacy\t2.0
|
251
|
+
Amount owed is 2.0\nYou earned 1 frequent renter points"
|
252
|
+
|
253
|
+
assert_equal(aStatement,aCustomer.statement)
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
We run the tests again, and see:
|
258
|
+
|
259
|
+
$ ruby testVideoStore.rb
|
260
|
+
Loaded suite testVideoStore
|
261
|
+
Started
|
262
|
+
...EEEEEEEE
|
263
|
+
Finished in 0.009378 seconds.
|
264
|
+
.
|
265
|
+
.
|
266
|
+
.
|
267
|
+
11 tests, 4 assertions, 0 failures, 8 errors
|
268
|
+
$
|
269
|
+
|
270
|
+
Great! The only errors left are on the Movie and Rental classes,
|
271
|
+
the Customer class is clean.
|
272
|
+
|
273
|
+
We can continue along like this for the remaining classes, but I'll
|
274
|
+
not bore you with those details. Instead, I'd like to look at how
|
275
|
+
ZenTest can help when you've already got some tests in place. Later
|
276
|
+
development allows us to do just that -- the video store owner
|
277
|
+
wants a new web based statement for web using customers.
|
278
|
+
|
279
|
+
After a bit of refactoring and new development, the code looks like
|
280
|
+
this:
|
281
|
+
|
282
|
+
class Customer
|
283
|
+
attr_accessor :name
|
284
|
+
|
285
|
+
def initialize(name)
|
286
|
+
@name = name
|
287
|
+
@rentals = Array.new
|
288
|
+
end
|
289
|
+
|
290
|
+
def addRental(aRental)
|
291
|
+
@rentals.push(aRental)
|
292
|
+
end
|
293
|
+
|
294
|
+
def statement
|
295
|
+
result = "\nRental Record for #{@name}\n"
|
296
|
+
@rentals.each do
|
297
|
+
|each|
|
298
|
+
# show figures for this rental
|
299
|
+
result +="\t#{each.aMovie.title}\t#{each.getCharge}\n"
|
300
|
+
end
|
301
|
+
result += "Amount owed is #{getTotalCharge}\n"
|
302
|
+
result +=
|
303
|
+
"You earned #{getFrequentRenterPoints} frequent renter points"
|
304
|
+
end
|
305
|
+
|
306
|
+
def htmlStatement
|
307
|
+
result = "\n<H1>Rentals for <EM>#{name}</EM></H1><P>\n"
|
308
|
+
@rentals.each do
|
309
|
+
|each|
|
310
|
+
result += "#{each.aMovie.title}: #{each.getCharge}<BR>\n"
|
311
|
+
end
|
312
|
+
result += "You owe <EM>#{getTotalCharge}</EM><P>\n"
|
313
|
+
result +=
|
314
|
+
"On this rental you earned <EM>#{getFrequentRenterPoints}" +
|
315
|
+
"</EM> frequent renter points<P>"
|
316
|
+
end
|
317
|
+
|
318
|
+
def getTotalCharge
|
319
|
+
result = 0.0
|
320
|
+
@rentals.each do
|
321
|
+
|each|
|
322
|
+
result += each.getCharge()
|
323
|
+
end
|
324
|
+
result
|
325
|
+
end
|
326
|
+
|
327
|
+
def getFrequentRenterPoints
|
328
|
+
result = 0
|
329
|
+
@rentals.each do
|
330
|
+
|each|
|
331
|
+
result += each.getFrequentRenterPoints
|
332
|
+
end
|
333
|
+
result
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
There's a lot of new stuff in here. If we run ZenTest again, it'll
|
338
|
+
pick up the methods we don't have any coverage on (we should have
|
339
|
+
written them as we wrote the new methods, but this is a bit more
|
340
|
+
illustrative). This time, we'll invoke ZenTest a little bit
|
341
|
+
differently:
|
342
|
+
|
343
|
+
$ zentest videostore.rb testVideoStore.rb > Missing_tests
|
344
|
+
|
345
|
+
and our (trimmed) output looks like this:
|
346
|
+
|
347
|
+
# Code Generated by ZenTest v. 2.1.2
|
348
|
+
# classname: asrt / meth = ratio%
|
349
|
+
# Customer: 4 / 6 = 66.67%
|
350
|
+
|
351
|
+
|
352
|
+
require 'test/unit'
|
353
|
+
|
354
|
+
class TestCustomer < Test::Unit::TestCase
|
355
|
+
def test_getFrequentRenterPoints
|
356
|
+
raise NotImplementedError,
|
357
|
+
'Need to write test_getFrequentRenterPoints'
|
358
|
+
end
|
359
|
+
|
360
|
+
def test_getTotalCharge
|
361
|
+
raise NotImplementedError, 'Need to write test_getTotalCharge'
|
362
|
+
end
|
363
|
+
|
364
|
+
def test_htmlStatement
|
365
|
+
raise NotImplementedError, 'Need to write test_htmlStatement'
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
Hmmm, three more test methods to fill in to get our complete
|
370
|
+
coverage. As we write these, we can just migrate them into our
|
371
|
+
existing testVideoStore.rb test suite. Then we can keep moving ahead
|
372
|
+
with refactoring and adding new features. In the future, let's just
|
373
|
+
be sure we add tests as we go along. ZenTest can help you here too.
|
374
|
+
You can write stubs for new development, then run ZenTest to create
|
375
|
+
your new test stubs as well. After some refactorings (like 'extract
|
376
|
+
method'), ZenTest can be used the same way.
|
377
|
+
|
378
|
+
Refactoring and unit testing are powerful tools for programmers, and
|
379
|
+
ZenTest provides an easy way to start using them in a Ruby
|
380
|
+
environment. Hopefully, this introduction has whetted your appetite.
|
381
|
+
|
382
|
+
If you're interested in learning more about refactoring, please grab a
|
383
|
+
copy of 'Refactoring: Improving the Design of Existing Code' and take
|
384
|
+
a look at www.refactoring.com. For more information about unit
|
385
|
+
testing, please see: c2.com/cgi/wiki?UnitTest,
|
386
|
+
www.junit.org/index.htm, and
|
387
|
+
www.extremeprogramming.org/rules/unittests.html.
|
388
|
+
|
389
|
+
The latest information about Test::Unit and ZenTest are available at
|
390
|
+
their home pages: testunit.talbott.ws (for Test::Unit) and
|
391
|
+
www.zenspider.com/ZSS/Products/ZenTest.
|
392
|
+
|
393
|
+
|