It's possible to enforce and test contracts defined at the module boundary within a
test module in the same file. Do this by
(submod "..") in the
Found at Confused about racket contracts - Stack Overflow
Usually my modules are of the form
Testing the module mostly works fine, however the contracts defined with
contract-out aren't applied in the tests. It would be possible to work around this by defining module contents with
define/contract etc., but this has the disadvantage that the contracts are checked for all uses in the module which might slow down the code too much.
When I was looking for a way to test the contracts defined with
contract-out from within the same file, I found the above StackOverflow answer. Due to the
(submod "..") import in the
test module it accesses the module in the same file across the file's module boundary.
Another tip related to testing contracts: If a contract is relatively complicated and especially if it's difficult to test procedures where the contract is used, it may make sense to put the contract in its own predicate function and test this function.
For example, today I wrote this code:
(and/c (listof (or/c 'completed? 'priority 'completion-date 'creation-date))
; These aren't actual dates, but they work the same way for
(define completion-date (index-of omit-fields 'completion-date))
(define creation-date (index-of omit-fields 'creation-date))
; In the context of `task->string` we're interested in omitting the
; fields, i.e. _not_ having them.
(task-date-combination/c (not completion-date) (not creation-date)))))
(the concrete background isn't relevant here), and I test
omit-fields/c on its own in the
"Valid date combinations"
(check-true (task-date-combination/c #f #f))
(check-true (task-date-combination/c #f "2022-01-04"))
(check-true (task-date-combination/c "2022-01-04" "2022-01-03")))
"Completion date without creation date"
(task-date-combination/c "2022-01-04" #f))
"Invalid task field symbol"
(omit-fields/c '(priority invalid)))
"Omit both dates"
(omit-fields/c '(priority creation-date completion-date)))
"Omit completion date, but keep creation date"
(omit-fields/c '(priority completion-date)))
"Omit neither date"
"Omit creation date, but keep completion date"
(omit-fields/c '(priority creation-date)))