如何记录单元测试?

2024-05-23 16:33:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在努力提高Python项目中测试的数量和质量。随着测试数量的增加,我遇到的一个困难是知道每个测试做什么,以及它应该如何帮助发现问题。我知道跟踪测试的一部分是更好的单元测试名称(已经过处理了elsewhere),但是我也对理解文档和单元测试是如何结合在一起感兴趣。

当单元测试在将来失败时,如何记录单元测试以提高它们的实用性?具体来说,是什么造就了一个好的单元测试docstring?

我很欣赏描述性的答案和优秀文档的单元测试示例。虽然我只使用Python,但我对其他语言的实践持开放态度。


Tags: 项目答案文档名称语言示例数量记录
3条回答

测试方法的名称应该准确描述您正在测试的内容。文档应该说明是什么导致测试失败。

我用方法名专门记录了大多数单元测试:

testInitializeSetsUpChessBoardCorrectly()
testSuccessfulPromotionAddsCorrectPiece()

对于几乎100%的测试用例,这清楚地解释了单元测试正在验证什么,这就是我所使用的全部。然而,在一些更复杂的测试用例中,我将在整个方法中添加一些注释来解释几行代码在做什么。

我以前见过一个工具(我相信是为Ruby开发的),它可以通过解析项目中所有测试用例的名称来生成文档文件,但我记不起这个名称。如果你有象棋皇后级的测试用例:

testCanMoveStraightUpWhenNotBlocked()
testCanMoveStraightLeftWhenNotBlocked()

该工具将生成包含以下内容的HTML文档:

Queen requirements:
 - can move straight up when not blocked.
 - can move straight left when not blocked.

也许问题不在于如何最好地编写测试docstring,而在于如何编写测试本身?重构测试的方式可以使它们具有自文档性,这会有很长的路要走,并且当代码更改时,docstring不会过时。

为了使测试更加清晰,您可以做一些事情:

  • 清晰的描述性测试方法名称(已提及)
  • 测试机构应清晰简洁(自我记录)
  • 在方法上抽象出复杂的设置/拆卸等
  • 更多?

例如,如果您有这样的测试:

def test_widget_run_returns_0():
    widget = Widget(param1, param2, "another param")
    widget.set_option(true)
    widget.set_temp_dir("/tmp/widget_tmp")
    widget.destination_ip = "10.10.10.99"

    return_value = widget.run()

    assert return_value == 0
    assert widget.response == "My expected response"
    assert widget.errors == None

您可以用方法调用替换setup语句:

def test_widget_run_returns_0():
    widget = create_basic_widget()
    return_value = widget.run()
    assert return_value == 0
    assert_basic_widget(widget)

def create_basic_widget():
    widget = Widget(param1, param2, "another param")
    widget.set_option(true)
    widget.set_temp_dir("/tmp/widget_tmp")
    widget.destination_ip = "10.10.10.99"
    return widget

def assert_basic_widget():
    assert widget.response == "My expected response"
    assert widget.errors == None

请注意,您的测试方法现在由一系列方法调用组成,这些方法调用具有意向性的名称,这是一种特定于您的测试的DSL。这样的测试还需要文档吗?

另一件需要注意的事情是,您的测试方法主要是在一个抽象级别上。阅读测试方法的人会发现算法是:

  • 创建小部件
  • 在小部件上调用run
  • 断言代码做了我们期望的事情

他们对测试方法的理解并没有被设置小部件的细节所迷惑,小部件是比测试方法低一级的抽象。

测试方法的第一个版本遵循Inline Setup模式。第二个版本遵循Creation MethodDelegated Setup模式。

一般来说,我反对注释,除非它们解释了代码的“原因”。读了鲍勃·马丁叔叔的书,我相信了这一点。有一章是关于评论的,还有一章是关于测试的。我推荐。

有关自动测试最佳实践的更多信息,请查看xUnit Patterns

相关问题 更多 >