编写unit testing标准

我计划在我的团队中引入一套标准来编写unit testing。 但要包括什么?

这两个post( unit testing命名最佳实践和单元/集成测试中文件系统依赖关系的最佳实践 )给了我一些思考的东西。

我的标准中应该涵盖的其他领域应该是如何设置测试类以及如何组织它们。 例如,如果你有一个名为OrderLineProcessor的类,那么应该有一个名为OrderLineProcessorTest的测试类。 如果在该类上有一个名为Process()的方法,那么应该有一个名为ProcessTest的测试(可能更多来测试不同的状态)。

还包括其他什么东西?

贵公司是否有unit testing标准?

编辑:我正在使用Visual Studio Team System 2008,我在C#.Net中开发

看看Michael Feathers关于什么是unit testing (或者是什么使unit testing不良unit testing)

看看“安排,行动,断言”的想法,即测试只按固定顺序执行三项操作的想法:

  • 安排测试所需的任何输入数据和处理类
  • 执行测试中的操作
  • 使用一个或多个断言测试结果。 是的,它可以是多个断言,只要它们都能够测试所执行的操作。

了解行为驱动开发 ,以便将测试用例与需求保持一致。

此外,我今天对标准文件的看法是,除非必须,否则不应该写它们 – 已经有很多可用的资源。 链接到他们而不是重复他们的内容。 为想要了解更多信息的开发人员提供阅读列表。

您应该看看“实用unit testing”系列。 这是C#版本,但Java还有另一个版本。

关于你的规范,我不会过火。 你有一个非常好的开始 – 命名约定非常重要。 我们还要求目录结构与原始项目匹配。 覆盖范围还需要扩展到边界案例和非法值(检查exception)。 这是显而易见的,但你的规范是为那个论点写下来的地方,你将来不可避免地会遇到那些不想测试通过非法值的人。 但是,不要让规范超过几页,否则没有人会将它用于与上下文相关的任务。

更新:我不同意Potato Head先生每unit testing只有一个断言。 这在理论上听起来相当不错,但在实践中,它会导致大多数冗余测试的负载,或者人们在设置和拆卸方面做大量工作本身应该进行测试。

我遵循TDD的TDD风格。 请参阅: http : //blog.daveastels.com/files/BDD_Intro.pdf http://dannorth.net/introducing-bdd http://behaviour-driven.org/Introduction

简而言之,这意味着

  • 测试不被视为“测试”,而是作为系统行为的规范(以下称为“规范”)。 规范的目的不是validation系统在任何情况下都能正常工作。 他们的目的是指定行为并推动系统的设计。

  • spec方法名称被写为完整的英语句子。 例如,球的规格可以包括“球是圆的”和“当球击中地板然后它反弹”。

  • 生产类和规范类之间没有强制的1:1关系(并且为每个生产方法生成测试方法都是疯狂的)。 相反,系统的行为与规格之间存在1:1的关系。

前段时间我写过TDD教程(你开始使用提供的测试开始编写俄罗斯方块游戏),它将这种编写测试的样式显示为规范。 您可以从http://www.orfjackal.net/tdd-tutorial/tdd-tutorial_2008-09-04.zip下载该教程中仍然缺少有关如何进行TDD / BDD的说明,但示例代码已准备就绪,因此您可以看到测试的组织方式并编写传递它们的代码。

您会注意到在本教程中,生产类被命名为Board,Block,Piece和Tetrominoe,它们以俄罗斯方块游戏的概念为中心。 但测试类围绕俄罗斯方块游戏的行为:FallingBlocksTest,RotatingPiecesOfBlocksTest,RotatingTetrominoesTest,FallingPiecesTest,MovingAFallingPieceTest,RotatingAFallingPieceTest等。

  1. 尝试尽可能少地使用每种测试方法的断言语句。 这确保了测试的目的是明确定义的。
  2. 我知道这将是有争议的,但不要测试编译器 – 测试Java Bean访问器和更改器花费的时间最好花在编写其他测试上。
  3. 尽可能尝试使用TDD,而不是在代码后编写测试。

我发现大多数测试约定都可以通过为所有测试使用标准基类来实施。 强制测试人员覆盖方法,以便它们都具有相同的名称。

我还提倡使用Arrange-Act-Assert (AAA)测试样式,然后您可以从测试中生成相当有用的文档。 它还会强制您考虑由于命名风格而您期望的行为

您可以在标准中添加的另一个项目是尝试保持单位测试尺寸小。 这就是实际测试方法本身。 除非您正在进行完整的集成unit testing,否则通常不需要进行大型unit testing,例如超过100行。 如果你有很多设置可以进行一次测试,我会给你那么多。 但是,如果你这样做,你应该重构它。

人们还谈到重构代码,确保人们意识到unit testing也是代码。 所以重构,重构,重构。

我发现在我看到的用途中最大的问题是人们并不倾向于认识到你希望保持你的unit testing轻巧灵活。 毕竟你不需要一个单片兽来进行测试。 考虑到这一点,如果您有一个尝试测试的方法,则不应在一个unit testing中测试每个可能的路径。 您应该有多个unit testing来考虑该方法的每个可能路径。

是的,如果您正确地进行了unit testing,那么平均应该有比您的应用程序更多的unit testing代码。 虽然这听起来像很多工作,但是当不可避免的业务需求发生变化时,它最终会为您节省大量时间。

我使用几乎简单的英语作为我的unit testing函数名称。 帮助定义他们的确切行为:

 TEST( TestThatVariableFooDoesNotOverflowWhenCalledRecursively ) { /* do test */ } 

我使用C ++但命名约定可以在任何地方使用。

确保包含不是unit testing的内容。 请参阅: unit testing时不测试什么?

包括指南,以便清楚地识别集成测试,并且可以与unit testing分开运行。 这很重要,因为如果unit testing与其他类型的测试混合,您可以以一组“单元”测试结束,这些测试非常慢。

检查这个以获取更多信息: 如何改进我的junit测试 …特别是第二次更新。

如果您使用的是Junit系列中的工具(OCunit,SHunit,…),测试名称已经遵循一些规则。

对于我的测试,我使用自定义Doxygen标签,以便在特定页面中收集他们的文档。