[plt-scheme] data setup for SchemeUnit tests

From: Ryan Culpepper (ryan_sml at yahoo.com)
Date: Sat Jul 29 15:12:00 EDT 2006

--- Christopher Armstrong <radix at twistedmatrix.com> wrote:

> (I hope this is the right place to ask this question; I haven't
> found any more appropriate forums specific to SchemeUnit).
> 
> Say I have a test suite like this:
> 
>   (test-suite
>    "amplify-alist"
> 
>    (test-equal? "Basic two element pair list"
>                 (let ([port (open-output-bytes)])
>                   (amplify-alist '((#"hi" . #"there") (#"_command"
> .
> #"something")) port)
>                   (get-output-bytes port))
> 
> #"\x00\x02hi\x00\5there\x00\x08_command\x00\x09something\x00\x00")
> 
>    (test-equal? "Empty list"
>                 (let ([port (open-output-bytes)])
>                   (amplify-alist () port)
>                   (get-output-bytes port))
>                 #"\x00\x00"))
> 
> 
> The duplication of the definition of `port' is unfortunate, and
> I'd like to unify it. I was expecting to be able to do this with
> before and after thunks, but since (AFAICT) they're not executed
> lexically around the test cases that are run, they can't help
> here.  #:before and #:after seem only useful for their
> side-effects (at least the examples in the documentation
> indicate that), and similar for (before) (after) and (around).
> 
> Perhaps I'm thinking about this the wrong way or missing
> something obvious, because it amazes me that SchemeUnit doesn't
> have anything to facilitate this case.  I think what I was
> expecting is to be able to specify something like a bindings
> list that would be evaluated around all tests in a suite.

This kind of problem is not the responsibility of the testing
framework. You can use the standard abstraction mechanisms of Scheme
(procedures and macros) to factor out common patterns in the test
cases. Here are two ideas:

1) Factor out the creation of the output port and the extraction of
the output as bytes into a procedure:
  
  ;; capture-output-bytes : (output-port -> void) -> bytes
  (define (capture-output-bytes proc)
    (let ([outport (open-output-bytes)])
      (proc outport)
      (get-output-bytes)))

Then you could write your second test case as this:

   (test-equal? "Empty list"
                (capture-output-bytes
                  (lambda (port) (amplify-alist () port)))
                #"\x00\x00"))

If 'amplify-alist' used the current output-port, this could be a
little shorter, and then if you made capture-output-bytes a macro
instead, you could eliminate the extra 'lambda' wrapper.

2) You could write a macro that produced the test case from just the
parts that change:

  (define-syntax test-amplify-alist
    (syntax-rules ()
      [(test-amplify-alist name alist expected-bytes)
       (test-equal? name
                    (capture-output-bytes
                      (lambda (port) (amplify-alist alist port)))
                    expected-bytes)]))

  (test-amplify-alist "Empty list" () #"\x00\x00")

Ryan

> If this example seems trivial, I have much worse ones; this one
> serves as a simple demonstration of my problem.
> 
> Thanks for any help.
> 
> -- 
> Christopher Armstrong
> International Man of Twistery
> http://radix.twistedmatrix.com/
> http://twistedmatrix.com/
> http://canonical.com/
> > _________________________________________________
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> 



Posted on the users mailing list.