unit testing命名最佳实践
命名unit testing类和testing方法的最佳实践是什么?
这在前面讨论过,在unit testing的一些stream行的命名约定是什么?
我不知道这是否是一个非常好的方法,但是目前在我的testing项目中,我在每个生产类和一个testing类(例如Product
和ProductTest
之间都有一对一的映射关系。
然后在我的testing类中,我使用方法的名称,我正在testing的方法,一个下划线,然后情况和我期望发生,例如Save_ShouldThrowExceptionWithNullName()
。
我喜欢Roy Osherove的命名策略 ,如下所示:
[UnitOfWork__StateUnderTest__ExpectedBehavior]
它具有方法名称和结构化方式所需的全部信息。
工作单元可以像单一的方法一样小,也可以像多个类一样大。 它应该代表所有在这个testing案例中被testing的东西,并且在控制之下。
对于程序集,我使用典型的.Tests
结尾,我认为这是相当普遍的,对于类(以Tests
结束)是相同的:
[NameOfTheClassUnderTestTests]
以前我用夹具作为后缀而不是testing,但我认为后者更常见,然后我改变了命名策略。
我喜欢这种命名风格:
OrdersShouldBeCreated(); OrdersWithNoProductsShouldFail();
等等。 这对非testing者来说真的很清楚是什么问题。
我喜欢按照“应该”命名标准进行testing,同时在testing装置 (即课程)之后命名testing夹具 。
为了说明(使用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)); } }
为什么“应该” ?
我发现它迫使testing作者用“应该[处于某种状态] [之前/之前/之后] [动作发生]”的句子来命名testing。
是的,在任何地方写“应该”都会有点重复,但正如我所说的那样,它会迫使作家以正确的方式思考(对新手来说也是如此)。 另外它通常会产生一个可读的英文testing名称。
更新 :
我注意到Jimmy Bogard也是“应该”的粉丝,甚至还有一个叫做Should的unit testing库。
更新(4年后…)
对于那些有兴趣的人来说,我的命名testing方法已经发展了多年。 我在上面描述的应该模式中的一个问题是,一眼就不容易知道哪种方法正在testing中。 对于OOP,我认为用被测方法开始testing名称更有意义。 对于devise良好的类,这应该会导致可读的testing方法名称。 我现在使用类似于<method>_Should<expected>_When<condition>
的格式。 很显然,根据上下文,你可能想用“应当/当动词”来替代更适合的东西。 例如: Deposit_ShouldIncreaseBalance_WhenGivenPositiveValue()
Kent Beckbuild议:
-
每个“单元”(您的程序的类)一个testing夹具。 testing夹具本身就是类。 testing夹具名称应该是:
[name of your 'unit']Tests
-
testing用例(testing夹具方法)的名称如下所示:
test[feature being tested]
例如,具有以下类:
class Person { int calculateAge() { ... } // other methods and properties }
testing夹具将是:
class PersonTests { testAgeCalculationWithNoBirthDate() { ... } // or testCalculateAge() { ... } }
类名称 。 对于testing夹具名称,我发现“testing”在很多领域中无处不在的语言中是相当普遍的。 例如,在工程领域: StressTest
和化妆品领域: SkinTest
。 对不起,不赞同肯特,但在我的testing夹具( StressTestTest
?)使用“testing”是混乱。
“单位”在域中也用得很多。 如MeasurementUnit
。 MeasurementUnitTest
是“Measurement”还是“MeasurementUnit”?
所以我喜欢为我的所有testing类使用“Qa”前缀。 例如QaSkinTest
和QaMeasurementUnit
。 它永远不会与领域对象混淆,使用前缀而不是后缀意味着所有的testing夹具都可视化地共存(如果您的testing项目中有假货或其他支持类,
命名空间 。 我在C#中工作,并将testing类放在与testing类相同的名称空间中。 比单独的testing命名空间更方便。 当然,testing类在不同的项目中。
testing方法名称 。 我喜欢命名我的方法WhenXXX_ExpectYYY。 它使前提条件清晰,并有助于自动化文档(一个TestDox)。 这与Googletesting博客上的build议类似,但前提条件和期望更加分离。 例如:
WhenDivisorIsNonZero_ExpectDivisionResult WhenDivisorIsZero_ExpectError WhenInventoryIsBelowOrderQty_ExpectBackOrder WhenInventoryIsAboveOrderQty_ExpectReducedInventory
请参阅: http : //googletesting.blogspot.com/2007/02/tott-naming-unit-tests-responsibly.html
对于testing方法的名称,我个人发现使用详细和自我logging的名字是非常有用的(Javadoc的评论,进一步解释了什么是testing正在做)。
为了最大限度地描述它们,我最近提出了下面的约定来命名我的testing,他们的类和包含项目:
比方说,我正在testingMyApp.Serialization命名空间中的项目中的设置类。
首先我将用MyApp.Serialization.Tests命名空间创build一个testing项目。
在这个项目中,当然还有命名空间,我将创build一个名为IfSettings (保存为IfSettings.cs)的类。
比方说我正在testingSaveStrings()方法。 – >我将命名testingCanSaveStrings() 。
当我运行这个testing时,它会显示下面的标题:
MyApp.Serialization.Tests.IfSettings.CanSaveStrings
我想这个告诉我很好,它正在testing什么。
当然,在英语中,名词“Tests”与动词“tests”是相同的。
你在命名testing方面的创造力是没有限制的,所以我们可以为他们提供完整的句子标题。
通常,testing名称必须以动词开头。
例子包括:
- 检测(例如DetectsInvalidUserInput)
- 抛出(例如ThrowOnNotFound)
- 意志(例如WillCloseTheDatabaseAfterTheTransaction)
等等
另一种select是使用“that”而不是“if”。
后者为我节省了键盘input,并且更准确地描述了我正在做的事情,因为我不知道被testing的行为是否存在,但是是否正在testing。
[ 编辑 ]
现在使用上面的命名约定现在已经有一段时间了,我发现,在处理接口时, If前缀可能会造成混淆。 恰好如此,testing类IfSerializer.cs与“Open Files”选项卡中的接口ISerializer.cs非常相似。 在testing,被testing的类和接口之间来回切换时,这会变得非常烦人。 因此,我现在将select如果作为前缀。
此外,我现在使用 – 仅用于我的testing类中的方法,因为它不被认为是其他任何地方的最佳实践 – “_”用于分隔testing方法名称中的单词,如下所示:
- [testing] public void detected_invalid_User_Input()*
我觉得这样比较容易阅读。
[ 结束编辑 ]
我希望这会产生更多的想法,因为我认为命名testing非常重要,因为它可以为您节省大量的时间,否则这些时间会花费在试图了解testing正在做什么(例如,在延长的中断之后重新开始项目之后) 。
我使用Given-When-Then概念。 看看这个简短的文章http://cakebaker.42dh.com/2009/05/28/given-when-then/ 。 文章用BDD来描述这个概念,但是你也可以在TDD中使用它,而不需要做任何改变。
我认为最重要的事情之一是在你的命名约定中保持一致(并与你的团队的其他成员达成一致)。 很多时候,我看到在同一个项目中使用了大量不同的约定。
在VS + NUnit中,我通常会在项目中创build文件夹,将functiontesting分组在一起。 然后我创buildunit testing夹具类,并在我testing的functiontypes之后命名它们。 [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
我应该补充说,保持你的testing在同一个包中,但是在一个并行目录中被testing的源代码消除了代码的膨胀,一旦你准备好部署它,而不需要做一堆排除模式。
我个人喜欢“JUnit Pocket Guide”中描述的最佳实践…很难打败JUnit的合着者所写的一本书!
Foo类的testing用例的名称应该是FooTestCase或类似的东西(FooIntegrationTestCase或FooAcceptanceTestCase) – 因为它是一个testing用例。 见http://xunitpatterns.com/一些标准的命名约定,如testing,testing用例,testing夹具,testing方法等。;