【问题标题】:How do I write busted unit tests for functions that return ok,err?如何为返回 ok,err 的函数编写破坏的单元测试?
【发布时间】:2017-09-21 18:52:24
【问题描述】:

我有一个 Lua 函数,它返回 false 后跟错误消息,并希望使用 busted 测试框架测试其行为。现在我正在这样做:

function safe_divide(a, b)
    if b > 0 then -- buggy! should be b ~= 0 
        return a / b
    else
        return false, "division by zero"
    end
end

describe("safe_divide", function()
    it("can divide by positive numbers", function()
        local ok, err = safe_divide(10.0, 5.0)
        assert.truthy(ok)
        assert.are.same(2.0, ok)
    end)

    it("errors when dividing by zero", function()
        local ok, err = safe_divide(10.0, 0.0)
        assert.not_truthy(ok)
        assert.are.same("division by zero", err)
    end)

    it("can divide by negative numbers", function()
        local ok, err = safe_divide(-10.0, -5.0)
        assert.truthy(ok)
        assert.are.same(2.0, ok)
    end)
end)

我不喜欢我目前的方法有两点:

  • 每个测试是 3 行而不是一个干净的行
  • 当第三次测试失败时,busted 只是说false 不是预期的真实值,并且从未提及“除以零”错误消息。

有没有办法改进我的测试文件以避免这些问题?

我认为我想做的有点类似于 busted 中的 has_error 断言,但这似乎只适用于实际引发异常的函数,而不适用于返回 false 后跟错误消息的函数。

【问题讨论】:

  • [我很着急,可以稍后发布答案。] 使用assert?它将“无声的错误”变成了“大声的错误”。 (失败的常见模式是return nil, errmsg,但return false, errmsg 也可以。)
  • 这对我不起作用,因为assert 将行号信息添加到错误消息中。 Busted 然后说 "divide_spec.lua:17: division by zero" 与预期的 "division by zero" 不匹配
  • 您可以编写自己的assert 变体,例如:local function myassert (ok, err) if ok then return ok else error (err) end end
  • @AlbanLinard 这与直接使用断言没有什么不同。 error 函数还添加了行号信息。

标签: lua lua-busted


【解决方案1】:

Busted 使用luassert,可以使用您自己的断言进行扩展。

例如,下面的代码使用了一个用户定义的断言answers,它将预期结果表作为第一个参数,并将有效函数结果作为其余参数。

local assert = require "luassert"

local function safe_divide(a, b)
    if b > 0 then -- buggy! should be b ~= 0
        return a / b
    else
        return false, "division by zero"
    end
end

local function answers(state, arguments)
  local expected = arguments[1]
  assert(type(expected) == "table")
  for i = 2, #arguments do
      if arguments[i] ~= expected[i-1] then
          state.failure_message = "unexpected result " .. tostring (i-1) .. ": " .. tostring (arguments [i])
          return false
      end
  end
  return true
end
assert:register("assertion", "answers", answers)

describe("safe_divide", function()
    it("can divide by positive numbers", function()
        assert.answers({ 2.0 }, safe_divide(10.0, 5.0))
    end)

    it("errors when dividing by zero", function()
        assert.answers({ false, "division by zero" }, safe_divide(10.0, 0.0))
    end)

    it("can divide by negative numbers", function()
        assert.answers({ 2.0 }, safe_divide(-10.0, -5.0))
    end)
end)

此代码缺少断言消息的正确格式。您可以查看luaassert 文档或predefined assertions。它包含一个用于翻译消息的say 模块。

【讨论】:

  • 小记。如果需要检查 nil 和错误消息,此代码不起作用。也可以在 say 模块中注册自定义消息。
猜你喜欢
  • 1970-01-01
  • 2015-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 2019-05-08
  • 1970-01-01
  • 2016-01-27
相关资源
最近更新 更多