LaTeX 的测试框架 API

LaTeX 的测试框架 API

作为在线考试应用程序的一部分,我们需要自动评估学生编写的 LaTeX 脚本。本质上,应该根据一组测试用例评估脚本,如果脚本通过,则所有测试用例都应返回通过 (true),否则应返回错误消息,以便学生可以重试该问题。

我们遇到了qstest,但我想知道是否有更好的解决方案,可以轻松高效地应用于 Web 应用程序。该 Web 应用程序是使用 Django 开发的。

答案1

使用多种语言进行测试断言和您在问题中提到的测试用例。 中的断言LaTeX可以采用以下一般形式:

      \def\test#1{\def\res{#1}\ifx\foo\res\else\ERROR\fi}

或者只返回“通过”或“失败”。对于较长的测试用例,我倾向于后者,而且如果对结果进行颜色编码,很容易发现错误。

在此处输入图片描述

代码可以根据含义简单判断真假

\newcommand\assert[2][]{%
   \ttfamily
   \def\result{#2}
   \ifx\foo\result\textcolor{green}{Passed}%
     \else \textcolor{red}{Failed}\fi
   \space Test:\,\stepcounter{tst}\thetst
   \detokenize{#1}
\par}

或检查事物是否已经定义(有时很棘手)。

% Checks if defined can be unreliable
\newcommand\assertdef[2][]{
 \ttfamily
  \ifdefined#2\textcolor{green}{Passed}%
     \else \textcolor{red}{Failed}\fi
   \space Test:\,\stepcounter{tst}\thetst
   \detokenize{#1}
\par
}

下面的 MWE 示例测试了一些定点算法和一些Lisp 遗迹来自 LaTeX 内核并生成上图的输出:

\documentclass{article}
\usepackage{xcolor,fp}
\parindent0pt
\makeatletter
\newcounter{tst}
\setcounter{tst}{9}
% asserts true on meaning
\newcommand\assert[2][]{%
   \ttfamily
   \def\result{#2}
   \ifx\test\result\textcolor{green}{Passed}%
     \else \textcolor{red}{Failed}\fi
   \space Test:\,\stepcounter{tst}\thetst
   \detokenize{#1}
   \par}
% Checks if defined can be unreliable
\newcommand\assertdef[2][]{
 \ttfamily
  \ifdefined#2\textcolor{green}{Passed}%
     \else \textcolor{red}{Failed}\fi
   \space Test:\,\stepcounter{tst}\thetst
   \detokenize{#1}
\par
}
\begin{document}
\section{\jobname\\ \today}
\edef\test{\@car 123\@nil}\assert[\@car 123\@nil==1]{1}
\edef\test{\@car{1}23\@nil} \assert[\@car {1}23\@nil==1]{1}
\edef\test{\@car {123}{456}{7}\@nil} \assert{123}
\edef\test{\@carcube1234567\@nil}\assert{123}
\edef\test{\@cdr 123\@nil} \assert{23}
\edef\test{\@cdr {134}{x}\@nil}\assert{x}
\edef\test{\@cdr {134}{{x}}\@nil}\assert{{x}}
\let\test\@nnil\assert{\@nil}
\toks@={abc\test}\addto@hook\toks@{x\bar}
\expandafter\def\expandafter\test\expandafter{\the\toks@} \assert{abc\test x\bar}
\g@addto@macro\test{y\gee} \assert{abc\test x\bar y\gee}
\def\xx{456}
\def\test{123}\@cons\test{\xx78}\assert{123\@elt45678}
\@cons\test{\xx780}\assert{123\@elt45678}
% assert if defined
\assertdef\assert
\assertdef[\@@par is defined]\@@par
% asserts for fp values
\FPadd\test{1}{1}\assert[\FPadd\test{1}{1}==2.000000000000000000]{2.000000000000000000}
\FPadd\test{1}{1}\assert[\FPadd\test{1}{1}==2.00000000000000000]{2.000000000000000000}
\end{document}

人们可以更有创造力并创建额外的断言,例如\assertfalse\assertcat用于类别代码检查等。据我了解,LaTeX3 团队做了很多测试;然而,将上述内容应用到学习环境中,我不太确定这样做是否可行或可取。

在教程中,你将主要测试如何掌握命令的使用。对于在线应用程序,我会选择Moodle带有用于考试和测验的内置结构的安装类型,但后来你选择了 Django:)

答案2

下面是我用来帮助编写的断言例程更新LaTeX lawtex 包。

\documentclass{article}
\usepackage{xstring} % IfEq, StrCompare
\usepackage{xcolor}

\newcounter{tst}

% \assert{test name}{string value1}{string value 2}- will test that
% the second argument matches the third argument and print in green if
% it passed or in red if it fails.
\long\def\assert#1#2#3{{% add a block to prevent namespace pollution
    % Note that you cannot use the macro on macros with optional
    % arguments because the macros won't expand properly in an edef.
    % see https://tex.stackexchange.com/questions/21514/why-isnt-a-command-defined-by-newcommand-with-an-optional-argument-expandable
    \edef\assertA{#2}\edef\assertB{#3}%
    \def\name{\if\relax\detokenize{#1}\relax\detokenize{#2} = \detokenize{#3}\else #1\fi}%
    \def\desc{\space Test:\,\stepcounter{tst}\thetst~(\name)\par}%
    \comparestrict%
    \IfEq{\assertA}{\assertB}{%
      \textcolor{green}{Passed} \desc%
    }{%
      \ifcsname EnforceAssertions\endcsname%
      \errmessage{Assertion \thetst (#1) failed. (#2) $\ne$ (#3)}%
      \else%
      \fi%
      \textcolor{red}{Failed} \desc%
      \par~~~~~~~~(\assertA)(\detokenize{#2}) $\ne$ \par~~~~~~~~(\assertB)(\detokenize{#3})\par%
      First difference at position %
      \comparestrict\StrCompare{\assertA}{\assertB}.\par%
    }%
}}

\begin{document}

\def\hello#1{hello #1}

\assert{hello world}{\hello{world}}{hello world}

\assert{failing hello world}{\hello{world}}{hello cruel world}

\end{document}

在此处输入图片描述

如果使用定义的宏调用它\EnforceAssertions,则断言错误将向日志文件打印错误消息。从命令行,我可以使用如下 bash 脚本进行测试:

#!/bin/bash
function dotest {
    echo testing $1
    pdflatex -halt-on-error "\def\EnforceAssertions{defined} \input{$1}" &> /dev/null && echo Test $1 passed || echo Test $1 FAILED.
}
export -f dotest
echo test.tex | parallel --timeout 1000% dotest 

它的名字如下:

bash-4.4$ ./temptestall.sh
testing test.tex
Test test.tex FAILED.

这可能不是使用网络进行测试的最佳方式,但我将此答案放在这里,以便其他可能正在寻找测试框架来帮助编程 TeX/LaTeX 的人使用。

相关内容