单元测试命名最佳实践

时间:2020-03-06 14:57:09  来源:igfitidea点击:

命名单元测试类和测试方法的最佳实践是什么?

之前在SO上对此进行了讨论,在单元测试中有哪些流行的命名约定?

我不知道这是否是一个很好的方法,但是目前在我的测试项目中,我在每个生产类和一个测试类之间都有一对一的映射,例如"产品"和"产品测试"。

然后在我的测试课程中,我有一些方法,其中包含我正在测试的方法的名称,下划线,然后是情况和我希望发生的事情,例如Save_ShouldThrowExceptionWithNullName()。

解决方案

看:
http://googletesting.blogspot.com/2007/02/tott-naming-unit-tests-responsfully.html

对于测试方法名称,我个人觉得使用冗长和自记录的名称非常有用(以及Javadoc注释,这些注释进一步解释了测试的功能)。

肯特·贝克(Kent Beck)建议:

  • 每个"单元"(程序类别)一个测试夹具。测试装置本身就是类。测试夹具名称应为:
[name of your 'unit']Tests
  • 测试用例(测试夹具方法)的名称如下:
test[feature being tested]

例如,具有以下类别:

class Person {
    int calculateAge() { ... }

    // other methods and properties
}

测试夹具为:

class PersonTests {

    testAgeCalculationWithNoBirthDate() { ... }

    // or

    testCalculateAge() { ... }
}

我喜欢这种命名方式:

OrdersShouldBeCreated();
OrdersWithNoProductsShouldFail();

等等。
对于非测试人员来说,这确实可以弄清楚问题出在哪里。

在VS + NUnit中,我通常在项目中创建文件夹以将功能测试分组在一起。然后,我创建单元测试夹具类,并以要测试的功能类型命名。 [Test]方法的名称与Can_add_user_to_domain相似:

- MyUnitTestProject   
  + FTPServerTests <- Folder
   + UserManagerTests <- Test Fixture Class
     - Can_add_user_to_domain  <- Test methods
     - Can_delete_user_from_domain
     - Can_reset_password

我应该补充说,一旦准备好部署测试,而不必执行大量排除模式,则将测试保留在相同的程序包中,并保留在与要测试的源程序平行的目录中,可以消除代码的膨胀。

我个人喜欢《 JUnit Pocket Guide》中描述的最佳实践……很难击败JUnit的合著者写的书!

Foo类的测试用例的名称应该是FooTestCase或者类似的名称(FooIntegrationTestCase或者FooAcceptanceTestCase),因为它是测试用例。请参阅http://xunitpatterns.com/了解一些标准命名约定,例如测试,测试用例,测试夹具,测试方法等。

我最近想出了以下约定来命名测试,它们的类和包含项目,以便最大程度地描述它们:

可以说我正在MyApp.Serialization命名空间的项目中测试Settings类。

首先,我将使用MyApp.Serialization.Tests命名空间创建一个测试项目。

在这个项目中,当然在命名空间中,我将创建一个名为IfSettings的类(另存为IfSettings.cs)。

可以说我正在测试SaveStrings()方法。 ->我将命名测试CanSaveStrings()。

当我运行此测试时,它将显示以下标题:

MyApp.Serialization.Tests.IfSettings.CanSaveStrings

我认为这很好地告诉了我,它正在测试什么。

当然,在英语中名词" Tests"与动词" tests"相同是有用的。

在命名测试时,创造力没有限制,因此我们可以为它们提供完整的句子标题。

通常,测试名称必须以动词开头。

示例包括:

  • 检测(例如DetectsInvalidUserInput)
  • 引发(例如ThrowsOnNotFound)
  • 遗嘱(例如WillCloseTheDatabaseAfterTheTransaction)

等等。

另一种选择是使用" that"代替" if"。

后者可以节省我的击键次数,并且可以更准确地描述我在做什么,因为我不知道所测试的行为是否存在,但我正在测试是否存在。

[编辑]

在使用上述命名约定一段时间之后,我发现在使用接口时,If前缀可能会造成混淆。碰巧的是,测试类IfSerializer.cs看起来与"打开文件"选项卡中的接口ISerializer.cs非常相似。

在测试,要测试的类及其接口之间来回切换时,这可能会非常烦人。结果,我现在选择If If作为前缀。

  • [测试]公共无效detects_invalid_User_Input()*

另外,我现在仅将其用于测试类中的方法,因为在其他任何地方," _"都不能用于分隔测试方法名称中的单词,因此不被视为最佳实践,如下所示:

我发现这更容易阅读。

[结束编辑]

我希望这能带来更多的想法,因为我认为命名测试非常重要,因为它可以为我们节省大量时间,否则这些时间会花在尝试理解测试的功能上(例如,在长时间的中断后恢复项目) 。

类名。对于测试装置名称,我发现"测试"在许多领域的通用语言中非常普遍。例如,在工程领域:" StressTest",在化妆品领域:" SkinTest"。抱歉,不同意Kent,但是在我的测试装置(" StressTestTest"?)中使用"测试"令人困惑。

"单元"在域中也经常使用。例如。 MeasurementUnit。名为" MeasurementUnitTest"的类是否是对" Measurement"或者" MeasurementUnit"的测试?

因此,我喜欢对所有测试类使用" Qa"前缀。例如。 QaSkinTest和QaMeasurementUnit。它永远不会与域对象混淆,并且使用前缀而不是后缀意味着所有测试夹具都可以在视觉上一起使用(如果我们在测试项目中有伪造品或者其他支持类,则很有用)

命名空间。我在Cand工作,我将测试类保留在与他们正在测试的类相同的名称空间中。这比拥有单独的测试名称空间更为方便。当然,测试类在另一个项目中。

WhenDivisorIsNonZero_ExpectDivisionResult
WhenDivisorIsZero_ExpectError
WhenInventoryIsBelowOrderQty_ExpectBackOrder
WhenInventoryIsAboveOrderQty_ExpectReducedInventory

测试方法名称。我喜欢将我的方法命名为WhenXXX_ExpectYYY。它使前提条件变得清晰,并有助于自动化文档(如TestDox)。这与Google测试博客上的建议类似,但前提条件和期望值之间存在更大的分离。例如:

我喜欢Roy Osherove的命名策略,如下所示:

[UnitOfWork__StateUnderTest__ExpectedBehavior]

它以结构化的方式提供了有关方法名称的所有信息。

工作单位可以小到单个方法,一个类,也可以大到多个类。它应该表示在此测试用例中要测试且受控制的所有事物。

对于程序集,我使用典型的.Tests结尾,我认为该结尾很普遍,并且对于类也是如此(以`Tests结尾):

[NameOfTheClassUnderTestTests]

以前我使用Fixture作为后缀而不是Tests,但是我认为后者更常见,然后我更改了命名策略。

段落数量不匹配