假设你编写了一个宏或一个包,它会经历软件生命周期的正常过程。你如何定义一组测试,并让这组测试自动运行,以确保对代码的更改在某种意义上是兼容的?
答案1
我认为 TeX 中的单元测试大致可以分为三类:
- 日志文件输出
- DVI/PDF 生成的输出
- 基于 TeX 的编程检查
日志文件输出
Joseph 已经提到了用于 LaTeX2e 和 expl3 的基于日志文件的测试,但值得注意的是,这些测试也可用于检查框和输出的内容,因此它们的范围非常广泛。例如:
\tracingoutput=1 \tracingonline=1
\showboxdepth=999 \showboxbreadth=999
\newbox\foo
\savebox\foo{abc $\cos(x)$}
\showbox\foo
生成的输出
对于unicode-math
我来说,fontspec
我有一个不同的系统,它比日志文件测试更慢且更不可靠,在该系统中,我使用生成的 PDF 来使用 ImageMagick 的工具比较前后差异compare
。
这种方法的主要问题之一是由于光栅化过程中像素舍入误差导致的误报。(并且,安装新字体可能会改变测试的输出。)
不过,我喜欢比较 PDF 的一点是,这样我就可以基于测试套件获得一份可用于演示目的的文档。不过,没有理由不能将其作为任何其他测试过程的副产品来完成。
使用其他评论者建议的基于 DVI 的比较可能更可靠,但我还没有研究那里的各种选项。
编程检查
上述两种技术都需要Makefile
或其他脚本来实现自动化。一种更简单(但不太灵活)的方法是使用qstest
包将单元测试作为 TeX 文档的一部分(通常包含在dtx
源文件中)编写。我们已经在包中成功使用了这种方法hardwrap
,但这种技术确实要求能够以某种方式从 TeX 内部检查测试 — 通常这就足够了。
举个例子hardwrap.dtx
,这种测试看起来像
\begin{qstest}{deal with explicit newlines}{}
\HardWrap{\xdef\TMP}{50}{}{NEWLINE}{aaa bbb^^Jccc}%
\Expect *{\TMP} *{aaa bbbNEWLINEccc}
\end{qstest}
答案2
如果你正在添加新功能,并且你有一个不使用新功能的 LaTeX(或 TeX)文件集合,你可以使用 来检查这些文件是否不受更改的影响dvii
,从dvii 主页。如果您使用命令dvii -p -M1 myfile.dvi > myfile.digest
,您将获得一个“消息摘要”,即“哈希”列表,每个页面一个。如果您随后使用更改后的版本重新创建 myfile.dvi,则可以比较摘要以快速查看任何页面上是否有任何内容发生了更改。
例如,我有大量 LaTeX 文件用于测试文档类。我有一个脚本makedigest
如下:
/bin/sh #!/bin/sh # 我们假设参数是 dvi 文件的名称。 # 我们将消息摘要写入标准输出。 dvii-p-M1$*
对于我运行makedigest
创建的每个文件 myfile.tex myfile.dvi.digest.old
。当我做出不应影响任何文件的更改时,我会运行脚本checknew
,该脚本由以下内容组成
/bin/sh #!/bin/sh 复制代码 对于 f 在 *tex 中;做 对于我在`seq 1 6`中;做 乳胶$f 完毕 完毕 对于 *.dvi 中的 f;do makedigest $f > ${f}.digest.new 完毕 回声 echo“检查错误:” grep 错误*.log echo“检查警告:” grep 警告*.log echo“将新摘要与旧摘要进行比较:” 对于 *.dvi 中的 f;do 回显“${f}:” 差异 ${f}.digest.old ${f}.digest.new 完毕
这样可以快速运行 LaTeX 多次以获得稳定版本,检查错误或警告,并将新摘要与旧摘要进行比较。因此,我很快就能知道哪些测试文档的哪些页面被意外更改了。
答案3
对于 LaTeX2e 内核和当前的 LaTeX3 代码,有一系列仅使用日志数据的自动化测试。这些测试在编程端进行,您可以将结果写入日志。经过一些后处理后,文件仅包含您需要测试的内容,而不包含变量内容(例如,用于\count
特定变量的内容)。因此,最大的问题不是测试本身,而是首先编写测试。(LaTeX3 的自动化系统可从公共 SVN 获得:http://www.latex-project.org/svnroot/experimental/trunk/)
答案4
我一直在考虑为我的 LaTeX 包编写单元测试。
目前,我正在做的是测试生成的 PDF。我今天才开始使用rspec
和pdf-reader
` 在 ruby 中。
这现代时间线包现在有基于生成的 PDF 的单元测试。单元测试位于spec/pdf_spec.rb
文件,到目前为止它主要检查一些内容,例如页数、创建者、媒体框坐标、字体数量和一些内容。
我已经将测试整合到特拉维斯·西实现包的持续集成。请参阅.travis.yml
请参阅存储库中的文件以了解如何完成此操作。