11

将测试代码翻译为文档

 3 years ago
source link: https://yihui.org/cn/2018/08/test-to-doc/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

将测试代码翻译为文档

谢益辉 / 2018-08-02


我有一个大胆的想法。这个想法萌生于我召唤壮士帮我写测试时。我的 R 包的测试代码都是基于我自己的轻量级 R 包 testit,我不用流行的 testthat 是因为我觉得它把语法搞得太复杂,活生生造出一套词汇。所谓测试,无非就是当(函数)输出与预期不符时,就给个提醒,这个提醒通常是报错。testit 的测试语法很简单,只由一个函数 assert() 和一个特殊语法构成,形如

library(testit)
assert('某函数 foo() 应该输出某结果', {
  # 任意 R 代码
  
  (foo() == '预期结果')  # 测试条件
})

上面说的特殊语法就是,测试条件要写在一对小括号中,这是为了让 assert() 知道花括号内部哪些 R 代码是应该被检测的。每个测试条件必须返回元素全部为 TRUE 的逻辑向量(长度大于等于 1)。花括号里可以写任意 R 代码以及多个测试条件,每个条件都得在小括号里。如果测试条件返回的不全是 TRUE,那么 assert() 就会报错。原理就是这么简单。

一般情况下,只有开发者自己知道测试的存在,用户不会关心一个包里有哪些测试,但其实测试在某种程度上也是宝贵的文档,把测试代码埋在地底下有些可惜。此话怎讲?

文档通常是文字描述。文字描述的问题就是可能会不精确,不同的人理解起来也可能会不一样。测试则是同时给出了源代码和它的预期输出,若读者能同时读这两部分,那么也许可以增强他们对一个函数的理解。代码和数学公式一样,都是精确的表达形式(所以有那句话:“废话少说,放码过来”)。

那么问题来了。测试代码的形式通常比较乱,普通青年应该不会爱读这样的源代码。要是能把代码重新组织一下,做成一篇文章或报告的形式,可读性应该可以大大增加。以 testit 的测试为例:assert() 的第一个参数(字符串)可以作为小节标题,花括号内的任意 R 代码可以作为普通代码段,测试条件则可以作为表格或某种双栏形式呈现。比如上面的测试可以翻译为下面的 Markdown 文档:

# 某函数 foo() 应该输出某结果

```r
# 任意 R 代码
```

------- -----------
foo()     预期结果
------- -----------

更进一步,如果再用一点黑魔法,把这样的输出塞进相应的 R 帮助文档中,那么一个函数的帮助文档中不仅可以看文字文档、只有源代码的例子,还可以看相关的测试,让用户知道一个函数在不同条件下预期应该返回什么值。那就厉害了我的哥。

上面的从测试到文档的翻译咋整呢?因为 R 继承了 Lisp 的“代码本身就是数据”的特征,你有了代码之后想怎么解析、运行都可以,所以翻译应该不成问题(虽然我也没有十成把握)。我在 assert()查探测试条件的小括号其实不过就是用了 match.call() 和表达式(expression)的简单魔法。

当然,这整件事情还可以完全反过来做,也就是从文档到测试。这个在去年的 R OpenSci 小会上已经有几位黑客尝试过了

桥水的招聘邮件 壮士的进步

Disqus Utterances Preferences

© Yihui Xie 2005 - 2020

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK