This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: A SUnit Extension
Feed Title: Richard Demers Blog
Feed URL: http://www.cincomsmalltalk.com/rssBlog/rademers-rss.xml
Feed Description: Richard Demers on Smalltalk
Last week I was developing SUnit test cases for code that generates long, deeply-nested XML strings. In the test cases I compared the generated string with a known hand-written string. Great when a test succeeded, but when it failed I had the problem of comparing the strings and finding the discrepancies. I started out using two Inspectors to view the strings, but that quickly became tiresome. Class Store.TextDifferenceBrowser was an easy answer -- just give it two strings and it opens a window that shows you the differences. All I had to do was code my test cases with
But of course I didn't really want a comparator window opening every time I ran the test case. My next step was to extend my subclass of TestCase with the following method:
and the comparator window opens only if the test fails.
But there was still a problem. Test cases can be run in either Run mode or in Debug mode. The main difference is that in Run mode failures are logged and counted as a series of test cases is run, while in Debug mode a debugging window opens at the first failure. So my next problem was to limit the opening of the comparator window to only Debug mode.
A quick scanning of the SUnit source code didn't show me how to distinguish between Run mode and Debug mode, but clearly there was such a distinction. It's great to have source code available to study, but that takes time so I took the easy way out and sent out a query on a Smalltalk mailing list. Michael Lucas-Smith shot right back with the answer. Here it is (with a bit of editing):
We do that in WithStyle so that if a test fails and we ran it in debug, it leaves the window open so we can see why it drew wrongly. If it's not running in debug, the window gets closed no matter what (otherwise, with 500 windows open you tend to run out of system resources ;>)
Here's how we did it:
Add instance variable isDebug to your TestCase subclass, along with a setter method.
Implement #debug to do:
self resources do: [:res | res isAvailable ifFalse: [^res
signalInitializationError]].
[(self class selector: testSelector)
isDebug: true;
runCase]
sunitEnsure: [self resources do: [:each | each reset]]
Now you have isDebug set to true whenever you're running in debug mode. A new instance of your test case class is made for each test, so its default value is nil. So also add method:
isDebug
^isDebug == true
Here's my modified #assert:equals: method, using the new isDebug TestCase state.
VisualWorks Smalltalk (and other versions, too) have a wide range of useful tools readily available to help programmers get the job done -- SUnit and the DifferenceBrowser in this case.
The source for these tools is also available, it can be studied, and it can be modified to meet new needs. There is no need to beg someone to eventually "fix" the language. You can do it yourself.
The Smalltalk community is wonderfully helpful and willing to share ideas, techniques and code.
I'd be willing to bet that Michael's way of distinguishing between Run mode and Debug mode for test cases has many other uses. Maybe it should be integrated into SUnit itself.