unittests,assert_function_called()和代码灵活性

时间:2017-03-21 21:24:52

标签: python unit-testing mocking integration-testing

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

假设有这样的函数:

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)或两者

1 个答案:

答案 0 :(得分:1)

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

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