最佳实践:通义灵码生成单元测试,让单测更简单

本文涉及的产品
云效 DevOps 流水线,基础版人数 不受限
云效 DevOps 代码管理,基础版人数 不受限
云效 DevOps 制品仓库,基础版人数 不受限
简介: 本文首先讲述了什么是单元测试、单元测试的价值、一个好的单元测试所具备的原则,进而引入如何去编写一个好的单元测试,通义灵码是如何快速生成单元测试的。

作者:虎仔

本文首先讲述了什么是单元测试、单元测试的价值、一个好的单元测试所具备的原则,进而引入如何去编写一个好的单元测试,通义灵码是如何快速生成单元测试的。


什么是单元测试?


单元测试是一种软件测试方法,通过编写代码来验证应用程序中最小的可测试单元(如单个函数、方法或类)的正确性。通常,单元测试由开发人员在功能实现过程中或完成后编写,其目的是确保每个最小可测试单元都能按照设计预期正常工作。


单元测试的价值


单元测试的价值主要体现在提高软件质量和可靠性,‌确保代码在修改或重构后仍然能够正常运行。‌单元测试的优势包括:


  • 提高代码质量:‌通过发现代码中的错误和漏洞,‌从而提高代码的质量和可靠性。‌
  • 提高开发效率:‌在开发过程中及时发现问题,‌减少开发周期和成本。‌
  • 便于重构和维护:‌确保代码在重构和维护过程中不会出现新的错误和漏洞。‌
  • 有助于团队协作:‌作为团队成员之间的沟通和协作工具,‌提高团队的协作效率和质量。‌


此外,‌单元测试还可以让软件故障尽早被发现,‌避免故障遗留到后期由于定位修复难度带来的更大损失。‌它的可回归性为软件提供了一层安全防护网,‌为软件后续的重构和修改提供了安全保障。‌单元测试还为软件单元如何被使用提供了天然的代码样例使用手册。


遵循的原则


好的单元测试就像空气(AIR)一样感觉不到,但在测试质量的保障上,却是非常关键的。好的单元测试宏观上来说,具有自动化(A)、独立性(I)、可重复执行(R)的特点。


  • A: Automatic(自动化):单元测试应能被自动化执行,以便在代码更改时快速确认新加入的代码没有破坏已有功能,通常情况下会将单测接入到持续集成中,每当代码有变更时都会通过持续集成自动触发单元测试。
  • I: Independent(独立性):每个单元测试应当是独立的,不能依赖于其他测试的执行顺序或结果。这也要求单测的测试颗粒度必须足够小,只有这样才能满足独立性。
  • R: Repeatable(可重复执行):好的单元测试在同样的条件下,每次运行应当给出相同的结果。它不应依赖于外部因素(如网络、数据库或文件系统),需要对这些外部的依赖进行正确的 mock。


除此之外,好的单测还必须要满足有明确的断言,执行速度快,边界测试充分,覆盖率高等特点。只有满足这些条件的单测才是好的单测,好的单元测试是对代码质量保障至关重要的一环。


如何编写单元测试?


下面以 Java 语言为例来介绍如何编写单元测试,总体遵循以下几个步骤:


拆分详细的测试用例

考虑分支条件:

在编写单元测试时,需要考虑代码中的所有分支。分支包括 if、else、switch 语句等,每个分支都需要单独测试。例如:


public String classifyNumber(int number) {
    if (number < 0) {
        return "negative";
    } else if (number == 0) {
        return "zero";
    } else {
        return "positive";
    }
}


在上述代码中,有三个分支需要测试:


  • number<0。
  • number==0。
  • number>0。


针对每个分支,都需要编写一个测试用例。


寻找边界条件:

除了分支,还需要考虑边界条件。例如,对于上述分类函数,边界值是 -1、0 和 1。边界条件测试可以找出可能潜在的问题,确保代码在极限条件下也能正常工作。


制定统一的单测规范

命名规范:

单元测试类通常采用类名 Test 的形式。例如,如果要测试一个 Calculator 类,则单元测试类可以命名为 CalculatorTest。单元测试方法的命名应当描述具体要测试的内容。例如:


public class CalculatorTest {
    @Test
    public void testAddition() {
        // 测试内容
    }
    @Test
    public void testSubtraction() {
        // 测试内容
    }
}

存放路径:

一般情况下,单元测试类存放的位置在与被测试类相同包名的下面,但在不同的目录中。在标准的 Maven 项目结构中,源代码放在 src/main/java,单元测试代码放在 src/test/java。


src/main/java/com/example/Calculator.java
src/test/java/com/example/CalculatorTest.java


选择合适的单测框架

Java 常用的单元测试框架有 JUnit 和 Mockito,下面将围绕如何使用这两种框架编写基本的单元测试。


JUnit 测试框架:

JUnit 是 Java 语言中最著名的单元测试框架。它简洁易用,提供了丰富的注解和断言。


1. 添加 JUnit 依赖(以 Maven 为例):


<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.13.2</version>
  <scope>test</scope>
</dependency>


2. 编写单元测试:


import org.junit.Test;
import static org.junit.Assert.*;

public class CalculatorTest {
    @Test
    public void testAddition() {
        Calculator calculator = new Calculator();
        assertEquals(5, calculator.add(2, 3));
    }
}


Mockito 测试框架:

Mockito 是一个强大的模拟框架,用于创建虚拟对象,简化单元测试,特别是在测试不易创建的依赖对象时非常有用。


