如何设计高效测试用例_高效的企业测试-单元和用例测试(2/6)

如何设计高效测试用例

在本系列的第一部分中,我们看到了有效测试应满足的一些普遍适用的原则和约束。 在这一部分中,我们将仔细研究代码级单元测试和组件用例测试。

单元测试

单元测试验证单个单元(通常是类)的行为,而忽略或模拟该单元外部的所有问题。 单元测试应测试各个单元的业务逻辑,而不验证其进一步的集成或配置。

根据我的经验,大多数企业开发人员对单元测试的构建方式都有很好的了解。 您可以在我的咖啡测试项目中查看此示例,以了解想法。 大多数项目将JUnit与Mockito结合使用以模拟依赖关系,理想情况下使用AssertJ有效地定义可读的断言。 我一直认为,我们可以执行单元测试而无需特殊的扩展程序或运行程序,即仅使用纯JUnit运行它们。 原因很简单:执行时间; 我们应该能够在几毫秒内运行数百个测试。

单元测试通常执行速度非常快,并且易于执行,并且不会对测试套件的生命周期施加任何约束,因此它们易于支持构建复杂的测试套件或特殊的开发工作流程。

但是,具有许多模拟被测类的依赖关系的单元测试的缺点是,它们将与实现紧密结合,尤其是类结构和方法,这使得重构代码变得困难。 换句话说,对于生产代码中的每个重构动作,测试代码也需要更改。 在最坏的情况下,这会导致开发人员进行较少的重构,这仅仅是因为它们变得太麻烦了,从而Swift导致项目代码质量下降。 理想情况下,开发人员应该能够重构代码并四处移动内容,只要他们不改变应用程序的行为(从用户的角度来看)即可。 单元测试并不总是使重构生产代码变得容易。

根据项目的经验,单元测试对于测试具有简洁逻辑或功能的高密度代码(例如特定算法的实现)非常有效,同时又不会与其他组件发生过多交互。 特定类中的代码密度越小或越复杂,循环复杂性越低,或者与其他组件的交互性越高,则测试该类的单元测试效果就越差。 尤其是在具有少量专业业务逻辑并且与外部系统具有大量集成的微服务中,对许多单元测试的需求减少了。 除了少数例外,这些系统的各个单元通常包含很少的专用逻辑。 在选择权衡时间和精力的地方时,必须考虑到这一点。

用例测试

为了解决将测试与实现紧密耦合的问题,我们可以使用略有不同的方法来扩大测试范围。 在我的书中 ,我描述了组件测试的概念,因为缺少一个更好的术语,我们也可以将其称为用例测试。

用例测试是代码级集成测试,由于测试启动时间的原因,该类测试尚未使用嵌入式容器或反射扫描。 他们验证通常参与单个用例的一致组件的业务逻辑行为,从边界的业务方法一直到所有涉及的组件。 与外部系统(如数据库)的集成已被嘲笑。

在不使用自动连接组件的更先进技术的情况下构建此类方案听起来很费力。 但是,我们定义了可重用的测试组件或test double ,它们通过模拟,接线和测试配置来扩展组件,以最大程度地减少重构变更的整体工作量。 目标是制定单一职责,以将更改的影响限制在测试范围内的单个或几个类中。 以可重复使用的方式执行此操作会限制总体所需的工作量,并且在项目规模变大后会得到回报,因为我们每个组件只需支付一次管道费用,这很快就可以摊销。

为了获得更好的主意,假设我们正在测试订购咖啡的用例,其中包括两个类CoffeeShopOrderProcessor

测试双重类CoffeeShopTestDoubleOrderProcessorTestDouble*TD驻留在项目的测试范围中,而它们扩展了驻留在主范围中的CoffeeShopOrderProcessor组件。 测试双打可能会设置所需的模拟和连线逻辑,并可能使用与用例相关的模拟或验证方法来扩展类的公共接口。

