如何设计单元测试用例?

news2024/11/17 21:49:58

🍅 视频学习:文末有免费的配套视频可观看

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快

最近一些大公司在进行去测试化的操作,这一切的根源大概可以从几年前微软一刀切砍掉所有内部正式的测试人员开始说起,当时微软内部的测试工程师有一部分转职成了开发工程师,他们的职能中有很大一部分的职责是教会普通开发人员如何进行测试。我们都知道开发人员进行的测试一般以单元测试为主,假如有一天你所在的组织需要你转变成一名测试方面的教练,除了自动化测试之外还需要去推广单元测试,那么你该如何去定义单元测试用例的设计方法论呢?这里给大家一些思路,看看简单的单元测试用例究竟该如何设计。

一个方法可以有任意数量的有效测试用例;它最终取决于方法的结构。有两种简单的方式可以帮助我们设计单元测试用例。

  • 参数方法
  • 执行路径方法

我将通过提供真实的代码来进行演示。所有代码片段都将用 C# 编写,断言将使用我最喜欢的单元测试包 Fluent Assertions。

我们将为以下方法提供测试用例:

public static bool ContainsNamelessItems(this List<Item> items)
{
  return items.Any(item => item.Name.IsNullOrEmpty())
}

此方法将项目集合作为参数。它遍历项目列表,并针对每个项目Item检查其name属性是否为空。如果name存在且不为空,我们返回True,否则我们返回False

使用参数方法创建测试用例

这种方式主要考虑的是入参可以传递哪些值。

查看该方法的参数ContainsNamelessItems,我们有一个List名为items. 此参数可能有几个可能的值:

  • items 是空的
  • items至少包含 1 个Item具有Name未定义的属性
  • items不包含具有未定义Name属性的项目
  • items 是 null

这些可能的值中的每一个都可以作为单独的用例存在。

以下是一些可能的测试用例和断言:

1,当List<Item>为空时,我们期望返回值是False因为其的List<Item>无name属性。

public void WhenItemsIsEmpty_ReturnFalse()
{
  var items = new List<Item>();
 
  var result = items.ContainsNamelessItems();
 
  result.Should()
    .BeFalse("because an empty collection cannot contain nameless items");
}

2,当List<Item>包含至少 1 项没有name属性的Item时,我们期望返回值是True