1. 添加 Mockito 依赖:


<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>3.11.2</version>
  <scope>test</scope>
</dependency>


2. 编写单元测试:


import static org.mockito.Mockito.*;
import org.junit.Test;

public class UserServiceTest {
    @Test
    public void testGetUser() {
        UserService userService = new UserService();
        UserRepository mockRepo = mock(UserRepository.class);

        when(mockRepo.findUserById(1)).thenReturn(new User(1, "John Doe"));
        userService.setUserRepository(mockRepo);

        User user = userService.getUserById(1);
        assertNotNull(user);
        assertEquals("John Doe", user.getName());
    }
}


如何使用通义灵码快速生成单测


在大多数开发者的编程习惯中,通常采用 Test Later 的方法进行单元测试,即首先编写好代码,然后再为代码编写相应的单元测试。在此背景下,利用通义灵码生成单元测试显得尤为便捷。以下列举几种使用通义灵码生成单元测试的方式。


手工选中代码方式生成

在 IDE 编辑区中,通过通义灵码选中某段代码来生成单测,选中代码后,在灵码的问答框内,通过 /generate unit test 来生成与选中的代码对应的单元测试。

image.png

说明:使用 /generate unit test 这个命令时,可以在输入框追加更多的信息,来生成更符合开发者需要的测试用例,如需要支持 JUnit5 或采用 Mockito 进行 Mock,就可以采用 /generate unit testJUnit5Mockito 这样的方式,后面两个关键词被当作前面命令的参数,这样的使用方式,同样适用于其他命令。


使用快捷按钮方式生成

通义灵码插件在每个方法签名的上面都会有一个小图标,单击图标后会弹出相应的命令菜单,选择生成单元测试。

image.png

也可以选择要生成的代码块,然后单击右键来选择生成单元测试功能。

image.png


采纳单元测试

单测代码生成完毕后,在问答区的代码块右上角,会有三个选项,分别是插入代码,复制和新建文件:


  • 插入代码:会将当前生成的单测代码插入到当前打开的文件中。
  • 复制:即复制代码块的代码,由用户自行选择将代码复制到哪个文件中。
  • 新建文件:会按照 Java 单测的规范,新生成一个单测类文件,放到指定的目录中(对应单测方法文件所在的 test 目录下),如果已经存在同名的单测文件,需要用户自主确认是否覆盖原文件。

image.png


单测生成追问

如果用户对当前生成的单测代码不满意(需要使用特定的单测框架或者生成更多的单测方法),只需在问答区中的输入框输入相应的文本进行追问即可,或者也可以单击预置的单测追问 Tag,如示例中追问的 Tag :RetryUse MockitoUse Spring TestExplain code,进行追问,直到生成用户满意的单测代码为止。

image.png

说明:一般根据代码生成的单元测试,会枚举常用的测试用例,并不会遍历所有的用例。如果用户觉得生成的用例不足,建议先采纳当前生成的几个用例,放到测试文件当中。然后,切换到测试文件中,采用代码续写的方式,通义灵码会帮助用户续写新的测试用例。


结语


单元测试是重要的编程实践,为编码过程搭建质量围栏。同时,采用测试驱动开发实践中的 Test First ,能够显著推动代码设计的演变。通义灵码,可以极大降低单元测试框架的搭建和测试用例编写的工作量。同时,使用通义灵码对单元测试用例保鲜,可以显著提升编码质量。


更多活动推荐


1)通义灵码一周年:灵码新功能有奖测评火热开启!参与有机会获得机械键盘、华为手环等精美好礼:https://developer.aliyun.com/topic/lingma-one-year

image.png

2)手把手带你体验通义灵码企业 RAG,让问答和代码补全更贴合企业规范和业务特点。赢通义灵码超大鼠标垫 1000 份,领完为止:https://developer.aliyun.com/topic/lingma/202409


点击此处,下载使用通义灵码!

相关实践学习
2分钟自动化部署人生模拟器
本场景将带你借助云效流水线Flow实现人生模拟器小游戏的自动化部署
SVN版本控制系统
SVN是现在软件开发之中的主流软件版本控制工具,在工作之中利用SVN可以有效的解决多人开发的代码管理问题,本课程将为读者讲解SVN服务器的配置以及基于MyEclipse的SVN客户端插件的配置与使用,并且在讲解之中着重讲解了冲突的产生于解决。
相关文章
|
6天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
8天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1563 10
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
11天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
738 27
|
8天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
226 3
|
15天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
788 5
|
2天前
|
Python
【10月更文挑战第10天】「Mac上学Python 19」小学奥数篇5 - 圆和矩形的面积计算
本篇将通过 Python 和 Cangjie 双语解决简单的几何问题:计算圆的面积和矩形的面积。通过这道题,学生将掌握如何使用公式解决几何问题,并学会用编程实现数学公式。
109 60
|
1天前
|
人工智能
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
115 1
|
3天前
|
Java 开发者
【编程进阶知识】《Java 文件复制魔法:FileReader/FileWriter 的奇妙之旅》
本文深入探讨了如何使用 Java 中的 FileReader 和 FileWriter 进行文件复制操作,包括按字符和字符数组复制。通过详细讲解、代码示例和流程图,帮助读者掌握这一重要技能,提升 Java 编程能力。适合初学者和进阶开发者阅读。
104 61
|
14天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】