首页 > 解决方案 > 球拍中的单元测试宏

问题描述

我目前正在努力通过“美丽的球拍”,尝试编写单元测试。

单元测试宏的最佳方法是什么?例如,如果我有一个宏infix

(define-macro (infix [A B C]) #'(B A C))

测试模式匹配和转换的最明智的方法是什么?我想做类似的事情:

(check equal? (infix '(3 - 2)) '(- 3 2))

标签: unit-testingracket

解决方案


通过测试宏的扩展来对宏进行单元测试几乎总是不是您想要的。这有点像用 mocks 测试所有东西——你最终会得到很多测试,这些测试过于耦合到某些甚至不一定能保证其行为的东西的实现

因此,当你测试一个宏时,你几乎总是想通过验证它确实做了正确的事情来测试它,而不是它扩展成什么。在你的宏的情况下,我会写一些这样的测试用例:

(check-equal? (infix (3 - 2)) 1)
(check-equal? (infix (4 / 2)) 2)

对于做更复杂事情的宏,我仍然建议不要对扩展进行断言。如果必须,请在此处使用现有的单元测试工具包。即使在测试宏时,同样的原则也适用:使用依赖注入来替换难以测试的东西,如果需要,可以为单元测试提供一个级别稍低的接口,该接口与其协作者的耦合度不高。

如果您确实觉得需要更细粒度的单元测试,phase1-evalfromsyntax/macro-testing可能会有所帮助,因为它允许您评估在编译时在测试套件中定义的函数。也就是说,我敦促您尽可能少地这样做。在我使用 Racket 期间,我编写了一些非常强大的宏,并且我设法在没有查看它们的扩展的情况下对它们进行了行为测试。


推荐阅读