【问题标题】:How can I test functions inside a single file Lua script?如何在单个文件 Lua 脚本中测试函数?
【发布时间】:2017-09-25 01:36:59
【问题描述】:

我想对单个文件 Lua 脚本中的函数进行单元测试,例如 script.lua。该脚本如下所示:

-- some fields from gvsp dissector which shall be post processed in custom dissector
gvsp_field0_f = Field.new("gvsp.<field0-name>")
gvsp_field1_f = Field.new("gvsp.<field1-name>")

-- custom protocol declaration
custom_protocol = Proto("custom","Custom Postdissector")

-- custom protocol field declarations
field0_f = ProtoField.string("custom.<field0-name>","Custom Field 0")
field1_f = ProtoField.string("custom.<field1-name>","Custom Field 1")

-- register custom protocol as postdissector
register_postdissector(custom_protocol)

function custom_protocol.dissector(buffer,pinfo,tree)
    -- local field values of "pre" dissector which are analyzed
    local gvsp_field0_value = gvsp_field0_f()
    local gvsp_field1_value = gvsp_field1_f()

    -- functions which shell be unit tested
    function0(...)
    function1(...)
end

function0(...)
    -- implementation
end

function1(...)
    -- implementation
end

假设我不想将脚本文件中的函数分离到单独的模块文件中(这可能会使事情变得更容易)。如何为script.lua 中定义的函数在script.lua 文件或单独的test_script.lua 文件中定义测试(最好使用luaunit,因为易于集成,但其他工具也可以)?

【问题讨论】:

  • 很大程度上取决于如何定义事物。你使用local(这让事情变得更加困难)还是使用“本地_ENVironments”(更容易)?您的代码结构如何?请添加一个关于如何定义函数等的小代码示例(不一定是实际代码,只是与您定义内容的方式相匹配的虚拟函数。)目前,没有足够的信息来提供有意义的信息答案。
  • 脚本锁定很像来自wiki.wireshark.org/Lua/Dissectors#postdissectors 的post dissector,在文件末尾定义了local 函数,这些函数在协议dissector 函数中使用。但是我不坚持这种结构。

标签: unit-testing testing lua


【解决方案1】:

要启用单独的脚本和单元测试执行,至少需要 3 个文件(在此示例中为 4,因为由单个文件组成的单元测试框架 luaunit 已集成到项目目录中)。对于此示例,所有文件都位于同一目录中。脚本script.lua 可能不会在其中定义任何函数,但必须从其模块module.lua 导入它需要的所有函数。

-- script imports module functions
module = require('module')

-- ... and uses it to print the result of the addition function
result = module.addtwo(1,1)
print(result)

module.lua是根据Lua module skeleton实现的,其功能自动注册,通过其他脚本文件或模块导入。

-- capture the name searched for by require
local NAME=...

-- table for our functions
local M = { }

-- A typical local function that is also published in the
-- module table.
local function addtwo(a,b) return a+b end
M.addtwo = addtwo

-- Shorthand form is less typing and doesn't use a local variable
function M.subtwo(x) return x-2 end

return M

test_module.lua 包含模块功能的单元测试并导入 luaunit.lua(单元测试框架)以执行其。 test_module.lua有以下内容。

luaunit = require('luaunit')
script = require('module')

function testAddPositive()
    luaunit.assertEquals(module.addtwo(1,1),2)
end

os.exit( luaunit.LuaUnit.run() )

如果您通过执行 lua test_module.lua 来运行测试,则测试将与脚本功能分开执行。

.
Ran 1 tests in 0.000 seconds, 1 success, 0 failures
OK

脚本像往常一样使用lua script.lua 执行,输出为2

【讨论】:

  • 我对 Lua 完全陌生,这种方法 os.exit( luaunit.LuaUnit.run() ) 正是我所需要的。当我关注来自 lua-users 的 UnitTesting guide 时,我一直面临“尝试索引一个 nil 值(全局'LuaUnit')”。
【解决方案2】:

简单的答案:你不能!

几年前我自己就这个问题询问了 Lua 团队,因为没有明显的方法可以让脚本知道它是正在运行还是包含在主脚本中(例如,'require'd)。

在可预见的未来似乎也没有兴趣添加这种功能!

【讨论】:

  • 好的。那么在单独的test_script.lua 中实现测试呢?
  • 我不确定我是否理解。那个怎么样?只需“要求”文件从您的测试文件中进行测试,并根据需要调用其公共函数。
  • 在下面的示例中,除了单元测试之外,还执行了脚本的主要功能。我不希望在单元测试执行期间执行脚本的主要功能。
  • 你需要相应地组织你的脚本,例如,把你的脚本变成一些模块。里面没有任何内联代码,只有函数/表定义。例如,local M={} ... function M.Init() ... return M,然后是主文件中的 my_module = require module,然后是 my_module.Init() 或类似的内容。
  • 以下示例的返工对我有用。我猜它类似于你的建议......
猜你喜欢
  • 2021-06-05
  • 1970-01-01
  • 2021-07-25
  • 1970-01-01
  • 2012-10-23
  • 1970-01-01
  • 2012-02-06
  • 2011-01-29
  • 2018-05-17
相关资源
最近更新 更多