Notes by Ed Kademan <email@example.com>
The sixth meeting of Scheme Boston took place at Northeastern University Monday night February 10, 2003. Approximately 10 people showed up to hear Mike Machenry describe his tool for helping programmers define and run unit tests in the DrScheme environment.
Scheme naturally lends itself to an interactive and incremental style of software development. Mike's project builds on these strengths by providing an integrated system that makes it much easier for users to ensure the correctness of the code they write as they write---and rewrite---it. A unit test simply executes some function and compares the value returned with an expected value. If the two agree the test succeeds, if not it fails. As developers write their programs piece by piece they simultaneously define simple unit tests, one for each piece. As long as that series of tests succeeds they can more confidently advance, and since programming is never simply a straightforward process of "advancing" but often involves revisiting old code and revising it those tests serve as a valuable check that the reworking of previously written units is not introducing new bugs. Unit tests cannot be perfectly comprehensive and catch every conceivable problem, but they can catch many.
Also, their power and usefulness grows as the time and effort required to define and use them shrinks. Mike's system is integrated into the DrScheme IDE in a seamless way and provides a graphical user interface so that the additional burden it imposes on the programmer is as small as possible. From within DrScheme a menu entry for defining a new test suite calls up a window with text boxes labelled "Call," "Expected," and "Actual." The user enters the expression to test and the value that that expression should return in the "Call" and "Expected" boxes respectively. Subsequently whenever the test executes, DrScheme evaluates the expression, puts the result in the "Actual" box, and draws either a green check mark or a red "x" next to it depending on whether or not the actual and expected agree. The system saves these test suites in disk files and knows to associate them with their corresponding source files. It does this even for source and tests written in the DrScheme module language, so that developers can keep the two separate.
One could argue that the test suite tool is simple to use because it is incomplete and hasn't reached its more featurefull and necessarily more complicated final state. Mike emphasized that it is still a work in progress and that there are other capabilities that he wants to incorporate, such as tighter integration with the standard REPL of DrScheme and the ability to automatically run several test suites at once---or even conditionally, so that for example some tests only execute if a preceeding one succeeded or failed. But the bulk of his talk---in which he described the mechanics of building tools for extending DrScheme---implicitly advanced the argument that such enhancements need not complicate the user interface excessively. DrScheme's underlying language and module system facilitate code reuse in such a way that implementors like Mike can elaborate the IDE's functionality in a relatively unobtrusive way.
DrScheme supports the building of first-class modules called units---not to be confused with the "unit" in "unit test"---that leave some or all of their imports unspecified and that can be passed around and mixed together. A tool such as the test suite tool is simply a module that supplies a unit. Also, the test suite code makes heavy use of another idiom that the language supports and that goes by the name of "mixin." In this context a mixin is a function that takes a class as argument and returns another class. The class returned (subclass) is an elaboration of the argument class (superclass) to which presumably the mixin has added new capabilities. After a mixin---or a composition of mixins---has specialized a class in this way it will behave differently while still maintaining its identity as the base class.
Units and mixins make it possible to build onto the base features of the IDE. (For example the test suite tool adds an entry for creating a test to the standard menu.) They also ease the task of providing for separate nonstandard execution environments, so that the test suite tool can evaluate expressions safely without interfering with the executive. In this way users can even test that their expressions fail in a particular way.