我想为 ConTeXt 使用的 Lua 代码编写一些单元测试,并且想知道是否有其他人做过这件事,以及设置框架时可能需要做什么。
Lua 代码特别存储在单独的文件中(例如numbering.lua
),这意味着测试运行器(例如破获) 可以直接用 来包含它们require
。
值得注意的是(但可能并不重要),我使用 Python 的 unittest 作为测试运行器疯子蟒。
固有的问题是 LuaTeX 和 ConTeXt 定义的全局变量在 Lua 中并不自然。如果没有从其相应文件导入这些表,则无法访问诸如context
和之类的表。(这看起来像是和...texio
require
tex/texmf-context/tex/context/base/trac-log.lua
谁知道, 分别)。
有人做过 ConTeXt + Lua 的单元测试吗?需要包含哪些 Lua 文件才能获取变量?我希望在某个地方有一个入口点,可以处理大部分设置。
看起来.lua
相关文件通常会在里面,./tex/texmf-context/tex/context/base/
但我只是猜测,而且由于大约有 840 个.lua
文件,我将非常感激任何关于从哪里开始的指导。
答案1
根据@Aditya 和@phg 的精彩评论,我做了以下事情:
我使用非常酷的lunatest框架. 设置起来很简单,因为只需要设置require('lunatest')
,并且有一组有用的示例test.lua
。
一旦我创建了自己的,my_tests.lua
我就会运行它:
context my_tests.lua --purgeall --batchmode --once
然后,我的 python 测试运行器检查上下文进程的返回代码(如果失败则为非零)。
context
经过一段时间的试验,我发现捕获和和其他函数的输出很有挑战性texio
。为了解决这个问题,我不再让 ConTeXt 启动 lua,而是使用带有存根的 vanilla lua,如下所示:
local function stub(name)
local stubbed = {}
local calls = {}
local metatable = {
__call = function(meta, ...)
local call = {}
call.method = nil
call.args = arg
table.insert(calls, call)
end,
__index = function(meta, ...)
local method = arg[1]
return function(...)
local call = {}
call.method = method
call.args = arg
table.insert(calls, call)
end
end
}
stubbed._calls = calls
setmetatable(stubbed, metatable)
_G[name] = stubbed
end
function M.setup()
stub('context')
stub('texio')
end
M.setup
运行器在每次测试之前调用Where lunatest
。结果是,我现在可以测试 Lua 的调用,如下所示texio
(context
涉及更多设置,但不会太多):
lt = require('lunatest')
function suite.test_double_indent()
test_double_indent()
lt.assert_len(5, context._calls)
lt.assert_equal('\\startitemize\\sym{}\\startitemize\\sym{}',
context._calls[1].args[1])
lt.assert_equal('\n\\stopitemize\n\\stopitemize\n\\stopitemize',
context._calls[5].args[1])
end
最后,因为这个设置没有什么特殊之处(即不需要变量),所以如果愿意的话,luatex
可以很容易地使用或其他解释器桥来调用。python-lunatic