在单元测试和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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350736.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

40个Java多线程问题总结

前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多、越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的。这篇文章主要是对多线程的问题…

.pro.user文件

.pro.user 用于记录打开工程的路径,所用的编译器、构建的工具链、生成目录、打开工程的qt-creator的版本等。 当更换编译环境时,要将其删除。

python tkinter实例_python绘制一个图形示例源码(tkinter)

【实例简介】 【实例截图】【核心代码】 # -*- coding: utf-8 -*- #!/usr/bin/python import math from tkinter import * class PTS: def __init__(self): self.x 0 self.y 0 points [] def LineToDemo(): screenx 400 screeny 400 canvas Canvas(width screenx,height…

PHP算法之冒泡排序

//冒泡排序 //①思路,先比较出第一次,找一个最大的值,排到最后; //②重复count遍之后,就能得到排序; //③优化,每一次循环之后不需要再次全部重复; $array [11,5,4,58,1,222,34]; for ($j 0; $j< count($array)-1; $j) { for($i 0 ; $i < count($array)-$j-1; $i){if(…

jaxb 命名空间_在JAXB解组期间应用名称空间

jaxb 命名空间对于某些XML模式来说&#xff0c;它是一组严格的规则&#xff0c;用于规定XML文档的结构方式。 但是对于其他人来说&#xff0c;通常的准则是指出XML的外观。 这意味着有时出于某些原因&#xff0c;人们希望接受不符合XML模式的输入。 在此示例中&#xff0c;我将…

pro文件

配置 注释 以“#”开始&#xff0c;到这一行结束。 快捷键&#xff1a;Ctrl / CONFIG 指定编译器选项和项目配置&#xff0c;值由qmake内部识别并具有特殊意义。 以下配置值控制编译标志&#xff1a; 选项说明release项目以release模式构建。如果也指定了debug&#xff0c;那么…

Java Thread 总结

线程的概述&#xff08;Introduction&#xff09; 线程是一个程序的多个执行路径&#xff0c;执行调度的单位&#xff0c;依托于进程存在。 线程不仅可以共享进程的内存&#xff0c;而且还拥有一个属于自己的内存空间&#xff0c;这段内存空间也叫做线程栈&#xff0c;是在建立…

前端和后端哪个工资高_新媒体运营和网络运维哪个好,哪个工资待遇高,门槛低?...

文/水流云在草青青通常情况下&#xff0c;门槛高低和待遇高低成反比。工资待遇和工作本领成正比。除非你有人脉或贵人&#xff0c;除非你踩狗屎运。门槛低&#xff0c;待遇高的工作对绝大多数人而言是梦话。不知题主朋友的特长是什么&#xff1f;有哪些工作经验&#xff1f;青青…

python框架源码学习

最近下了一个别人的接口测试框架原码来学习 1.有用到logbook模块进行日志管理 2.使用xlrd模块对excel数据表的操作 3.使用自定义的代码输出测试报告 4.使用logger模块记录运行时日志 主要是看了关于接口的代码&#xff1a;封装了http请求的get/post请求 用法&#xff1a; 需要导…

使用TestContainers进行数据库测试

如果您曾经编写过测试数据库交互的代码&#xff0c;例如数据访问对象&#xff0c;那么您很可能遇到了测试中最长期的烦恼之一&#xff1a;为了准确地测试这些交互&#xff0c;需要一个数据库。 为了本文的方便&#xff0c;让我们考虑一个将PostgreSQL用作其环境的一部分的应用…

cuda安装配置VS2013

1.1 安装cuda 首先官网下载安装包&#xff0c;这个就不细说了 &#xff0c;我下的是这个版本cuda_8.0.61_win10.exe&#xff0c;&#xff0c;注意win7和win10版本要对应&#xff0c;千万别弄错了 之后双击会出现如下截图&#xff0c;解压完以后一直点下一步如下图出现这个等半个…

两列布局、三列适应布局、两列等高适应布局。

一. 两列布局&#xff1a;左侧定宽、右侧自适应。 四种方法 &#xff1a;flex 、position、float和负外边距、外边距 1. 使用flex. <!DOCTYPE html> <html> <head><meta charset"utf-8"><title></title><style type"tex…

操作系统的线程和进程的区别_面试官:你熟悉多线程嘛?线程跟进程有什么区别?...

这篇文章跟大家聊聊线程&#xff0c;讲到线程&#xff0c;⼜不得不提进程了~进程我们估计是很了解的了&#xff0c;在windows下打开任务管理器&#xff0c;可以发现我们在操作系统上运⾏的程序都是进程。什么是叫一个进程&#xff1f; 什么叫一个线程&#xff1f;进程&#xff…

以OpenCV为例配置VS第三方库

正常情况下&#xff0c;你拿到的别人的第三方动态库&#xff08;静态库调用方式这里不讲&#xff0c;有另外一篇文章&#xff09;至少应该包含下面三种文件&#xff1a; 1. 头文件&#xff0c;这个一般放在include这样字眼的文件夹下&#xff0c;比如OpenCV的&#xff1a;然后i…

光纤接口怎么接 图解_光纤的数据比网线快很多倍,但为什么没有在家庭局域网中普及呢?...

光纤的数据吞吐量比网线大很多&#xff0c;速度也更快&#xff0c;网络光纤入户已经普及&#xff0c;但是家庭内组网却没有普及&#xff0c;大部分家庭组网还是网线较多。分析起来主要的原因有&#xff1a;光纤线的价格和网线差不多&#xff0c;但是因为光纤所使用的专用的光接…

项目Alpha冲刺--1/10

项目Alpha冲刺--1/10作业要求 这个作业属于哪个课程软件工程1916-W(福州大学)这个作业要求在哪里项目Alpha冲刺团队名称基于云的胜利冲锋队项目名称云评&#xff1a;高校学生成绩综合评估及可视化分析平台这个作业的目标团队的代码规范、本次冲刺任务与计划其他参考文献1.邹欣.…

Java连接postgresql数据库

1.下载驱动jar 下载地址&#xff1a;https://jdbc.postgresql.org/download.html 2.导入jar包 新建lib文件夹&#xff0c;将下载的jar驱动包拖到文件夹中。 将jar驱动包添加到Libraries 3.程序代码如下&#xff1a;HelloWorld.java package test; import java.sql.Connecti…

jvm默认的初始化参数_您是否应该信任JVM中的默认设置?

jvm默认的初始化参数如今&#xff0c;JVM被认为是智能的。 预期配置不多-只需设置要在启动脚本中使用的最大堆&#xff0c;您就可以进行了。 所有其他默认设置都很好。 大概我们当中有些人误以为。 实际上&#xff0c;在运行时期间发生了很多事情&#xff0c;无法自动调整性能&…

setGeometry

setGeometry (9,9, 50, 25) 从屏幕上&#xff08;9&#xff0c;9&#xff09;位置开始&#xff08;即为最左上角的点&#xff09;&#xff0c;显示一个50*25的界面&#xff08;宽50&#xff0c;高25&#xff09; 如果在控件中加上了layout布局&#xff0c;就会发现发现没有办法…

python如何输出两行_python pandas dataframe拆分行(某些行一行拆成多行)

简单循环 最简单的方式就是循环拆分一下呗。先上最简单方法&#xff1a;import pandas as pd df pd.DataFrame({A:[1,2,3],B:[1,2,3,4,5,6],C:[3,3,3]}) result pd.DataFrame(columns[A,B,C]) print(df,\n)for i in df.itertuples(): for j in i[2].split(,): result result…