从零开发短视频电商 单元测试(TestNG)

news2024/12/24 2:26:03

文章目录

    • 简介
    • 简单示例
    • 执行测试并查看测试报告
      • 方式一 在IDEA中运行testng.xml文件
      • 方式二 在IDEA中运行测试类或者package
      • 方式三 在Maven中运行测试
    • 统计测试覆盖率
      • 方式一 IDEA 支持详细的代码测试覆盖率统计
      • 方式二 Maven支持测试覆盖率
    • 在IDEA中创建测试用例
      • 使用 IDEA 快速创建单元测试,提高开发和测试效率
    • 常用注解
    • 常用场景
      • 忽略测试
      • 参数化测试
      • 测试组
      • 异常测试
      • 超时测试
      • 多线程测试
    • 重新运行失败的测试
    • 断言
      • 验证两个值是否相等
      • 验证条件是否为真或为假
      • 验证值是否为 null 或非 null
      • 验证是否抛出了预期的异常

简介

官网: https://testng.org/doc/index.html

TestNG是一个基于 Java 的开源测试框架。该框架受到 JUnit 和 NUnit 的启发,但引入了一些新功能,使其更强大且更易于使用。您可以在测试实施期间创建 HTML 报告。它具有分组测试、注释、参数化等功能,有助于更快地创建测试。

TestNG的核心特性

  • 在任意大小的线程池中运行测试,并提供各种可用策略(所有方法都在自己的线程中,每个测试类一个线程等等)。

  • 测试您的代码是否是线程安全的。

  • 灵活的测试配置。

  • 支持数据驱动测试(使用@DataProvider)。

  • 支持参数。

  • 强大的执行模型(不再是TestSuite)。

  • 由多种工具和插件支持(Eclipse、IDEA、Maven 等)。

  • 嵌入 BeanShell 以提高灵活性。

  • 用于运行时和日志记录的默认 JDK 函数(无依赖项)。

  • 应用程序服务器测试的相关方法。

  • 可以进行单元测试,功能测试,端到端测试,集成测试等。

简单示例

1.添加依赖

        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.1.0</version>
            <scope>test</scope>
        </dependency>

TestNG 最高 v7.5: JDK 8 或更高版本。

TestNG v7.6.0 及更高版本: JDK 11 或更高版本。

2.简单测试示例

import org.testng.annotations.*;
 
public class SimpleTest {
 
 @BeforeClass
 public void setUp() {
   // 实例化此测试时将调用的代码
 }
 
 @Test(groups = { "fast" })
 public void aFastTest() {
   System.out.println("Fast test");
 }
 
 @Test(groups = { "slow" })
 public void aSlowTest() {
    System.out.println("Slow test");
 }
 
}
  • 一个测试方法可以属于一个或多个组。

执行测试并查看测试报告

方式一 在IDEA中运行testng.xml文件

这是一个testNG.xml文件

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Suite1" verbose="1">
    <!-- 指定包名-->
    <test name="Regression1">
        <packages>
            <package name="test.sample"/>
        </packages>
    </test>

    <!-- 指定类名称 -->
    <test name="Regression2">
        <classes>
            <class name="test.sample.ParameterSample"/>
            <class name="test.sample.ParameterTest"/>
        </classes>
    </test>

    <!-- 指定要包含和排除的组和方法 -->
    <test name="Regression3">
        <groups>
            <run>
                <exclude name="brokenTests"/>
                <include name="checkinTests"/>
            </run>
        </groups>

        <classes>
            <class name="test.IndividualMethodsTest">
                <methods>
                    <include name="testMethod"/>
                </methods>
            </class>
        </classes>
    </test>

    <!-- 在属性中指定其他详细信息,例如是否并行运行测试、使用多少个线程、是否正在运行 JUnit 测试等 -->
    <test name="Regression4" preserve-order="false" parallel="methods" thread-count="5">
        <classes>
            <class name="test.Test1">
                <methods>
                    <include name="m1"/>
                    <include name="m2"/>
                </methods>
            </class>
            <class name="test.Test2"/>
        </classes>
    </test>

</suite>

在testNG.xml文件上右键运行即可。

方式二 在IDEA中运行测试类或者package

在测试类或者测试的package上右键运行即可。

方式三 在Maven中运行测试

在Maven项目中Maven Surefire Plugin插件是用来执行单元测试的,所以在pom.xml文件中需要添加Maven Surefire Plugin插件,在 configuration 中可以配置需要执行的测试文件。

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <!--<version>3.0.0-M5</version>-->
            <version>${maven-surefire-plugin.version}</version>
            <configuration>
                <trimStackTrace>true</trimStackTrace>
                <includes>
                    <include>**/*Test.java</include>
                    <include>**/*Tests.java</include>
                </includes>
                <excludes>
                    <exclude>**/integration/**</exclude>
                </excludes>
                <parallel>classes</parallel>
                <threadCountMethods>2</threadCountMethods>
                <useSystemClassLoader>false</useSystemClassLoader>
                <forkCount>1</forkCount>
                <reuseForks>true</reuseForks>
                <argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
                <rerunFailingTestsCount>3</rerunFailingTestsCount>
                <testFailureIgnore>true</testFailureIgnore>
                <reportFormat>plain</reportFormat>
                <reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
            </configuration>
        </plugin>
    </plugins>
</build>

在执行完之后,surefire的report默认会存放在target/surefire-reports 文件夹中。

  • <trimStackTrace> 设置为 true,以裁剪堆栈跟踪信息,使其更易读。
  • <parallel> 设置为 classes,以允许并行执行测试类,提高执行速度。
  • <threadCountMethods> 设置为一个适当的线程数,用于并行执行测试方法。
  • <useSystemClassLoader> 设置为 false,以避免使用系统类加载器,减少可能的冲突。
  • <forkCount> 设置为 1,以避免使用多个进程执行测试。
  • <reuseForks> 设置为 true,以重用测试进程,提高执行效率。
  • <argLine> 可以指定额外的 JVM 参数,如堆内存大小、永久代大小等。
  • <rerunFailingTestsCount> 设置为一个适当的值,以在测试失败时重新运行测试。
  • <testFailureIgnore> 设置为 true,以忽略测试失败并继续构建过程。
  • <reportsDirectory> 指定测试报告的输出目录。

Maven也有自己的一些常用命令,我们可以通过Maven命令来执行测试代码。

编译:mvn compile  --src/main/java目录java源码编译生成class (target目录下)
测试:mvn test    --src/test/java 目录编译
清理:mvn clean    --删除target目录,也就是将class文件等删除
打包:mvn package  --生成压缩文件:java项目#jar包;web项目#war包,也是放在target目录下
安装:mvn install   --将压缩文件(jar或者war)上传到本地仓库
部署:mvn deploy     --将压缩文件上传私服

​ 我们可以通过 mvn clean test执行测试用例,整个过程是通过调用pom.xml 中的 Maven Surefire Plugin插件 - > 运行所配置的测试用例。

跳过测试

  • mvn clean package/install -DskipTests

  • mvn clean package/install -Dmaven.test.skip=true

统计测试覆盖率

测试代码覆盖率越高,代码质量越高

方式一 IDEA 支持详细的代码测试覆盖率统计

很简单不介绍了

方式二 Maven支持测试覆盖率

JaCoCo是一个开源的覆盖率工具,它针对的开发语言是java,其使用方法很灵活,可以嵌入到Ant、Maven中,很多第三方的工具提供了对JaCoCo的集成,如sonar、Jenkins等。

JaCoCo包含了多种尺度的覆盖率计数器,包含指令级覆盖(Instructions,C0coverage),分支(Branches,C1coverage)、圈复杂度(CyclomaticComplexity)、行覆盖(Lines)、方法覆盖(non-abstract methods)、类覆盖(classes)

pom.xml添加

   <!-- jacoco: generate test coverage report -->
        <jacoco.version>0.8.8</jacoco.version>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.version}</version>
                <configuration>
                    <includes>
                        <include>com/**/*</include>
                        <include>**/*Test.java</include>
                    </includes>
                    <excludes>
                        <exclude>**/AccountImageUtilTest.java</exclude>
                    </excludes>
                    <skip>false</skip>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>generate-code-coverage-report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

