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

这在之前的SO中讨论过,在什么是单元测试的一些流行命名约定?

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

在我的测试类中,我有我正在测试的方法的名称,一个下划线,然后是情况和我期望发生的事情,例如Save_ShouldThrowExceptionWithNullName()。


当前回答

我应该补充一点,将您的测试放在同一个包中,但位于与被测试的源代码并行的目录中,一旦您准备好部署它,就可以消除代码的膨胀,而不必执行一堆排除模式。

我个人喜欢“JUnit Pocket Guide”中描述的最佳实践……很难有一本书比JUnit!

其他回答

类名。对于测试fixture名称,我发现“test”在许多领域的通用语言中非常常见。例如,在工程领域:应力测试,在化妆品领域:SkinTest。很抱歉不同意Kent的观点,但是在我的测试装置中使用“Test”(stress stesttest ?)是令人困惑的。

“单位”在域中也经常使用。例如MeasurementUnit。一个名为MeasurementUnitTest的类是“Measurement”或“MeasurementUnit”的测试吗?

因此,我喜欢对所有测试类使用“Qa”前缀。例如QaSkinTest和qammeasurementunit。它永远不会与域对象混淆,并且使用前缀而不是后缀意味着所有测试fixture在视觉上一起存在(如果您的测试项目中有假类或其他支持类,则非常有用)

名称空间。我使用c#工作,并且我将我的测试类保持在与它们所测试的类相同的命名空间中。这比使用单独的测试名称空间更方便。当然,测试类在不同的项目中。

测试方法名称。我喜欢命名我的方法WhenXXX_ExpectYYY。它使前提条件变得清晰,并有助于自动化文档(一种TestDox)。这类似于谷歌测试博客上的建议,但更多地分离了前提条件和期望。例如:

WhenDivisorIsNonZero_ExpectDivisionResult
WhenDivisorIsZero_ExpectError
WhenInventoryIsBelowOrderQty_ExpectBackOrder
WhenInventoryIsAboveOrderQty_ExpectReducedInventory

在VS + NUnit中,我通常在项目中创建文件夹,将功能测试分组在一起。然后我创建单元测试fixture类,并以我正在测试的功能类型命名它们。[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

我最近提出了以下约定来命名我的测试,它们的类和包含项目,以最大化它们的描述符:

假设我在MyApp的一个项目中测试设置类。序列化的名称空间。

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

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

假设我正在测试SaveStrings()方法。我将测试命名为CanSaveStrings()。

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

MyApp.Serialization.Tests.IfSettings.CanSaveStrings

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

当然,在英语中名词“Tests”和动词“Tests”是一样的,这是很有用的。

在命名测试时,你的创造力是没有限制的,这样我们就可以得到完整的句子标题。

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

例子包括:

检测(例如DetectsInvalidUserInput) 抛出(例如ThrowsOnNotFound) Will(例如WillCloseTheDatabaseAfterTheTransaction)

etc.

另一个选择是用“that”而不是“if”。

后者虽然节省了我的击键,但更准确地描述了我正在做的事情,因为我不知道,测试的行为是否存在,但我正在测试它是否存在。

(编辑)

在使用上述命名约定一段时间后,我发现,在处理接口时,If前缀可能令人困惑。恰好,测试类IfSerializer.cs看起来与“打开文件选项卡”中的isserializer .cs接口非常相似。 当在测试、被测试的类和它的接口之间来回切换时,这会非常烦人。因此,我现在将选择That而不是If作为前缀。

此外,我现在只对我的测试类中的方法使用“_”来分隔我的测试方法名称中的单词,因为它在其他任何地方都不是最佳实践:

[Test] public void detects_invalid_User_Input()

我觉得这个更容易读。

(结束编辑)

我希望这能产生更多的想法,因为我认为命名测试非常重要,因为它可以为您节省大量时间,否则您将花费大量时间试图理解测试正在做什么(例如,在长时间中断后恢复项目)。

我喜欢这样的命名风格:

OrdersShouldBeCreated();
OrdersWithNoProductsShouldFail();

等等。 它让非测试人员清楚地知道问题所在。

Kent Beck建议:

每个“单元”(程序的类)一个测试夹具。测试fixture本身就是类。测试夹具的名称应该是: [您的“单元”名称]测试 测试用例(测试夹具方法)的名称如下: 测试[正在测试的功能]

例如,拥有以下类:

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

    // other methods and properties
}

测试夹具应该是:

class PersonTests {

    testAgeCalculationWithNoBirthDate() { ... }

    // or

    testCalculateAge() { ... }
}