gpt4 book ai didi

erlang - 常见测试中如何测试错误处理?

转载 作者:行者123 更新时间:2023-12-02 09:20:51 26 4
gpt4 key购买 nike

我开始使用 common test 作为我在 erlang 中的测试框架。

假设我有一个函数,我希望只接受正数,并且在任何其他情况下它都会失败。

positive_number(X) when > 0 -> {positive, X}.

我想测试一下

positive_number(-5).

将无法成功完成。

如何测试此行为?在其他语言中,我会说测试用例需要一些错误或异常,并且如果它在测试下运行不会因无效的无效参数而引发任何错误,则测试用例会失败。如何通过普通测试来做到这一点?

更新:

我可以让它工作

test_credit_invalid_input(_) ->
InvalidArgument = -1,
try mypackage:positive_number(InvalidArgument) of
_ -> ct:fail(not_failing_as_expected)
catch
error:function_clause -> ok
end.

但我认为这太冗长了,我想要这样的东西:

assert_error(mypackage:positive_number, [-1], error:function_clause)

我假设常见测试在某些地方存在这种情况,并且我对框架缺乏适当的了解,这使得我采取了如此冗长的解决方案。

更新:受到迈克尔的回应的启发,我创建了以下函数:

assert_fail(Fun, Args, ExceptionType, ExceptionValue, Reason) ->
try apply(Fun, Args) of
_ -> ct:fail(Reason)
catch
ExceptionType:ExceptionValue -> ok
end.

我的测试变成了:

test_credit_invalid_input(_) ->
InvalidArgument = -1,
assert_fail(fun mypackage:positive_number/1,
[InvalidArgument],
error,
function_clause,
failed_to_catch_invalid_argument).

但我认为它确实有效,因为在每个测试用例中使用 assert_fail 调用比使用 try....catch 更具可读性。

我仍然认为 Common Test 中应该存在一些更好的实现,在我看来,在每个项目中重复实现此测试模式是一种丑陋的重复。

最佳答案

将异常转换为表达式并匹配它:

test_credit_invalid_input(_) ->
InvalidArgument = -1,
{'EXIT', {function_clause, _}}
= (catch mypackage:positive_number(InvalidArgument)).

这会将您的异常转变为非异常,反之亦然,这可能与您所期望的一样简洁。

您也可以随时使用宏或函数来隐藏冗长的内容。

编辑(回复:评论):

如果您使用完整的 try catch 构造(如您的问题所示),您将丢失有关任何失败情况的信息,因为该信息被丢弃以支持原子“not_failing_as_expected”或“failed_to_catch_invalid_argument”。

在 shell 上尝试预期的失败值:

1> {'EXIT', {function_clause, _}}
= (catch mypackage:positive_number(-4)).
{'EXIT',{function_clause,[{mypackage,positive_number,
[-4],
[{file,"mypackage.erl"},{line,7}]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,661}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,434}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,441}]},
{shell,exprs,7,[{file,"shell.erl"},{line,676}]},
{shell,eval_exprs,7,[{file,"shell.erl"},{line,631}]},
{shell,eval_loop,3,[{file,"shell.erl"},{line,616}]}]}}

在 shell 上实现预期成功值:

2> {'EXIT', {function_clause, _}} = (catch mypackage:positive_number(3)). 
** exception error: no match of right hand side value {positive,3}

在这两种情况下,您都会获得大量信息,但最重要的是,从这两种情况中,您可以知道使用哪些参数来调用被测试的函数(尽管在第二种情况下,这只是因为您的函数是确定的,并且一个一)。

在像这样的简单情况下,这些事情并不那么重要,但作为原则问题,它很重要,因为稍后在更复杂的情况下,可能导致函数失败的值不会像这里那样被硬编码,你可能不知道什么值导致你的函数失败,或者什么返回值。这可能是花一两分钟查看丑陋的回溯并准确了解问题所在,或者花 15 分钟设置测试以真正找出发生了什么的区别……或者,更糟糕的是,如果它是heisenbug您可能会花几个小时寻找它!

关于erlang - 常见测试中如何测试错误处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33722462/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com