在工程根目录下执行mvn clean test来执行单元测试并生成覆盖率报告,生成后的报告为./target/site/jacoco/index.html,通过浏览器打开该文件,可以看到整体的覆盖率以及单元测试的情况。

在IDEA中创建测试用例

使用 IDEA 快速创建单元测试,提高开发和测试效率

在需要测试的类或接口(推荐基于接口创建)名称上使用 Alt+Enter,然后选择创建测试

常用注解

注解注释
@BeforeSuite被注解的方法,将在整个测试套件之前运行
@AfterSuite被注解的方法,将在整个测试套件之后运行
@BeforeTest被注解的方法,将在测试套件内所有用例执行之前运行
@AfterTest被注解的方法,将在测试套件内所有用例执行之后运行
@BeforeGroups被注解的方法,将在指定组内任意用例执行之前运行
@AfterGroups被注解的方法,将在指定组内任意用例执行之后运行
@BeforeClass带注释的方法将在调用当前类中的第一个测试方法之前运行。
@AfterClass被注解的方法将在当前类中的所有测试方法运行完毕后运行。
@BeforeMethod带注释的方法将在每个测试方法之前运行。
@AfterMethod带注释的方法将在每个测试方法之后运行。
@DataProvider被注解的方法,强制返回一个 二维数组Object[ ][ ]作为另外一个@Test方法的数据工厂
@Factory被注解的方法,作为对象工厂,强制返回一个对象数组 Object[ ]
@Listeners定义一个测试类的监听器
@Parameters定义一组参数,在方法运行期间向方法传递参数的值,参数的值在testng.xml中定义
@Test标记方法为测试方法,如果标记的是类,则此类中所有的public方法都为测试方法

具体生命周期如下图

img

常用场景

忽略测试

有时,你可能需要暂时忽略某些测试方法,以避免执行它们。你可以使用 @Test(enabled = false) 注解来标记需要忽略的测试方法。

import org.testng.annotations.Test;

public class IgnoreTest {

  @Test
  public void testMethod1() {
    // 测试方法1的代码
  }

  @Test(enabled = false)
  public void testMethod2() {
    // 测试方法2的代码
  }
}

testMethod2 被标记为 enabled = false,表示该测试方法将被忽略,不会执行。只有被标记为 enabled = true 或未使用 enabled 属性的测试方法才会被执行。

参数化测试

通过参数化测试,可以使用不同的输入值运行相同的测试方法,以验证代码在不同参数下的行为。

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class ParameterizedTest {

  @DataProvider(name = "additionData")
  public Object[][] additionData() {
    return new Object[][] {
      {2, 3, 5},
      {5, 5, 10},
      {-10, 10, 0}
    };
  }

  @Test(dataProvider = "additionData")
  public void testAddition(int a, int b, int expected) {
    int result = Calculator.add(a, b);
    assertEquals(result, expected);
  }
}

测试组

通过测试组(Test Groups),可以对测试方法进行分类,并选择性地运行特定组的测试。

import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class GroupTest {

  @Test(groups = "smoke")
  public void testLogin() {
    // 测试登录功能
    assertTrue(true);
  }

  @Test(groups = "regression")
  public void testHomePage() {
    // 测试首页功能
    assertTrue(true);
  }

  @Test(groups = "regression")
  public void testProfilePage() {
    // 测试个人资料页面功能
    assertTrue(true);
  }
}

异常测试

在测试中验证代码是否能够正确地抛出预期的异常。

import org.testng.annotations.Test;

public class ExceptionTest {

  @Test(expectedExceptions = ArithmeticException.class)
  public void testDivideByZero() {
    int result = Calculator.divide(10, 0);
  }
}