public void WhenItemsContainsANamelessItem_ReturnTrue()
{
  var items = new List<Item>
  {
    { new Item { Name = "Item1" },
    { new Item { Name = string.Empty } // nameless item
  };
 
  var result = items.ContainsNamelessItems();
 
  result.Should()
    .BeTrue("because there is a nameless item in the collection");
}

3,当List<Item>不包含任何没有name属性的项目时,我们期望返回值是False,因为所有项目都有name。

public void WhenItemsDoesNotContainANamelessItem_ReturnFalse()
{
  var items = new List<Item>
  {
    { new Item { Name = "Item1" },
    { new Item { Name = "Item2" }
  };
 
  var result = items.ContainsNamelessItems();
 
  result.Should()
    .BeFalse("because there are no nameless items in the collection");
}

4,当List<Item>is null的时候,我们期望抛出ArgumentNullException异常,这往往是最难想到的。

public void WhenItemsIsNull_ThrowArgumentException()
{
  List<Item> items = null;
 
  Action act = () => items.ContainsNamelessItems();
 
  act.Should()
    .Throw<ArgumentNullException>("because the collection is null");  
}

使用执行路径方法创建测试用例

路径方式需要遍历被测方法并找到所有不同的执行路径。

我们上面定义的方法只有一条执行路径,因为除了直接到达方法的末尾之外,没有任何条件驱动路径。要改变路径,我们就需要引入某种条件,可以通过if...else、 switch以及try/catch语句。在这些条件块中,方法可能会在达到某个条件的情况下直接退出,而不是运行到方法的最后一行。

下面我们就引入条件。假设我们不希望方法在入参为空时候抛出ArgumentNullException异常,而是想抛出一个我们自定义的ArgumentException异常。那么我们必须向检查项目列表是否为空的方法添加一个条件。

流程图如下:

现在,如果项目为空,则有可能提前退出,而不是走到方法的末尾,具体实现如下

public static bool ContainsNamelessItems(List<Item> items)
{
  if (items == null)
    throw new ArgumentException("The collection of items should not be null.");
 
  return items.Any(item => item.Name.IsNullOrEmpty())
}

这个测试用例的相应测试看起来像这样:

public void WhenItemCollectionIsNull_ThrowArgumentException()
{
  List<Item> items = null;
 
  Action act = () => items.ContainsNamelessItems();
 
  act.Should().Throw<ArgumentException>()
    .WithMessage("The collection of items should not be null.");  
}

总结

在入参的时候可以用等价类的方式构造任意参数,强类型语言里无效类用的会相对少一些,毕竟编译器会进行校验;而弱类型语言里无效类比较隐蔽,是测试的重点;

执行路径方法其实就是分支覆盖,通过不通的输入参数去覆盖所有分支,比如同样是有效类的输入情况下,空集合和非空集合可能会走到不通的路径;

在方法或函数特别复杂的情况下,可以试着去把方法拆小,从而获得更好的可测试性;

在这我为大家准备了一份软件测试视频教程(含面试、接口、自动化、性能测试等),就在下方,需要的可以直接去观看,也可以直接【点击文末小卡片免费领取资料文档】

2024全网最牛,字节大佬花了一周讲完的自动化测试全套教程,从零开始教你成为年薪百万测开工程师

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

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

相关文章

【深度学习实战(10)】图像推理之预处理

一、预处理流程 在把一张图像送入模型进行推理时&#xff0c;需要先进行预处理&#xff0c;预处理流程包括&#xff1a; &#xff08;1&#xff09;读取图像 &#xff08;2&#xff09;尺寸调整&#xff0c;letter_box&#xff08;不失真&#xff09; &#xff08;3&#xff0…

MATLAB绘制圆锥曲线:抛物线,双曲线,椭圆

MATLAB绘制圆锥曲线:抛物线,双曲线,椭圆 clc;close all;clear all;warning off;%清除变量x linspace(-10, 10, 1000); % 创建一个x值的向量&#xff0c;范围从-10到10&#xff0c;共1000个点 y x.^2; % 计算每个x值对应的y值% 使用plot函数绘制图形 figure; % 创建一个新的图…

排序 “壹” 之插入排序

目录 ​编辑 一、排序的概念 1、排序&#xff1a; 2、稳定性&#xff1a; 3、内部排序&#xff1a; 4、外部排序&#xff1a; 二、排序的运用 三、插入排序算法实现 3.1 基本思想 3.2 直接插入排序 3.2.1 排序过程&#xff1a; 3.2.2 代码示例&#xff1a; 3.2.3…

使用Spring进行文件的上传和下载

概览 使用Spring进行文件的上传和下载Spring上传文件接口设计dubbo接口设计上传文件流的RPC的接口设计 Spring文件下载接口设计dubbo接口设计下载文件流的RPC的接口设计 spring上传文件大小控制 使用Spring进行文件的上传和下载 本文主要介绍在Spring框架下面调用微服务的dubb…

YOLOv9改进策略 | 添加注意力篇 | 利用ILSVRC冠军得主SENetV1改善网络模型特征提取能力

一、本文介绍 本文给大家带来的改进机制是SENet&#xff08;Squeeze-and-Excitation Networks&#xff09;其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型&#xff0c;而是一个可以和现有的任何一个模型相结合的模块(可以看作是一…

项目实践:贪吃蛇

引言 贪吃蛇作为一项经典的游戏&#xff0c;想必大家应该玩过。贪吃蛇所涉及的知识也不是很难&#xff0c;涉及到一些C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。这里我会介绍贪吃蛇的一些思路。以及源代码也会给大家放到文章末尾。 我们最终的…

【Ne4j图数据库入门笔记1】图形数据建模初识

1.1 图形建模指南 图形数据建模是用户将任意域描述为节点的连接图以及与属性和标签关系的过程。Neo4j 图数据模型旨在以 Cypher 查询的形式回答问题&#xff0c;并通过组织图数据库的数据结构来解决业务和技术问题。 1.1.1 图形数据模型介绍 图形数据模型通常被称为对白板友…

【Gradle如何安装配置及使用的教程】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

双链表的实现

我们知道链表其实有很多种&#xff0c;什么带头&#xff0c;什么双向啊&#xff0c;我们今天来介绍双向带头循环链表&#xff0c;了解了这个其他种类的链表就很简单了。冲冲冲&#xff01;&#xff01;&#xff01; 链表的简单分类 链表有很多种&#xff0c;什么带头循环链表&…

tcp-learner 数据包分析 20240420

输入输出&#xff1a; 数据包分析&#xff1a; learner和Adapter建立连接。 Learner让Adapter发送RST Adapter没有从SUT抓到任何回复&#xff0c;于是向learner发送timeout learner给adapter发送reset命令&#xff0c;让SUT重置。 这是第一次初始化&#xff0c;由于Adapter和…

Spring Boot后端与Vue前端融合:构建高效旅游管理系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

【简单讲解下npm常用命令】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

【hackmyVM】whitedoor靶机

文章目录 信息收集1.IP地址2.端口探测nmapftp服务 3.访问主页 漏洞利用1.反弹shell2.尝试提权3.base64解密 提权1.切换用户2.john爆破3.切换Gonzalo用户4.vim提权 信息收集 1.IP地址 ┌─[✗]─[userparrot]─[~] └──╼ $fping -ag 192.168.9.0/24 2> /dev/null192.168…

ZYNQ NVME高速存储之EXT4文件系统

前面文章分析了高速存储的各种方案&#xff0c;目前主流的三种存储方案是&#xff0c;pcie switch高速存储方案&#xff0c;zynq高速存储方案&#xff0c;fpga高速存储方案。虽然三种高速存储方案都可以实现高速存储&#xff0c;但是fpga高速存储方案是最烂的&#xff0c;fpga…

Android Studio 新建Android13 代码提示Build Tools revision XX is corrupted无法编译解决

Android Studio 新建Android13 代码提示Build Tools revision XX is corrupted无法编译解决 文章目录 Android Studio 新建Android13 代码提示Build Tools revision XX is corrupted无法编译解决一、前言二、分析解决1、原因分析2、解决方法 三、其他1、Android13 新项目无法编…

什么是时间序列分析

时间序列分析是现代计量经济学的重要内容&#xff0c;广泛应用于经济、商业、社会问题研究中&#xff0c;在指标预测中具有重要地位&#xff0c;是研究统计指标动态特征和周期特征及相关关系的重要方法。 一、基本概念 经济社会现象随着时间的推移留下运行轨迹&#xff0c;按…

随身WiFi真实测评推荐!格行vs新讯随身wifi对比,公认最好的随身WiFi格行随身wifi有什么优势?

在当前移动网络高度发达的时代&#xff0c;随身 WiFi 已成为人们出差、旅行等场景中不可或缺的工具。格行和新讯是目前比较受欢迎的无线随身wifi。本次评测将对比分析这两款产品的区别&#xff0c;做为随身WiFi推荐第一名的格行随身wifi到底有什么优势呢&#xff1f; 品牌对比&…

[阅读笔记15][Orca]Progressive Learning from Complex Explanation Traces of GPT-4

接下来是微软的Orca这篇论文&#xff0c;23年6月挂到了arxiv上。 目前利用大模型输出来训练小模型的研究都是在模仿&#xff0c;它们倾向于学习大模型的风格而不是它们的推理过程&#xff0c;这导致这些小模型的质量不高。Orca是一个有13B参数的小模型&#xff0c;它可以学习到…

C++ 内存分区管理

一、栈区&#xff08;Stack&#xff09; 栈区用来存储函数的参数值、局部变量的值等数据。栈区是自动分配和释放的&#xff0c;函数执行时会在栈区分配空间&#xff0c;函数执行结束时会自动释放这些空间。栈区的数据是连续分配的&#xff0c;由系统自动管理。 注意事项&…

layui框架实战案例(27):弹出二次验证

HTML容器 <button class"layui-btn layui-btn-sm layui-btn-danger" lay-event"delete"><i class"layui-icon layui-icon-delete"></i>批量删除</button>删除封装函数 function delAll(school_id, school_name) {var lo…