As Leif mentions, RackUnit's require/expose
will allow using unprovided identifiers in other modules, but its own documentation doesn't promise a very strong guarantee:
Note that require/expose
can be a bit fragile, especially when mixed with compiled code. Use at your own risk!
Another approach would be to use submodules, which can effectively provide a sanctioned way to export a private API for use in tests or other means.
For example, consider a module that implements a function to test if a string contains a single word:
#lang racket
(provide word?)
(define (word? str)
(not (ormap space? (string->list str))))
(define (space? c)
(eq? c #\space))
(This is, perhaps, not the most realistic example, but bear with me.)
It might be useful to test the space?
function to ensure it works, but it likely shouldn't be part of the public API. To create an "escape hatch", it's possible to define a submodule that exports this binding:
(module+ for-testing
(provide space?))
The name for-testing
is arbitrary—it could be anything. Either way, it is now possible to require that submodule in another module to get access to the private bindings:
#lang racket
(require rackunit
(submod "a.rkt" for-testing))
(check-true (space? #\space))
(check-false (space? #\a))
This is something of a safer way to expose identifiers from modules without exposing them to all consumers.