在单元测试和TDD中指定时间的重要性

最近,我一直在写与自动测试有关的更高级的概念(主要与Spock有关)。 但是,在进行测试培训时,我清楚地看到,通常对特定工具的知识并不是主要问题。 即使使用Spock,也可以编写肿且难以维护的测试,从而破坏(或不了解)与编写单元测试有关的良好实践。 因此,我决定写一些更基本的东西来促进它们,并且在指导经验不足的同事时准备使用一些参考材料。

介绍

编写良好的单元测试应满足几个要求,这是整个系列的主题。 在这篇博客文章中,我想提出一个相当成熟的概念,即使用严格定义的功能(依次是行为驱动开发的子集)将单元测试划分为3个独立的块。

单元测试通常集中于测试给定单元(通常是一个给定类)的某些特定行为。 与通过UI执行的验收测试相反,在每个测试中都将存根/模拟作为其合作者,从零开始设置一个要测试的类(被测类)是便宜(快速)。 因此,性能应该不是问题。

样品测试

为了演示规则,我将使用一个小例子。 ShipDictionary是一个类,可根据特定条件(按名称的一部分,生产年份等)搜索太空船。 该词典由不同的船舶索引(在役,退役,在生产等中的船舶)提供动力。 在那个特定的测试中,它被测试了按其名称的一部分搜索飞船的能力。

private static final String ENTERPRISE_D = "USS Enterprise (NCC-1701-D)";

@Test
public void shouldFindOwnShipByName() {
//given
ShipDatabase shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex);
given(ownShipIndex.findByName("Enterprise")).willReturn(singletonList(ENTERPRISE_D));
//when
List foundShips = shipDatabase.findByName("Enterprise");
//then
assertThat(foundShips).contains(ENTERPRISE_D);
}

给定时间

测试驱动开发方法和行为驱动开发方法中都存在的良好习惯是“先验”知识,将在特定测试用例中进行测试(认定)。 可以以更正式的方式(例如,用Cucumber / Gherkin编写的用于验收测试的方案)或以自由形式(例如,特别注意的要点或只是下一步应该做什么的想法)来完成。 有了这些知识,就很容易确定整个测试将组成的三个关键部分(分开的部分)。

给定–准备

在单元测试的第一部分(称为given )中,需要创建一个实际对象实例,在该对象实例上将执行测试的操作。 在重点单元测试中,只有一类放置要测试的逻辑。 此外,应将执行测试所需的其他对象(称为协作者)初始化为存根/模拟,并适当存根(如果需要)。 还必须将所有协作者注入到要测试的对象中,该对象通常与对象创建结合在一起(因为构造函数注入应该是依赖注入的首选技术)。

//given
ShipDatabase shipDatabase = new ShipDatabase(ownShipIndex, enemyShipIndex);
given(ownShipIndex.findByName("Enterprise")).willReturn(singletonList(ENTERPRISE_D));

何时–执行

when部分中,将执行要测试的操作。 在我们的情况下,这是一个搜索请求,然后将结果存储在变量中以供进一步声明。

//when
List foundShips = shipDatabase.findByName("Enterprise");

在大多数情况下,在该部分中仅执行一个操作是一件好事。 更多的元素可能表明尝试测试多个操作(可能)可以分为多个测试。

然后–断言

-最后一节的责任, then -主要是先前接收到的结果的断言。 它应该等于期望值。

//then
assertThat(foundShips).contains(ENTERPRISE_D);

另外,可能有必要对声明的模拟执行方法执行的验证。 这不应该是一种普遍的做法,因为在大多数情况下,对接收值的声明足以确认所测试的代码按预期工作(根据设置的边界)。 但是,尤其是在测试void方法时,需要验证使用预期参数执行的特定方法。

AAA aka 3A –一种替代语法

正如我已经提到的,BDD是一个更广泛的概念,对于编写具有预先定义的需求(通常以非技术形式)的功能/验收测试而言,BDD特别方便。 一种替代的测试划分语法(对于各节而言具有非常相似的含义)是通常将其缩写为AAA或3A的“ 排列动作声明” 。 如果您根本不使用BDD,并且三个字母比GWT更容易记住,那么使用它来创建相同的高质量单元测试就很好。

调整与优化