使用 @Test 注解的 expectedExceptions 属性指定了预期的异常类型。如果在测试方法中执行的代码确实抛出了指定的异常,则测试将被标记为通过。

超时测试

设置测试方法的最大执行时间,以确保代码在规定的时间范围内完成执行。

import org.testng.annotations.Test;

public class TimeoutTest {

  @Test(timeOut = 500)
  public void testLongRunningOperation() throws InterruptedException {
    // 模拟一个长时间运行的操作
    Thread.sleep(1000);
  }
}

使用 @Test 注解的 timeOut 属性指定了最大执行时间(以毫秒为单位)。如果测试方法的执行时间超过指定的时间,测试将被标记为失败。

多线程测试

使用 TestNG,你可以在多个线程中并发地执行测试方法,以模拟并发和并行的场景。可以通过在 @Test 注解中设置 threadPoolSizeinvocationCount 属性来实现。

import org.testng.annotations.Test;

public class MultiThreadTest {

  @Test(threadPoolSize = 5, invocationCount = 10)
  public void testMethod() {
    // 在多个线程中并发执行的测试方法
  }
}

testMethod 使用了 threadPoolSize = 5invocationCount = 10,表示将在一个具有 5 个线程的线程池中并发地执行该测试方法,总共执行 10 次。这样可以模拟并发的场景,并观察测试方法在多线程环境下的行为。

注意:在编写多线程测试时,要确保测试方法是线程安全的,并处理好线程间的同步和共享资源的访问。

重新运行失败的测试

在maven环境执行测试中,每次测试失败时,TestNG 都会在输出目录中创建一个名为testng-failed.xml 的文件。此 XML 文件包含仅重新运行这些失败的方法所需的信息,使您能够快速重现故障,而无需运行整个测试。

\target\surefire-reports\testng-failed.xml

断言

在 TestNG 中,常用的断言方法位于 org.testng.Assert 类中,它提供了一系列用于验证测试结果的断言方法。以下是一些常用的断言方法及其最佳实践的代码示例:

验证两个值是否相等

assertEquals:验证两个值是否相等。

import org.testng.Assert;
import org.testng.annotations.Test;

public class AssertionTest {

  @Test
  public void testAddition() {
    int result = Calculator.add(2, 3);
    Assert.assertEquals(result, 5, "Addition result is incorrect.");
  }
}

在上述示例中,assertEquals 方法用于验证 result 的值是否等于 5。如果断言失败,会抛出 AssertionError,并显示指定的错误消息。

验证条件是否为真或为假

assertTrueassertFalse:验证条件是否为真或为假。

import org.testng.Assert;
import org.testng.annotations.Test;

public class AssertionTest {

  @Test
  public void testIsEvenNumber() {
    int number = 10;
    Assert.assertTrue(number % 2 == 0, "Number is not even.");
  }
}

在上述示例中,assertTrue 方法用于验证 number 是否为偶数。如果条件不满足,断言失败并显示错误消息。

验证值是否为 null 或非 null

assertNullassertNotNull:验证值是否为 null 或非 null。

import org.testng.Assert;
import org.testng.annotations.Test;

public class AssertionTest {

  @Test
  public void testArray() {
    String[] names = {"John", "Jane", "Doe"};
    Assert.assertNotNull(names, "Array is null.");
  }
}

在上述示例中,assertNotNull 方法用于验证 names 数组是否为非 null。如果数组为 null,断言失败并显示错误消息。

验证是否抛出了预期的异常

assertThrows:验证是否抛出了预期的异常。

import org.testng.Assert;
import org.testng.annotations.Test;

public class AssertionTest {

  @Test
  public void testDivideByZero() {
    Assert.assertThrows(ArithmeticException.class, () -> Calculator.divide(10, 0));
  }
}

在上述示例中,assertThrows 方法用于验证 Calculator.divide(10, 0) 是否抛出了 ArithmeticException 异常。如果没有抛出预期的异常,断言失败。

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

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

