TeX用のqstestというユニットテスティングライブラリがあるらしい。

準備

とりあえずqstest.styと下請けのmakematch.styがあれば動くようなので、用 意する。

% wget http://mirror.ctan.org/macros/latex/contrib/qstest.zip
% unzip -d tmp qstest.zip
% cd tmp/qstest
% make qstest.sty makematch.sty
...
% mv makematch.sty qstest.sty ../../
% cd -
% rm -fr tmp

テストは\RequirePackage{qstest}したスタイルファイルとして書く。xUnitの 語彙で言うと、qstest環境がテストケース、\Expectがassertに相当するもの らしい。

% vi foo.sty
% vi testfoo.sty
% head testfoo.sty
==> testfoo.sty <==
\RequirePackage{qstest}
\RequirePackage{foo}

\begin{qstest}{# in isolation 2}{\Expect, #, \string}
  \toks0{# and #}
  \Expect*{\the\toks0}*{\unexpanded{# and #}}
\end{qstest}

文書を用意する。

% vi foo.tex
% head foo.tex
==> foo.tex <==
\documentclass{article}
\usepackage{testfoo}
\begin{document}
Foo.
\end{document}

(実際には、望みどおりの結果になっているか目視でも確認できるように、 foo.styで定義されたマクロを使って何か書いておくとよさそう。)

実行

文書をコンパイルすると、テストの実行結果がログに書き出される。

% latex foo.tex
...
% grep 'qstest Info:' foo.log
Package qstest Info: Passed: ## in isolation 2 on input line 7.
%

成功している模様。

困ったこと

eTeX拡張なしのpTeXでは動かない(e-pTeXやe-upTeXでは問題ないはず)。

% platex foo.tex
...
! Undefined control sequence.
\\MakeMatcher [#1]#2#3->\edef #2{\detokenize
...
l.36 \TestErrors{*, !fails}

参考:http://tex.loria.fr/moteurs/etex_ref.html#detokenize

pTeXで無理矢理動かす(非推奨)

.dtxからetexオプションを削除したうえで.styを生成すると、非eTeX向けにダ ウングレードされた.styが出力される。ただしREADMEでは非推奨でサポートな しとされているので注意。

% sed -i.bak 's/,etex//g' qstest.dtx
% diff -u qstest.dtx.bak qstest.dtx
--- qstest.dtx.bak
+++ qstest.dtx
@@ -602,13 +602,13 @@
 \input docstrip
 \ifx\Make y\askforoverwritefalse\fi
 \generate{
-  \file{qstest.drv}{\from{qstest.dtx}{driver,test,etex}}
-  \file{qstest-qs.tex}{\from{qstest.dtx}{test,etex}}
-  \file{makematch.drv}{\from{makematch.dtx}{driver,etex}}
-  \file{makematch-qs.tex}{\from{makematch.dtx}{test,etex}}
+  \file{qstest.drv}{\from{qstest.dtx}{driver,test}}
+  \file{qstest-qs.tex}{\from{qstest.dtx}{test}}
+  \file{makematch.drv}{\from{makematch.dtx}{driver}}
+  \file{makematch-qs.tex}{\from{makematch.dtx}{test}}
   \ifx\Make y\else \usedir{tex/latex/qstest}\fi
-  \file{qstest.sty}{\from{qstest.dtx}{package,etex}}
-  \file{makematch.sty}{\from{makematch.dtx}{package,etex}}}
+  \file{qstest.sty}{\from{qstest.dtx}{package}}
+  \file{makematch.sty}{\from{makematch.dtx}{package}}}
 \endbatchfile
 %</installer>
 %    \end{macrocode}

% make qstest.sty makematch.sty

テストのほうも、\unexpandedといったeTeX拡張を使わないように適宜修正する。

% vi foo.sty
% vi testfoo.sty
% head testfoononetex.sty
==> testfoononetex.sty <==
\RequirePackage{qstest}
\RequirePackage{foo}

\begin{qstest}{# in isolation 2}{\Expect, #, \string}
  \toks0{# and #}
  \Expect*{\the\toks0}*{\string#\string# and \string#\string#}
\end{qstest}

あとは同様。

雑感

とりあえずpTeXで実行できるか試してみただけで、テストの書き方はまだよく分 からない。文脈依存だったり副作用が目的だったりするマクロはテストが難しそ う。

ともあれ、これだけの道具とドキュメントを用意してくれたことは大変ありがた いし、TeX方面にもテストの有用性を理解している人がいると分かってうれしい。