实用工具和方法学与持续进行的技能获取过程(也称为Dreyfus模型 )进行匹配的过程已在《 实用思维与学习:重构您的湿软件 》一书中进行了很好的描述。 当然,在许多情况下,使用测试的简化变体可能很方便, given节移到setup/init/before节或内联初始化。 同样可以适用于whenthen部分,其可以被合并在一起(成expect部分,特别是在参数化测试)。 具有编写单元测试的经验和流利性,使用速记和优化(特别是测试一些非平凡的案例)是完全有效的。 只要整个团队都了解约定,并且能够记住有关编写好的单元测试的基本假设。

摘要

根据我在软件开发方面的经验以及作为一名培训师,我清楚地看到将(单元)测试划分为多个部分可以使它们更短,更易读,尤其是团队中经验不足的人员。 用简单定义的责任来填充3个部分比立即找出并在测试中编写所有内容要容易得多。 最后,特别是对于仅阅读本文第一部分和最后部分的人们,此处遵循以下简明规则:

  • given –测试中的对象初始化+存根/模拟的创建,存根和注入
  • when –在给定测试中进行测试的操作
  • then –收到结果声明+模拟验证(如果需要)

PS最好在IDE中设置一个测试模板,以保护编写每个测试所需的许多击键。
PSS,我认为本文很有用,您可以让我知道,以激励我将来写更多有关单元测试的基础知识。

图片来源:Tomas Sobek,Openclipart, https ://openclipart.org/detail/242959/old-scroll

自我提升 。 您想快速有效地提高您和您的团队的测试技能以及对Spock / JUnit / Mockito / AssertJ的了解吗? 我进行了浓缩(单元) 测试培训 ,您可能会觉得有用。

翻译自: https://www.javacodegeeks.com/2017/05/importance-given-unit-tests-tdd.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
测试驱动的编程是 XP 困扰程序员的一个方面。对于测试驱动的编程意味着什么以及如何去做,大多数人都做出了不正确的假设。这个月,XP 方面的讲师兼 Java 开发人员 Roy Miller 谈论了测试驱动的编程是什么,它为什么可以使程序员的生产力和质量发生巨大变化,以及编写测试的原理。请在与本文相随的 论坛提出您就本文的想法,以飨笔者和其他读者。(您也可以单击本文顶部或底部的“讨论”来访问该论坛。) 最近 50 年来,测试一直被视为项目结束时要做的事。当然,可以在项目进行之结合测试,测试通常并不是在 所有编码工作结束后才开始,而是一般在稍后阶段进行测试。然而,XP 的提倡者建议完全逆转这个模型。作为一名程序员,应该在编写代码 之前编写测试,然后只编写足以让测试通过的代码即可。这样做将有助于使您的系统尽可能的简单。 先编写测试 XP 涉及两种测试: 程序员测试和 客户测试。测试驱动的编程(也称为 测试为先编程)最常指第一种测试,至少我使用这个术语时是这样。测试驱动的编程是让 程序员测试(即单元测试 ― 重申一下,只是换用一个术语)决定您所编写的代码。这意味着您必须在编写代码之前进行测试。测试指出您 需要编写的代码,从而也 决定了您要编写的代码。您只需编写足够通过测试的代码即可 ― 不用多,也不用少。XP 规则很简单:如果不进行程序员测试,则您不知道要编写什么代码,所以您不会去编写任何代码。 测试驱动开发(TDD)是极限编程的重要特点,它以不断的测试推动代码的开发,既简化了代码,又保证了软件质量。本文从开发人员使用的角度,介绍了 TDD 优势、原理、过程、原则、测试技术、Tips 等方面。 背景 一个高效的软件开发过程对软件开发人员来说是至关重要的,决定着开发是痛苦的挣扎,还是不断进步的喜悦。国人对软件蓝领的不屑,对繁琐冗长的传统开发过程的不耐,使大多数开发人员无所适从。最近兴起的一些软件开发过程相关的技术,提供一些比较高效、实用的软件过程开发方法。其比较基础、关键的一个技术就是测试驱动开发(Test-Driven Development)。虽然TDD光大于极限编程,但测试驱动开发完全可以单独应用。下面就从开发人员使用的角度进行介绍,使开发人员用最少的代价尽快理解、掌握、应用这种技术。下面分优势,原理,过程,原则,测试技术,Tips等方面进行讨论。 1. 优势 TDD的基本思路就是通过测试来推动整个开发的进行。而测试驱动开发技术并不只是单纯的测试工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值