相关文章

LLaMA微调记录

本文基于开源代码https://github.com/Lightning-AI/lit-llama/tree/main执行微调 其他参考链接&#xff1a; Accelerating LLaMA with Fabric: A Comprehensive Guide to Training and Fine-Tuning LLaMA - Lightning AI 结构化数据示例&#xff1a; BelleGroup/train_0.5M_…

动态sql语句

1.1 动态sql语句概述 Mybatis 的映射文件中&#xff0c;业务逻辑复杂时&#xff0c; SQL是动态变化的&#xff0c;此时在前面的学习中 SQL 就不能满足要求了。 参考的官方文档&#xff1a; 1.2 动态 SQL 之<if> 根据实体类的不同取值&#xff0c;使用不同的 SQL语句…

常见安装工具以及命令(工作常用)长期维护

dockermongodbnginxredis 1.docker 启动2.docker 安装 MongoDB3.启动nginx4.redis配置&#xff0b;安装4.1 Redis的启动和停止4.2 后台启动方式 systemctl start docker redis-server /root/myredis/redis.conf docker start mymongo docker exec -it mymongo /bin/bash 1.doc…

代码随想录算法训练营第58天 | 单调栈 ●739 每日温度 ●496下一个更大元素I ●503下一个更大元素II ●42 接雨水 ●84 柱形图中最大的矩形

#单调栈&#xff1a; 单调栈就是保持栈内元素有序。和栈与队列&#xff08;239. 滑动窗口最大值 自己写一个class来实现单调队列&#xff09;一样&#xff0c;需要我们自己维持顺序&#xff0c;没有现成的容器可以用。 通常是一维数组&#xff0c;要寻找任一个元素的右边或者…

浅谈物联网工程专业:技术融合与未来发展

技术融合与未来发展 引言1. 专业的定义与概述2. 专业的知识体系3. 专业的实践应用4. 专业的发展趋势5. 专业的就业前景结语&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收…

zabbix 企业级级监控(1) 监控自己

重点一 Zabbix简介在企业网络运维过程中&#xff0c;管理员必须随时关注各服务器和网络的运行状况&#xff0c;以便及时发现问题&#xff0c;尽可能减少故障的发生。当网络中的设备&#xff0c;服务器等数量较多时&#xff0c;为了更加方便&#xff0c;快捷的获得监控信息&…

【软件测试面试】腾讯数据平台笔试题-接口-自动化-数据库

数据库题 答案&#xff1a; Python编程题 答案&#xff1a; 接口参数化题 答案&#xff1a; 接口自动化题 答案&#xff1a; 以下是我收集到的比较好的学习教程资源&#xff0c;虽然不是什么很值钱的东西&#xff0c;如果你刚好需要&#xff0c;可以评论区&#…

6.3.6 利用Wireshark进行协议分析(六)----网页提取过程的协议分析

6.3.6 利用Wireshark进行协议分析&#xff08;六&#xff09;----网页提取过程的协议分析 利用Wireshark捕获网页访问过程中产生的应用协议报文&#xff0c;还原Web服务中报文的交互过程&#xff0c;为了防止网页直接从本地缓存中获取&#xff0c;我们首先需要清空浏览器保存的…

GO语言GMP模型

目录 程序入口 协程主动让出: 被动让出: schedule 监控线程 程序入口 在执行一系列检查和初始化&#xff08;创建多少个P&#xff0c;与M&#xff10;关联&#xff09;后&#xff0c;进入runtime.main,创建main goroutine,执行mian.mian。 一开始GO语言的调度只有M和G。每个M…

【代码随想录 | Leetcode | 第七天】链表 | 链表相交 | 环形链表 II

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来链表相交和环形链表 II的分享✨ 目录 前言面试题 02.07. 链表相交142. 环形链表 II总结 面试题 02.07. 链表相交 ✨题目链接点这里 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找…

C/C++ new A与new A()的区别

在C中&#xff0c;POD是“Plain Old Data”的缩写&#xff0c;即“普通旧数据”。POD data是指一种特殊类型的数据结构&#xff0c;它们具有简单的内存布局&#xff0c;没有构造函数、虚函数、私有/保护非静态数据成员&#xff0c;也没有虚继承等特性。这些数据结构可以直接通过…

k8s与集群管理

从docker讲起 终于有人把 Docker 讲清楚了&#xff0c;万字详解&#xff01; Docker资源&#xff08;CPU/内存/磁盘IO/GPU&#xff09;限制与分配指南 默认情况下&#xff0c;Docker容器是没有资源限制的&#xff0c;它会尽可能地使用宿主机能够分配给它的资源。如果不对容器资…

C++--day3(内联函数、结构体、类、封装、this、构造函数、析构函数)

#include <iostream>using namespace std;class My_stack { private:int *ptr; //指向堆区空间int top; //记录栈顶元素int size; public://有参构造My_stack(int size):ptr(new int[size]),top(-1){this->sizesize;cout<<"My_stack::有参构造&…

基于STM32的智能喂养系统

基于STM32的智能喂养系统 系统简介 自动检测环境温湿度&#xff0c;当温湿度低于阈值时自动打开加湿器&#xff1b;自动检测水位&#xff0c;当水位低于阈值时自动加水&#xff1b;自动检测有害气体&#xff0c;当检测到有害气体时自动打开风扇&#xff1b;同步状态到微信小程…

中间件上云部署 zookeeper

中间件上云部署 zookeeper 企业级中间件上云部署 zookeeper一、环境说明二、zookeeper部署YAML资源清单准备三、zookeeper部署及部署验证四、zookeeper应用验证 企业级中间件上云部署 zookeeper 一、环境说明 storageclassingress 二、zookeeper部署YAML资源清单准备 # vim…

图解java.util.concurrent并发包源码系列,原子类、CAS、AtomicLong、AtomicStampedReference一套带走

图解java.util.concurrent并发包源码系列&#xff0c;原子类、CAS、AtomicLong、AtomicStampedReference一套带走 原子类为什么要使用原子类CAS AtomicLong源码解析AtomicLong的问题ABA问题AtomicStampedReference 高并发情况下大量的CAS失败&#xff0c;导致CPU空转 往期文章&…

百度智能汽车负责人储瑞松离职,智驾重心转向ANP3

作者 | 王博 HiEV从多个信息源获悉&#xff0c;百度集团副总裁、百度智能汽车事业部总经理储瑞松将从百度离职。一位知情人士透露&#xff0c;储瑞松「即将启程&#xff0c;返回美国」。 继百度Apollo技术骨干郭阳离职后&#xff0c;储瑞松的变动&#xff0c;更加直白地反映出百…

电动汽车高压测试方案

针对电动汽车道路试验的要求&#xff0c;风丘科技携手德国IPETRONIK共同推出了电动汽车高压测试方案。电动汽车测试通常有两种测量手段&#xff1a;第一种是测量模拟量信号&#xff0c;包括电压、电流、温度和高压&#xff1b;第二种是使用数据记录仪或CAN卡从车辆总线读取数据…

你一定要收好这个系统性能测试用例模板

引言 文档目的 [简述本文档的目的] 适用范围 [指明本文档的适用范围和读者对象。如本测试计划是在策略和方法的高度说明如何计划、组织和管理测试项目。测试计划应包含足够的信息&#xff0c;使测试人员明白项目需要做什么、是如何运作的。另外&#xff0c;测试计划只是测试的…

刚体运动学-速度和加速度的表示方法(连体坐标系和世界坐标系)

0. 符号定义 自己画了一个图 下标 b b b是连体坐标系原点 O b O_b Ob​相对世界坐标系原点 O p O_p Op​的矢量在世界坐标系下的表示。下标 p p p是观察点相对世界坐标系原点 O p O_p Op​的矢量在世界坐标系下的表示。下标 p / b p/b p/b是观察点相对连体坐标系原点 O b O_b…