1 Quick Start Guide for SchemeUnit

Suppose we have code contained in file.scm, which implements buggy versions of + and - called my-+ and my--:

#lang scheme/base
 
(define (my-+ a b)
  (if (zero? a)
      b
      (my-+ (sub1 a) (add1 b))))
 
(define (my-* a b)
  (if (zero? a)
      b
      (my-* (sub1 a) (my-+ b b))))
 
(provide my-+
         my-*)

We want to test this code with SchemeUnit. We start by creating a file called file-test.scm to contain our tests. At the top of file-test.scm we import SchemeUnit and file.scm:

#lang scheme/base
 
(require (planet schematics/schemeunit:3)
         "file.scm")

Now we add some tests to check our library:

(check-equal? (my-+ 1 1) 2 "Simple addition")
(check-equal? (my-* 1 2) 2 "Simple multiplication")

This is all it takes to define tests in SchemeUnit. Now evaluate this file and see if the library is correct. Here’s the result I get:

#t

--------------------

FAILURE

name:       check-equal?

location:   (file-test.scm 7 0 117 27)

expression: (check-equal? (my-* 1 2) 2)

params:     (4 2)

actual:     4

expected:   2

 

--------------------

The first #t indicates the first test passed. The second test failed, as shown by the message.

Requiring SchemeUnit and writing checks is all you need to get started testing, but let’s take a little bit more time to look at some features beyond the essentials.

Let’s say we want to check that a number of properties hold. How do we do this? So far we’ve only seen checks of a single expression. In SchemeUnit a check is always a single expression, but we can group checks into units called test cases. Here’s a simple test case written using the test-begin form:

(test-begin
 (let ((lst (list 2 4 6 9)))
   (check = (length lst) 4)
   (for-each
    (lambda (elt)
      (check-pred even? elt))
    lst)))

Evalute this and you should see an error message like:

--------------------

A test

... has a FAILURE

name:       check-pred

location:   (#<path:/Users/noel/programming/schematics/schemeunit/branches/v3/doc/file-test.scm> 14 6 252 22)

expression: (check-pred even? elt)

params:     (#<procedure:even?> 9)

--------------------

This tells us that the expression (check-pred even? elt) failed. The arguments of this check were even? and 9, and as 9 is not even the check failed. A test case fails as soon as any check within it fails, and no further checks are evaluated once this takes place.

Naming our test cases if useful as it helps remind us what we’re testing. We can give a test case a name with the test-case form:

(test-case
 "List has length 4 and all elements even"
 (let ((lst (list 2 4 6 9)))
   (check = (length lst) 4)
   (for-each
    (lambda (elt)
      (check-pred even? elt))
    lst)))

Now if we want to structure our tests are bit more we can group them into a test suite:

(define file-tests
  (test-suite
   "Tests for file.scm"
 
   (check-equal? (my-+ 1 1) 2 "Simple addition")
 
   (check-equal? (my-* 1 2) 2 "Simple multiplication")
 
   (test-case
    "List has length 4 and all elements even"
    (let ((lst (list 2 4 6 9)))
      (check = (length lst) 4)
      (for-each
        (lambda (elt)
          (check-pred even? elt))
      lst)))))

Evaluate the module now and you’ll see the tests no longer run. This is because test suites delay execution of their tests, allowing you to choose how you run your tests. You might, for example, print the results to the screen or log them to a file.

Let’s run our tests, using SchemeUnit’s simple textual user interface (there are fancier interfaces available but this will do for our example). In file-test.scm add the following lines:

(require (planet schematics/schemeunit:3/text-ui))
 
(run-tests file-tests)

Now evaluate the file and you should see similar output again.

These are the basics of SchemeUnit. Refer to the documentation below for more advanced topics, such as defining your own checks. Have fun!