Unit Testing is useful for testing your code. At the heart of a unit test are your assetions that check your code. Here is an example.
(define-unit-test check (assert (string=? (string-upcase "Hello world") "HELLO WORLD")))
The assert macro performs the test and reports any problems encountered. This kind of tests goes a long way and allow you to have a nice test suite for your code.
Now let say that you have a web application. For the login process you also have a password reset procedure that resets the password and sends a mail containing the new password to the user. Here is how such a procedure could be implemented.
(define (reset-password-for-user user-name)
(with-db *db*
(lambda ()
(let ((user (find-user-by-name user-name))
(new-password (random-password)))
(set-user-password! user new-password)
(send-mail (user-email user) (string-append "Your new password is:" new-password))))))
You want your unit test to verify that the mail is really sent when you reset a password. What we are going to do is to mock the send-mail procedure. Mocking a procedure consists in modifying the original procedure such that calling it is recorded in the system. Later your unit test will check that a record exists.
So let define the mocking framework.
(define (mock procedure)
(lambda args
(record-procedure-call! procedure args)
(apply procedure args)))
(define-syntax mock!
(syntax-rules ()
((mock! procedure-name)
(set! procedure-name (mock procedure-name)))))
To mock a procedure you call (mock! <your-procedure>). The mock macro registers a procedure to be mocked.
The second step for your unit test is the check definition for ensuring that the code behave correctly. Let's define some check procedures.
(define (assert-that-procedure-was-called-n-times procedure n) (= (length (procedure-called procedure)) n))
Finally you can define your unit test in the following way.
(define-unit-test mock "Check that a mail is sent to the user when we reset the password for a user" (mock! send-mail) (reset-password-for-user "pierre") (assert-that-procedure-was-called-n-times send-mail 1))
A good mock framework provides many more kinds of assertion related to procedure calling. For example instead of simply making sure that the procedure send-mail is called, we could ensure that the parameters are right. Your imagination is the limit here.