如何为单元测试类和测试方法命名最佳实践是什么?
这个问题曾在SO上讨论过,在Unit Tests的一些流行命名约定是什么?
我不知道这是否是一个非常好的方法,但目前在我的测试项目中,我将每个生产类与一个测试类进行一对一映射,例如Product
和ProductTest
。
在我的测试类中,我使用正在测试的方法的名称、下划线以及情况和我期望发生的情况来命名方法,例如Save_ShouldThrowExceptionWithNullName()
。
如何为单元测试类和测试方法命名最佳实践是什么?
这个问题曾在SO上讨论过,在Unit Tests的一些流行命名约定是什么?
我不知道这是否是一个非常好的方法,但目前在我的测试项目中,我将每个生产类与一个测试类进行一对一映射,例如Product
和ProductTest
。
在我的测试类中,我使用正在测试的方法的名称、下划线以及情况和我期望发生的情况来命名方法,例如Save_ShouldThrowExceptionWithNullName()
。
更新(2021年7月)
距离我最初的回答已经有一段时间了(接近12年),在此期间,最佳实践已经发生了很大变化。因此,我觉得有必要更新我的答案,并向读者提供不同的命名策略。
许多评论和答案指出,我在原始答案中提出的命名策略不耐重构,并且最终会导致难以理解的名称,我完全同意。
在过去几年中,我采用了更人性化的命名模式,其中测试名称描述了我们想要测试的内容,正如 Vladimir Khorikov 所描述的那样。
以下是一些示例:
Add_credit_updates_customer_balance
Purchase_without_funds_is_not_possible
Add_affiliate_discount
但是,正如您所看到的,这是一个相当灵活的模式,最重要的是,在阅读名称时,您知道测试是关于什么的,而不包括可能随时间变化的技术细节。
对于项目和测试类的命名,我仍然遵循原始答案的模式。
原始答案(2009年10月)
我喜欢Roy Osherove的命名策略。它是这样的:
[UnitOfWork_StateUnderTest_ExpectedBehavior]
它在方法名称中提供了所有必要的信息,并且以结构化的方式呈现。
工作单元可以是一个方法,一个类甚至多个类。它应该代表在此测试用例中要测试和可控制的所有内容。
对于程序集,我使用典型的.Tests
结尾,我认为这相当普遍,并且对于类(以Tests
结尾)也是如此:
[NameOfTheClassUnderTestTests]
以前,我使用Fixture作为后缀而不是Tests,但我认为后者更常见,因此我改变了命名策略。
UpdateManager.Update()
。考虑到这一点,我倾向于将我的测试命名为 WhenUpdating_State_Behaviour
或 WhenUpdating_Behaviour_State
。这样,我可以在测试类的特定操作,同时避免在测试名称中放置方法名称。但最重要的是,当我看到一个失败测试的名称时,我必须知道哪个业务逻辑出了问题。 - Ramunas我喜欢遵循"应该"的命名标准来为测试命名,同时在为单元测试(即类)命名测试夹具时,以受测单元为基础。
举个例子(使用C#和NUnit):
[TestFixture]
public class BankAccountTests
{
[Test]
public void Should_Increase_Balance_When_Deposit_Is_Made()
{
var bankAccount = new BankAccount();
bankAccount.Deposit(100);
Assert.That(bankAccount.Balance, Is.EqualTo(100));
}
}
为什么要使用"Should"?
我发现它迫使测试编写者用类似于“应该[在某种状态之后/之前/当] [执行某个操作时]”的句子来命名测试。
是的,到处写"Should"的确有点重复,但正如我所说的,它迫使作者以正确的方式思考(因此对新手可能有好处)。此外,它通常会产生可读性强的英语测试名称。
更新:
我注意到Jimmy Bogard也喜欢使用'should',甚至还有一个名为Should的单元测试库。
更新(四年后...)
对于那些感兴趣的人,我的测试命名方法随着时间的推移而发展。上述的Should模式存在一个问题,就是很难一眼看出正在测试哪个方法。对于OOP,我认为以被测试的方法开头更有意义。对于设计良好的类,这应该会产生可读性强的测试方法名称。我现在使用类似于<method>_Should<expected>_When<condition>
的格式。显然,根据上下文,您可能需要将Should/When动词替换为更合适的内容。例如:Deposit_ShouldIncreaseBalance_WhenGivenPositiveValue()
当存款被进行时增加余额。
- hotshot309我喜欢这种命名风格:
OrdersShouldBeCreated();
OrdersWithNoProductsShouldFail();
等等。
它确实能让非测试人员清楚地了解问题所在。
should
,我更愿意使用 will
,所以会写成 OrdersWithNoProductsWillFail()
。 - Calin肯特·贝克建议:
每个“单元”(你的程序类)一个测试夹具。测试夹具本身也是类。测试夹具名称应为:
[name of your 'unit']Tests
测试用例(测试夹具方法)的名称如下:test[feature being tested]
例如,有以下类:
class Person {
int calculateAge() { ... }
// other methods and properties
}
一个测试夹具将是:
class PersonTests {
testAgeCalculationWithNoBirthDate() { ... }
// or
testCalculateAge() { ... }
}
类名。对于测试夹具名称,我发现在许多领域的通用语言中,“Test”是很常见的。例如,在工程领域:StressTest
,在化妆品领域:SkinTest
。抱歉不同意肯特的看法,但在我的测试夹具中使用“Test”(StressTestTest
?)会让人困惑。
在许多领域中也经常使用“Unit”。例如:MeasurementUnit
。一个名为MeasurementUnitTest
的类是对“Measurement”还是“MeasurementUnit”的测试呢?
因此,我喜欢在所有的测试类中使用“Qa”前缀。例如:QaSkinTest
和QaMeasurementUnit
。它永远不会与领域对象混淆,而且使用前缀而不是后缀意味着所有测试夹具在视觉上都在一起(如果你在测试项目中有伪造或其他支持类,这非常有用)。
命名空间。我在C#中工作,并将我的测试类放在与它们测试的类相同的命名空间中。这比拥有单独的测试命名空间更方便。当然,测试类位于不同的项目中。
测试方法名称。我喜欢将我的方法命名为WhenXXX_ExpectYYY。这使得前置条件明确,并有助于自动化文档(例如TestDox)。这类似于Google测试博客上的建议,但具有更多的前置条件和期望值分离。例如:
WhenDivisorIsNonZero_ExpectDivisionResult
WhenDivisorIsZero_ExpectError
WhenInventoryIsBelowOrderQty_ExpectBackOrder
WhenInventoryIsAboveOrderQty_ExpectReducedInventory
我使用Given-When-Then概念。 请看这篇简短的文章:http://cakebaker.42dh.com/2009/05/28/given-when-then/。该文章从BDD的角度描述了这个概念,但是你也可以在TDD中使用它而不需要做任何更改。
给定已登录_当写文章_然后显示成功消息
- wonsucMyApp.Serialization
命名空间下的 Settings
类。MyApp.Serialization.Tests
的测试项目。IfSettings
的类(保存为 IfSettings.cs )。SaveStrings()
方法。-> 我会将测试命名为 CanSaveStrings()
。MyApp.Serialization.Tests.IfSettings.CanSaveStrings
我认为这很好地告诉我,它正在测试什么。DetectsInvalidUserInput
)ThrowsOnNotFound
)WillCloseTheDatabaseAfterTheTransaction
)[Test] public void detects_invalid_User_Input()
我发现这样更容易阅读。
[结束编辑]
我希望这能激发出更多想法,因为我认为给测试命名非常重要,它可以节省你大量的时间,否则这些时间将会花费在试图理解测试正在做什么上(例如在长期停顿后恢复项目)。
我认为最重要的一点是在命名约定上保持一致(并与团队中的其他成员达成一致)。太多时候,我看到同一个项目中使用了许多不同的约定。
我应该补充一下,将测试代码放在与被测试的源代码相同的包中,但是在平行目录中,可以消除代码膨胀问题,当你准备部署代码时,无需进行大量排除模式操作。
我个人喜欢《JUnit Pocket Guide》中描述的最佳实践...很难超越JUnit的联合创始人所写的书!
test<MethodUnderTest>_<state>
зљ„е‘ҢеђҚж–№еәЏпәЊдң‹е¦‚testPop_emptyStack
гЂ‚е…·дҢ“иҮ¦жѓ…иҮ·и§Ѓhttps://google-styleguide.googlecode.com/svn/trunk/javaguide.htmlдёзљ„5.2.3节“方法еђҚвЂқ。如жһњжњ‰з–‘й—®пәЊиҮ·йЃµеңҒGoogleзљ„е»ғи®®гЂ‚ - Ciro Santilli OurBigBook.com