Unit testing racket中的宏单元测试

Unit testing racket中的宏单元测试,unit-testing,racket,Unit Testing,Racket,我目前正在努力完成“美丽的拍子”,试图边写边写单元测试 单元测试宏的最佳方法是什么?例如,如果我有一个宏中缀: (define-macro (infix [A B C]) #'(B A C)) 测试模式匹配和转换最合理的方法是什么?我想做一些类似的事情: (check equal? (infix '(3 - 2)) '(- 3 2)) 通过测试宏的扩展来对宏进行单元测试几乎总是不是您想要的。这有点像用mock测试所有东西,结果是很多测试与某些东西的实现过于耦合,甚至不一定保证其行为 因此,在

我目前正在努力完成“美丽的拍子”,试图边写边写单元测试

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

(define-macro (infix [A B C]) #'(B A C))
测试模式匹配和转换最合理的方法是什么?我想做一些类似的事情:

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

通过测试宏的扩展来对宏进行单元测试几乎总是不是您想要的。这有点像用mock测试所有东西,结果是很多测试与某些东西的实现过于耦合,甚至不一定保证其行为

因此,在测试宏时,您几乎总是希望通过验证宏是否确实执行了正确的操作来测试宏,而不是验证宏扩展到什么。对于您的宏,我只编写一些测试用例,如下所示:

(check-equal? (infix (3 - 2)) 1)
(check-equal? (infix (4 / 2)) 2)
对于执行更复杂操作的宏,我仍然建议不要断言扩展。如果必须,请在此处使用现有的单元测试工具包。即使在测试宏时,同样的原则也适用:使用依赖项注入来替换难以测试的东西,如果需要,为单元测试提供一个稍微低一点的接口,该接口与它的协作者之间没有那么紧密的耦合


如果您确实觉得需要更细粒度的单元测试,那么from可能会有所帮助,因为它允许您评估在测试套件的编译时定义的函数。也就是说,我敦促你尽可能少做这件事。在我使用Racket的时间里,我写了一些非常密集的宏,我设法在不看它们的扩展的情况下测试它们的行为。

我知道有两种策略。(1) 测试作为输出生成的代码的行为,而不是输出本身。这看起来像
(检查相等?(中缀[3-2])1)
。(2) 在宏的大部分复杂性中使用辅助函数,并测试辅助函数。这看起来像是
(define macro(infix-infix-expr)(process infix-infix-expr))
,在这里您可以编写类似
(开始语法)(检查stx-equal?(process infix-infix-expr)[3-2])(-32))
。只是出于兴趣,我快速浏览了(2)并且无法获得任何合理的工作-我在定义宏时遇到
进程中缀:未绑定标识符
错误。您是否将
进程中缀
的定义放在
语法开始
块中?看看答案,看看如何做到这一点。