Re: SchemeUnit 2.0rc1: difficulty defining new assertions

Noel Welsh <noelwelsh-/[email protected]> Sat, 1 Jan 2005 10:53:58 -0800 (PST)
Newsgroups gmane.lisp.scheme.plt.schematics.general
Message-ID <[email protected]>
Hello,

> I want to write something like this:

>    (assert-parse-exn MSG VAL EXPR)

> where EXPR is an arbitrary expression.  The assertion
> should pass if evaluating EXPR throws an exn:cj:parse
with
> a message of MSG and a value that is equal? to VAL; the
> assertion should fail otherwise.

> I've tried the four following possibilities, and only the
> fourth works.  The rest signal an uncaught exception of
> type exn:cj:parse when I try to run the test case.

The problem is that assertions evaluate their arguments,
like functions.  So you want to parse them thunks not
expressions -- the expression is evaluated before the
assertion is called and so the exn:cj:parse is raised
outside of the assertion.

Below if an assertion using define-assertion and assert-exn
that does what you want:

(define-assertion (assert-parse-exn msg val thunk)
  (assert-exn (lambda (exn)
                ;; I'm using or as a sequencing construct
                (or (exn:cj:parse? exn)
                    (with-assertion-info
                     (('message "Wrong exception raised"))
                     (fail-assertion)))
                (or (string=? msg (exn-message exn))
                    (with-assertion-info
                     (('message "Wrong message provided")
                      ('provided-message (exn-message exn))
                      ('expected-message msg))
                     (fail-assertion)))
                (or (equal? val (exn:application-value
exn))
                    (with-assertion-info
                     (('message "Wrong value provided")
                      ('provided-value
(exn:application-value exn))
                      ('expacted-value val))
                     (fail-assertion))))
              thunk))

The points to note about this assertion are:

  - It accepts a thunk, not an expression

  - It makes use of assert-exn.  In 1.x only the inner most
    assertion would report any information on failure.  The
    new message reporting system in SchemeUnit 2.0 allows
    much better composition of assertion.

  - I've used with-assertion-info to provide useful
    debugging information on each different type of
failure.

    We have to use define-assertion, not
    define-simple-assertion, as define-simple-assertion
    cannot report extra information with
    with-assertion-info.

An example:

(require (lib "test.ss" "schemeunit")
         (lib "text-ui.ss" "schemeunit"))

(define-struct (exn:cj:parse exn:application) ())

(define-assertion (assert-parse-exn msg val thunk)
  (assert-exn (lambda (exn)
                ;; I'm using or as a sequencing construct
                (or (exn:cj:parse? exn)
                    (with-assertion-info
                     (('message "Wrong exception raised"))
                     (fail-assertion)))
                (or (string=? msg (exn-message exn))
                    (with-assertion-info
                     (('message "Wrong message provided")
                      ('provided-message (exn-message exn))
                      ('expected-message msg))
                     (fail-assertion)))
                (or (equal? val (exn:application-value
exn))
                    (with-assertion-info
                     (('message "Wrong value provided")
                      ('provided-value
(exn:application-value exn))
                      ('expacted-value val))
                     (fail-assertion))))
              thunk))

(test/text-ui
   (make-test-suite
    "Example test suite"
    (make-test-case
     "Successful test case"
     (assert-parse-exn 
      "message" 
      'value 
      (lambda () 
        (raise 
         (make-exn:cj:parse
          "message"
          (current-continuation-marks)
          'value)))))
    
    (make-test-case
     "Failing test case"
     (assert-parse-exn
      "message"
      'value
      (lambda ()
        (raise
         (make-exn:cj:parse
          "message" 
          (current-continuation-marks) 
          'foo)))))
    ))

The output is given below:

Failure:
--------
Failing test case
#<struct:object:/proj/scheme/plt/collects/test-suite/tool.ss:89:8>:7:2
  message: Wrong value provided
  provided-value: foo
  expacted-value: value
  name: assert-exn
  location:
(#<struct:object:/proj/scheme/plt/collects/test-suite/tool.ss:89:8>
7 2 186 895 #f)
  expression: (assert-exn (lambda (exn) (or (exn:cj:parse?
exn) (with-assertion-info (('message Wrong exception
raised)) (fail-assertion))) (or (string=? msg (exn-message
exn)) (with-assertion-info (('message Wrong message
provided) ('provided-message (exn-message exn))
('expected-message msg)) (fail-assertion))) (or (equal? val
(exn:application-value exn)) (with-assertion-info
(('message Wrong value provided) ('provided-value
(exn:application-value exn)) ('expacted-value val))
(fail-assertion)))) thunk)
  params: (#<procedure:7:14> #<procedure:42:4>)
  name: assert-parse-exn
  location:
(#<struct:object:/proj/scheme/plt/collects/test-suite/tool.ss:89:8>
42 4 1398 233 #f)
  expression: (assert-parse-exn message 'value (lambda ()
(raise (make-exn:cj:parse message
(current-continuation-marks) 'foo))))
  params: (message value #<procedure:42:4>)

1 success(es)  0 error(s)  1 failure(s)
----------------------------------------------------

I'll update the documentation to make the issue of
evaluation of arguments explicit.

HTH,
Noel

=====
Email: noelwelsh <at> yahoo <dot> com
AIM: noelhwelsh


		
__________________________________ 
Do you Yahoo!? 
Dress up your holiday email, Hollywood style. Learn more. 
http://celebrity.mail.yahoo.com


-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt