[racket] A `check-expansion` for rackunit to test macros?
I recently got a pull request where someone defined a
`check-expansion` form to use with rackunit. Simplified excerpt:
#lang racket/base
(require syntax/parse/define)
(define-simple-macro (if-let [binding:id value:expr] then:expr else:expr)
(let ([binding value])
(if binding then else)))
(module+ test
(require rackunit)
(define (check-expansion input expected-output)
(check-equal? (syntax->datum (expand-once input)) expected-output))
(check-expansion '(if-let [x #t] 0 1) '(let [(x #t)] (if x 0 1))))
Although DrRacket doesn't warn that the the test fails, it fails with
`raco test`:
raco test conditionals.rkt
raco test: (submod "conditionals.rkt" test)
if-let: unbound identifier;
also, no #%app syntax transformer is bound
at: if-let
in: (if-let (x #t) 0 1)
context...:
/Users/greg/src/scheme/collects/rackjure/rackjure/conditionals.rkt:11:2:
check-expansion
/Users/greg/src/scheme/collects/rackjure/rackjure/conditionals.rkt:
[running body]
/Applications/Racket_v5.3.5/collects/compiler/commands/test.rkt:29:10:
for-loop
f8
/Applications/Racket_v5.3.5/collects/compiler/commands/test.rkt:
[running body]
/Applications/Racket_v5.3.5/collects/raco/raco.rkt: [running body]
/Applications/Racket_v5.3.5/collects/raco/main.rkt: [running body]
Without giving it much time or deep thought, I came up with this
version which succeeds in both DrRacket and raco test:
(module+ test
(require rackunit)
(define (check-expansion input expected-output)
(check-equal? (syntax->datum (expand-once input))
(syntax->datum expected-output)))
(check-expansion #'(if-let [x #t] 0 1) #'(let [(x #t)] (if x 0 1))))
In light of that:
[1] Why don't DrRacket and `raco test` both succeed for the first version?
[2] Is my new version correct?
[3] Could/should rackunit provide something like `check-expansion`?