单元测试之禅


编写良好的单元测试的能力是任何开发人员的重要功能。 但是如何理解您的单元测试是正确的呢? 好的单元测试就像是很好的国际象棋游戏。 在我们的案例中,下棋者是我们将在本文中讨论的方法。 在象棋游戏中没有最好的棋手,因为一切都取决于位置(和玩家) 。 同样,在单元测试中,您不必仅区分一种方法。 换句话说,您应该一起使用所有方法以获得最佳结果。 因此,如果您想赢得这场比赛,那么欢迎您参加。


出道


为什么要编写单元测试?


您不必编写单元测试,除非您是一个具有超常感知能力的人,他们可以编写代码而没有错误,您拥有超大的内存,可以在脑海中编译您的代码,或者就像痛苦一样。 否则,您肯定必须编写单元测试,因为它们会减少新功能和现有功能中的错误数量,降低成本并担心更改功能并允许重构代码。 此外,您应该始终运行现有测试,我建议您注意连续测试工具。


要测试什么?


显然,在单元测试中,您正在测试某个单独单元的行为(不是调用,因为稍后可以更改它们) 。 另外,将所有发现的错误证明为已修复的单元测试定为一条规则。 那么代码覆盖率呢? 代码覆盖率不是目标,它只是一种度量,可以帮助您了解忘记了单元测试的逻辑部分。 当您决定使用单元测试覆盖每一行代码时,这将是一个巨大的错误。


Mittelspiel


只测试一件事


不要将单元测试与集成测试混为一谈,在集成测试中 ,不止一项测试是正常的。 单元测试的思想是证明一个单独的应用程序模块是否起作用。 您必须轻松理解,并且肯定要理解代码中的哪些行为失败以及如何解决。 您应该使用几个断言? 一个! 使用许多断言可能是您正在测试的代码异味。 此外,有人可能会在测试中添加新的断言,而不用编写另一个断言。 当第一个失败时,您如何理解其他声明的完成方式?


避免逻辑


测试中的错误是开发人员最难发现的东西。 当您决定在测试中添加逻辑时,在测试代码中出现错误的机会就会增加。 变得难以阅读,理解和维护。 在测试中使用forforeachifswitch和其他运算符也可能是代码气味,说明您要测试的不只一件事。


AAA级


排列,执行,声明是一种常用的模式,可以帮助将测试代码相应地组织为三个阶段。 它清楚地将要测试的内容与设置和验证步骤分开。 这是最佳实践之一,它使您的测试代码更具可读性和可维护性。 话虽如此,如果您想保持代码的清洁和可读性,请不要在测试中使用AAA 注释 。 有效创建的测试即使没有评论也能表达AAA想法。


遵守命名约定


测试名称不仅应对其作者具有描述性,而且应易于理解。 测试命名策略很多,但我喜欢Roy Osherove的一种: [MethodName_StateUnderTest_ExpectedBehavior] 。 它以格式化的方式提供了有关测试的所有必要信息。 任何开发人员都可以很容易地遵循这种策略。


范例:


 public void Sum_NegativeNumberAs2ndParam_ExceptionThrown () public void Sum_simpleValues_Calculated () public void Parse_OnEmptyString_ExceptionThrown() public void Parse_SingleToken_ReturnsEqualTokenValue () 

但是请注意,您可能具有在当前项目中必须遵循的命名约定。 不要把它们混在一起。


测试数据准备


构造测试数据可能会给您的测试代码带来混乱和痛苦。 在以下情况下,您可以面对这种情况:


  • 您必须在创建该模型的每段代码中更改模型的构造函数(通常在模型不可变时发生)
  • 构建测试数据时,您有很多重复的代码;
  • 您必须将许多“魔术数据”传递到模型构造函数中(例如, new Device("Stub", 10, true, "http");
  • 您感到需要创建一种随机数据生成器;
  • 您很难建立测试数据集合。

考虑到这一点,您必须考虑一些常见的替代方法: 对象母体和[Fluent构建器模式]。 这种方法也是优秀的团队合作者,因此可以一起使用。


不要使用随机数据,因为您的测试可能对某些值敏感。 结果,您会在测试中得到难以发现和复制的邪恶的海森伯


了解您的测试框架


了解测试框架的所有属性,断言和其他功能。 它可以帮助您提高测试的可读性和优雅度。 例如,在NUnit框架中,您可以使用两个断言模型,并且可以选择最喜欢的一个:


 Assert.AreEqual(StatusCode.OK, response.StatusCode); 


 Assert.That(StatusCode.OK, Is.EqualTo(response.StatusCode)); 

不要忘记设置和拆卸方法,TestCase和Category属性,集合断言。 不要在断言中混淆预期和实际结果参数。


恩斯皮尔


测试代码与必须编写和维护的生产代码具有相同的特权,请不要忘记SOLID原理。 另外,您的单元测试应该可读,并且有几个原因。 首先,测试的意图应该是可以理解和清楚的。 这意味着您不必在阅读测试时浪费时间。 其次,无需调试即可轻松维护测试,检测并消除故障。


单元测试是一种巨大的哲学,不能仅在一篇文章中讨论。 在这里,我解释了与单元测试有关的常见方法和常见问题。 如果您想更深入地学习,可能会发现此链接很有趣:


Roy Osherove博客
Roy Osherove的书,“单元测试的艺术”


保持冷静并进行单元测试

Source: https://habr.com/ru/post/zh-CN439804/


All Articles