下面显示了CoffeeShop组件的测试double类:

 public class CoffeeShopTestDouble extends CoffeeShop { public CoffeeShopTestDouble(OrderProcessorTestDouble orderProcessorTestDouble) { entityManager = mock(EntityManager. class ); orderProcessor = orderProcessorTestDouble; } public void verifyCreateOrder(Order order) { verify(entityManager).merge(order); } public void verifyProcessUnfinishedOrders() { verify(entityManager).createNamedQuery(Order.FIND_UNFINISHED, Order. class ); } public void answerForUnfinishedOrders(List<Order> orders) { // setup entity manager mock behavior }  } 

测试double类可以访问CoffeeShop基类的字段和构造函数以设置依赖项。 它使用其测试双重形式的其他组件,例如OrderProcessorTestDouble ,以便能够调用用例中包含的其他模拟或验证方法。

测试双重类是可重用的组件,在每个项目范围内编写一次,并在多个用例测试中使用

 class CoffeeShopTest { private CoffeeShopTestDouble coffeeShop; private OrderProcessorTestDouble orderProcessor; @BeforeEach void setUp() { orderProcessor = new OrderProcessorTestDouble(); coffeeShop = new CoffeeShopTestDouble(orderProcessor); } @Test void testCreateOrder() { Order order = new Order(); coffeeShop.createOrder(order); coffeeShop.verifyCreateOrder(order); } @Test void testProcessUnfinishedOrders() { List<Order> orders = Arrays.asList(...); coffeeShop.answerForUnfinishedOrders(orders); coffeeShop.processUnfinishedOrders(); coffeeShop.verifyProcessUnfinishedOrders(); orderProcessor.verifyProcessOrders(orders); }  } 

用例测试验证在入口点(这里为CoffeeShop上调用的单个业务用例的处理。 这些测试变得简短且易于阅读,因为接线和模拟发生在单个测试双打中,并且它们还可以利用特定于用例的验证方法,例如verifyProcessOrders()

如您所见,测试双重扩展了生产范围类,用于设置模拟和验证行为的方法。 尽管这似乎是一些设置工作,但如果我们有多个用例可以在整个项目中重复使用这些组件,则成本将Swift摊销。 我们的项目增长得越多,这种方法的好处就越大,尤其是当我们查看测试执行时间时。 我们所有的测试用例仍然使用JUnit运行,它可以立即执行数百个测试用例。

这是此方法的主要优点:用例测试的运行速度与普通单元测试一样快,但由于仅需对单个或几个组件进行更改,因此可以方便地重构生产代码。 此外,使用针对我们领域的富有表现力的设置和验证方法来增强测试效率,从而使我们的测试代码更具可读性,更易于使用,并避免了测试案例中的样板代码。

不包含任何高级测试上下文运行程序的代码级测试可以非常快速地执行,并且即使在非常复杂的项目中也不会为整体构建增加太多时间。 该系列的下一部分将显示代码级以及系统级集成测试。

翻译自: https://www.javacodegeeks.com/2019/09/efficient-enterprise-testing-unit-use-case.html

如何设计高效测试用例

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

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

相关文章

php mysql study_PHPstudy升级mysql数据库

首先查看phpstudy的mysql版本&#xff1a;方法一 使用mysql的version函数&#xff1a;mysql> selectversion();方法二 status命令mysql> status&#xff1b;方法三 直接在cmd下输入命令查看mysql -vmysql --help下面开始升级数据库1、备份好自己的数据库2、清空phpstudy…

selenium 等待_Selenium等待:内隐,外显,流利和睡眠

selenium 等待Selenium等待页面加载在Selenium脚本中起着重要的作用。 它们有助于使它们不易剥落&#xff0c;更可靠。 Selenium提供多次等待&#xff0c;以根据某些条件在脚本执行中提供足够的等待或暂停。 从而确保您在使用Selenium执行自动化测试时不会导致脚本失败。 在本教…

java接口概述

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java 接口概念 &#xff1b; 0.2&#xff09;接口技术&#xff1a; 这种技术主要用来描述类具有什么功能&#xff0c; 并不给出每个功能的具体实现&#xff1b; 一个类可以实现多…

通过aws部署推荐系统_通过AWS Elastic Beanstalk轻松进行Spring Boot部署

通过aws部署推荐系统朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户&#xff1f; 立即尝试Okta的API和Java SDK。 数分钟之内即可在任何应用程序中对用户进行身份验证&#xff0c;管理和保护。 几乎所有应用程序都依赖于身份验证。 开发人员以及雇用他们的公司都想确认…

图论算法基础

【0】README 0.1&#xff09;本文总结于 数据结构与算法分析&#xff0c; 旨在复习数据结构中图论算法的基础知识&#xff1b; 【1】图论若干相关定义 1.1&#xff09;图G定义&#xff1a;一个图G&#xff08;V&#xff0c;E&#xff09;由顶点及集V 和 边集E组成&#xff0c…

mysql 表丢失_Mysql数据库备份 部分数据表丢失 Mysql table doesn't exist 解决

问题&#xff1a;直接拷贝data下的数据库数据进行备份&#xff0c;重装升级了数据库&#xff0c;直接复制备份数据到新的数据库data目录下&#xff0c;发现部分数据表不见了。原因分析&#xff1a;以表“Table”为例:如类型是MyISAM, 数据文件则以”Table.frm”&#xff0c;”T…

aws 删除ec2实例_如何在AWS EC2实例上部署Spring Boot应用程序

aws 删除ec2实例你好朋友&#xff0c; 在本教程中&#xff0c;我们将看到如何在AWS EC2实例上部署Spring Boot应用程序。 这是我们将要执行的步骤。 1.使用Spring Boot Initialiser创建一个Spring Boot项目。 2.创建一个休息端点&#xff0c;部署后我们可以访问 3.启动EC2…

jdbc操作mysql数据库_JDBC操作MySQL数据库(一)

连接MySQL数据库连接数据源有两种方式&#xff1a;1)通过DriverManager类2)通过DataSource接口及JNDI资源获得连接DriverManager类的路径为java.sql.DriverManager&#xff0c;它主要完成驱动程序的装载和建立新的数据库连接。其常用方法如下&#xff1a;* getConnection (Stri…

只读事务上下文_我可以/应该在事务上下文中使用并行流吗?

只读事务上下文介绍 长话短说&#xff0c;您不应在并行流中使用事务。 这是因为并行流中的每个线程都有其自己的名称&#xff0c;因此它确实参与了事务。 Streams API旨在在某些准则下正常工作。 实际上&#xff0c;为了受益于并行性&#xff0c;不允许每个操作更改共享对象的…

mysql多表查询详解_MySQL多表查询详解上

时光在不经意间&#xff0c;总是过得出奇的快。小暑已过&#xff0c;进入中暑&#xff0c;太阳更加热烈的绽放着ta的光芒&#xff0c;...在外面被太阳照顾的人们啊&#xff0c;你们都是勤劳与可爱的人啊。在房子里已各种姿势看我这篇这章的你&#xff0c;既然点了进来&#xff…

无权最短路径

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在理解 无权最短路径 的思想并用源代码加以实现&#xff1b; 【1】无权最短路径相关概念&#xff08;边的权值赋值为1&#xff09; 1.1&#xff09;概述&#xff1a;下…

java 键入_在Java中键入Safe SQL

java 键入字符串&#xff0c;字符串&#xff0c;字符串 无论您使用的是JPA &#xff0c; MyBatis还是Spring Data JDBC之类的框架&#xff0c;总会最终将SQL语句声明为Java String。 这种方法的问题在于&#xff0c;您必须为每个语句编写测试&#xff0c;以确保它甚至是有效SQ…

filter过滤后重新添加_Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

前言在 Spring Boot 中已经移除了 web.xml 文件&#xff0c;如果需要注册添加 Servlet、Filter、Listener 为 Spring Bean&#xff0c;在 Spring Boot 中有两种方式&#xff1a;使用 Servlet 3.0 API 的注解 WebServlet、WebFilter、Listener 用来配置。Spring Boot JavaConfig…

对象克隆+深浅拷贝

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 对象拷贝 的概念 &#xff0c; 特别是对 深拷贝和浅拷贝 的理解&#xff1b; 0.2&#xff09; 最后&#xff0c;我们还要看一个 clone 的荔枝&#xff1b; 【1】对象克隆相关 1…

read cache_通过READ-BEHIND CACHE控制您的慢速生产者

read cache在我们的互联世界中&#xff0c;我们经常使用我们不拥有或无权改善的API中的数据。 如果一切顺利&#xff0c;他们的表现就会很好&#xff0c;每个人都会高兴。 但是太多次&#xff0c;我们不得不使用延迟小于最佳延迟的 API。 当然&#xff0c;答案是缓存该数据 。…

azkaban mysql参数_azkaban参数详解

参数传递是调度字体工作流运行时非常重要的一部分&#xff0c;工作流的执行&#xff0c;单个作业的执行&#xff0c;多个工作流之间的依赖执行&#xff0c;历史任务重算&#xff0c;都涉及到参数传递和同步。1 参数类型综述azkaban的工作流中的参数可以分为如下几个类型&#x…

接口与回调

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 接口与回调 概念 &#xff1b; 【1】接口与回调相关 1.1&#xff09;回调定义&#xff1a; 回调是一种常见的程序设计模式&#xff0c; 在这种模式中&#xff0c; 可以指出某个…

spring react_使用Spring Cloud Gateway保护React式微服务

spring react朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户&#xff1f; 立即尝试Okta的API和Java SDK。 数分钟之内即可在任何应用程序中对用户进行身份验证&#xff0c;管理和保护。 所以你想完全React&#xff0c;是吗&#xff1f; 大&#xff01; React式编程是使…

mysql断电同步不起作用_mysql主从同步因断电产生的不能同步问题

偶尔因为断电导致mysql slave 出现复制错误“Could not parse relay log event entry”Could not parse relay log event entry. The possible reasons are: the masters binary log is corrupted (you can check this by running mysqlbinlog on the binary log), the slaves …

图论——Dijkstra+prim算法涉及到的优先队列(二叉堆)

【0】README 0.1&#xff09;为什么有这篇文章&#xff1f;因为 Dijkstra算法的优先队列实现 涉及到了一种新的数据结构&#xff0c;即优先队列&#xff08;二叉堆&#xff09;的操作需要更改以适应这种新的数据结构&#xff0c;我们暂且吧它定义为Distance&#xff0c; 而不是…