单元测试、assert_function_called() 和代码灵活性



这是一个关于单元测试的问题,以及是否/在哪里绘制要测试的内容的界限

假设有一个这样的函数:

def function():
do_work()

您必须针对您处理的问题进行修改,如下所示:

def function():
do_work()
do_additional_work()

是否应该(A)function()添加如下所示的单元测试:

def test_function_called_additional_work():
mocked_additional_work = mock(function.do_additional_work)
function()
assert mocked_additional_work.called_once

或者你(B)编写一个依赖于function()的集成测试,如下所示:

def test_additional_work_was_done_upon_function_call():
assert some_client.state == add_work_was_not_done
function()
assert some_client.state == add_work_was_done

或者你应该同时写两个


我的第一个镜头是不做A而更喜欢B,因为它

  • 强制实施如何完成额外工作的特定实现,因此它不会中断未来的重构,例如提高速度但具有不同的调用签名。相反,只有当do_additional_work()应该修改/提供的状态错误时,它才会中断。

  • 如果你做A,你在哪里画线?难道你不需要嘲笑断言do_work()曾经被叫过吗?


但是,如果function()有自己的逻辑,则可以进行参数化,例如:

def function(conditional):
do_work() if(conditional) else do_different_work()

那么我会看到编写模拟断言两个不同分支的单元测试的理由。


你会写哪些测试?(A)、(B)还是两者兼而有之

一般来说,倾向于松散耦合你的测试,因为这会使它们不那么脆弱。一个例外情况是,调用do_work是重要的行为,而不仅仅是调用它导致的状态更改。在将被子类覆盖的方法中可能就是这种情况。

也就是说,测试是为了让你的工作更轻松(特别是在维护方面),有时仅仅为了满足上述要求而重构代码是不切实际的(例如,当你在修改之前向遗留代码添加测试以记录行为时)。在这种情况下,请在测试中的注释中解释您的推理并继续。

最新更新