I'll also throw my hat in the ring with handy/test-more, which I'm in the process of breaking out into a separate module but have not yet found the tuits to finish.
It takes a different approach than rackunit: Tests always have output regardless of whether they succeed or fail. Running a different number of tests than expected is an error. Not declaring how many tests you will run (or, equivalently, putting (done-testing) at the bottom of your file) is a warning. Tests return their final value so that you can use the results of a test as part of a separate test. Typically you will group tests in a test-suite. A test suite is itself a test, the nature of which is "none of my tests threw an exception that they didn't handle." As such, the test suite will report a failing test if an exception occurs, but the test script as a whole will continue. #lang racket (require "../collaborations.rkt" handy/test-more) (test-suite "collaboration-id" (is (collaboration-id "public") 1 "happy path: found the public collaboration") (throws (thunk (collaboration-id "foo")) exn:fail:db:num-rows:zero? "collaboration-id throws if there was no such collaboration and #:create was #f") (define foo-id (lives (thunk (collaboration-id "foo" #:create #t)) "(collaboration-id 'foo' #:create #t) worked when the collaboration w\ as NOT there ")) (if (equal? 'windows (system-type 'os)) (ok 'do-some-windows-only-tests "did the windows-only tests") (ok #t "did NOT do the windows-only tests because this isn't Windows"))) > racket example.rkt ######## (START test-suite: collaboration-id) ok 1 - happy path: found the public collaboration ok 2 - collaboration-id throws if there was no such collaboration and #:create was #f ok 3 - (collaboration-id 'foo' #:create #t) worked when the collaboration was NOT there ok 4 - did NOT do the windows-only tests because this isn't Windows ok 5 - test-suite completed without throwing uncaught exception Total tests passed so far: 5 Total tests failed so far: 0 ######## (END test-suite: collaboration-id) WARNING: Neither (expect-n-tests N) nor (done-testing) was called. May not have run all tests. On Wed, Apr 3, 2019 at 2:44 PM Lukas Lazarek <lukasalaza...@gmail.com> wrote: > If you want your tests to catch exceptions you need to wrap them in > exception handlers, which you could write a macro to do for you; as Eric > noted though you need to be careful to preserve source locations. > > These kinds of issues (error messages and managing source locations when > using macros) led me to write a small testing package > <https://pkgd.racket-lang.org/pkgn/package/ruinit> that might suit your > needs. > Using the package you could do something like this: > > #lang racket >> >> (require ruinit) >> >> (define (f x) >> (error 'f)) >> >> (define-test-syntax (fail-if-throws test) >> #'(with-handlers ([exn? >> (λ (e) >> ((error-display-handler) (exn-message e) e) >> (fail "Exception thrown during test (see >> above)"))]) >> test)) >> >> (test-begin >> (fail-if-throws (test-= (f 2) 2))) >> > > which shows a message like this: (running with errortrace to get the > exception context) > >> ; error: f >> ; Context (errortrace): >> ; tmp.rkt:6:2: (error (quote f)) >> ; tmp.rkt:16:18: (test-= (f 2) 2) >> ; ... >> --------------- FAILURE --------------- >> location: test4.rkt:16:2 >> test: (fail-if-throws (test-= (f 2) 2)) >> message: Exception thrown during test (see above) >> --------------------------------------- >> > > As requested, this points you to both the source of the exception and the > test in which it was thrown. > > Lukas > > On Wednesday, April 3, 2019 at 3:21:37 AM UTC-5, zeRusski wrote: >> >> >> #lang racket/base >>> (define f (λ _ (error 'FAIL))) >>> (module+ test >>> (require rackunit) >>> (define OK (string->unreadable-symbol "OK")) >>> (define-syntax-rule (check-OK-form expr) >>> (let ([val expr]) >>> (with-check-info (['input 'expr] ['expected OK] ['actual val]) >>> (check eq? val OK)))) >>> (check-OK-form OK) >>> *(check-OK-form (values #f))* >>> (check-OK-form (f))) >>> >>> Even without a C-u prefix, the input can help locate the offending >>> check: >>> >>> -------------------- >>> ; FAILURE >>> ; /tmp/somefile.rkt:9:8 >>> input: (values #f) >>> expected: OK >>> actual: #f >>> name: check >>> location: somefile.rkt:9:8 >>> -------------------- >>> ; error: FAIL >>> ; Context: >>> ; (submod "/tmp/somefile.rkt" test):1:1 [running body] >>> >> >> Argh, I was too hasty to declare the with-check-info the winner here. >> Note that you get this extra info when the check actually fails, in your >> example above the (values #f) case fails, note the next one that calls >> (f) that throws. In this latter case the stack is nowhere to be found >> and no extra check info is present, so you are essentially back to square >> one, sigh. Now this really bothers me cause all of my tests turn into a >> black box that I need to poke and prod whenever something breaks. > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.