【测试开发篇9】Junit框架

news2024/12/29 14:07:45

目录

一、认识Junit框架

Junit和Selenium的关系是什么

导入Junit框架+common-io包

二、Junit框架的使用

2.1Junit有哪些常用注解

2.1.1@Test注解

2.1.2BeforeEach

2.1.3@BeforeAll

2.1.4@AfterAll

2.1.5@AfterEach

2.2Junit的断言

Assertions.assertEquals(期待值,真实值);

2.2.1Assertions.assertNotEquals("百度一下",text)

2.2.2Assertions.assertTrue(text.equals("百度一下"))

2.2.3Assertions.assertNull(a);

三、用例的执行顺序

①针对方法的排序

为什么需要用到juit的排序功能

四、测试套件(Suit)

@Suite

@SelectClasses({待测试的类.class})

@SelectPackages("包名")

五、参数化

5.1@ParameterizedTest、@ValueSource(strings = {})

5.2@CsvSource(value={"第一组数据","第二组数据"})

 如果参数当中包含逗号:",",就需要使用单引号转义字符串

5.3读取文件参数:@CsvFileSource(resources="/文件名称")

 5.3.1读取其他磁盘文件的操作:指定文件为files=...

5.4动态参数(单参数版本)

5.5动态参数(多参数版本)

六、对于重要测试场景的截图

第一步:定位到需要的页面

第二步:调用getSrceenshotAs方法,传入的擦参数是OutputTpye.FILE;

第三步:新建一个File类,指定路径;

第四步:调用copyFile方法,把生成的文件放到指定的目录当中


一、认识Junit框架

Junit是一个开源的Java语言的单元测试框架

回顾一下,单元测试就是在编码阶段,一般情况下,由开发进行的测试。

Junit和Selenium的关系是什么

      Junit是单元测试框架,而selenium是web自动化测试框架。如果把selenium比作灯泡,那么junit就是电灯。因此:一般情况下,junit负责运行selenium脚本编写的代码。


导入Junit框架+common-io包

<dependency>
               <groupId>commons-io</groupId>
               <artifactId>commons-io</artifactId>
               <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

二、Junit框架的使用

2.1Junit有哪些常用注解

2.1.1@Test注解

       这一个注解作用于方法上面,表示这个方法是一个测试用例。当@Test注解作用在一个方法上面的时候,表示这一个方法是可以直接运行的,无需通过main方法来调用


2.1.2BeforeEach

在执行每一个被@Test修饰的方法之前,都会执行一次@BeforeEach注释的方法。

@BeforeEach
    void aaa(){
        System.out.println("pre");
    }

    @Test
    void bbb(){
        System.out.println("bbb");
    }

    @Test
    void ccc(){
        System.out.println("ccc");
    }

 每执行一个@Test之前,就需要执行一次@BeforeEach注释的方法

运行类上面的运行按钮:


2.1.3@BeforeAll

       首先,被@BeforeAll注释的方法一定是静态的。

       其次,不同于@BeforeEach的是,@BeforeAll注释的方法一定是静态的,并且只会在加载外部类的时候执行一次,并不会在每一个方法执行之前再次执行了。

public class Test1 {



    @BeforeAll
    static void aaa(){
        System.out.println("pre");
    }

    @Test
    void bbb(){
        System.out.println("bbb");
    }

    @Test
    void ccc(){
        System.out.println("ccc");
    }
}


2.1.4@AfterAll

被这个注解修饰的方法也必须是静态的,在每一个@Test之后进行修饰。

public class Test1 {
    @BeforeAll
    static void aaa(){
        System.out.println("pre");
    }

    @Test
    void bbb(){
        System.out.println("bbb");
    }

    @Test
    void ccc(){
        System.out.println("ccc");
    }

    @AfterAll
    static void afterAll(){
        System.out.println("end...");
    }
}

运行结果:


2.1.5@AfterEach

同理,在每一个@Test注释的方法执行结束的末尾,都会执行一次@AfterEach注释的方法。

public class Test1 {
    @BeforeEach
    void aaa(){
        System.out.println("pre");
    }

    @Test
    void bbb(){
        System.out.println("bbb");
    }

    @Test
    void ccc(){
        System.out.println("ccc");
    }

    @AfterEach
    void afterAll(){
        System.out.println("end...");
    }
}

运行结果:


2.2Junit的断言

写自动化测试,结果要么是成功的,要么是失败的,不存在成功一半的情况。

那么就需要使用到断言:assert,断言预期结果真实结果是否一致。

Assertions.assertEquals(期待值,真实值);

期待值真实值一致的时候,这个断言才不会抛出异常

期待值真实值不一致的时候,就会抛出异常;


代码实现:

public class Test2 {

    FirefoxDriver driver;
    @BeforeEach
    public void get(){
        driver=new FirefoxDriver();
        //捕捉到这一个页面
        driver.get("https://www.baidu.com");
    }

    @Test
    public void testOne(){
        //尝试获取"百度一下"的文本框
        String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");
        //使用AssertEquals来进行断言
        Assertions.assertEquals("百度一下",text);
    }

    @AfterEach
    public void after(){
        driver.quit();
    }
}

如果运行的结果一致,那么就提示测试用例通过:


2.2.1Assertions.assertNotEquals("百度一下",text)

与Assertions.assertEquals(期待值,真实值)相反。

只有不一致的时候,测试用例才会通过。


2.2.2Assertions.assertTrue(text.equals("百度一下"))

传入的参数应该是一个返回值为boolean类型的表达式

@Test
public void assertTrueTest(){
        String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");
        //如果返回true,那么测试用例通过,否则测试用例不通过
        Assertions.assertTrue(text.equals("百度一下"));
   }

同理,还有AssertFalse 


2.2.3Assertions.assertNull(a);

 @Test
    public void assertNull(){
        String a=null;
        Assertions.assertNull(a);
    }

如果一个引用为null,那么默认测试用例通过。

同理,还有Assertions.assertNotNull(),那么一个引用不为null的时候,测试用例才通过。


三、用例的执行顺序

①针对方法的排序

第一步:在这个类上面添加注解:@TestMethodOrder(MethodOrderer.OrderAnnotation.class)


第二步:

使用@Order(执行顺序)作用在方法上面,表示是第几个执行;


@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Test2 {

    FirefoxDriver driver;
    @BeforeEach
    @Order(1)
    public void get(){
        driver=new FirefoxDriver();
        //捕捉到这一个页面
        driver.get("https://www.baidu.com");
    }

    @Test
    @Order(2)
    public void testOne(){
        //尝试获取"百度一下"的文本框
        String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");
        Assertions.assertNotEquals("百度一下",text);
    }

    @Test
    @Order(3)
    public void assertTrueTest(){
        String text=driver.findElement(By.cssSelector("#su")).getAttribute("value");
        //如果返回true,那么测试用例通过,否则测试用例不通过
        Assertions.assertTrue(text.equals("百度一下"));
    }

    @AfterEach
    public void after(){
        driver.quit();
    }
}

为什么需要用到juit的排序功能

       如果用例之间存在关联关系(存在耦合)(但是不是绝对有关联关系),那么就需要手动指定用例的执行顺序。因为各个测试用例的执行顺序是无序的。

       这样就可以避免出现各个测试用例之间执行顺序不正确的情况。


四、测试套件(Suit)

测试套件,用于把所有的测试用例都执行起来。

@Suite

这一个注解作用于类上面,用于执行所有的测试用例


@SelectClasses({待测试的类.class})

这个注解和上面的注解需要配合使用,这样才可以一起执行待测试类的测试用例。

当然也可以传递多个.class对象。


@Suite
@SelectClasses({Test1.class,Test2.class})
public class SuitTest {

}

运行结果:


@SelectPackages("包名")

扫描这一个包下面包含了@Test注解的方法的类

@Suite
@SelectPackages("TestFile")
public class SuitTest {

}

但是扫描的包不可以和当前的类在同一个包下面;

需要注意的是,这种情况下面,被扫描的类一定是xxxTest这样命名的,否则是扫描不到的。


五、参数化

对于一个测试用例,可能会测试传入的参数是多种的情况;

例如对于一个文本框进行测试,可以测试多种输入的情况

如下图:如果为每一个输入的name都定义一个方法,那么就显得非常冗余,于是就引入了参数化。


5.1@ParameterizedTest、@ValueSource(strings = {})

第一个注解@Parameterized作用在方法上面,用来表示这个方法支持传入多个参数;

第二个注解@ValueSource用于指定传入参数的类型;例如:strings={}就表示传入的是一个string类型的数组;

ints={2,3,4,5}表示传入的参数是一个int类型的数组;

但是,同一个@ValueSource注解当中只支持一种数据类型

运行结果:


5.2@CsvSource(value={"第一组数据","第二组数据"})

其中,每一组数据当中对应方法传入的参数的值。采用","来分割。 

@ParameterizedTest
    @CsvSource(value = {"小明,20","小红,30","小李,40"})
    public void printStringAndInteger(String name,int age){
        System.out.println("name:"+name+";age="+age);
    }


当然,一组数据当中的分隔符也不一定采用系统默认的","分割,也可以采用自定义的分隔符。

@ParameterizedTest
    @CsvSource(value = {"小明-20","小红-20","小李-40"},delimiter = '-')
    public void printStringAndAge(String name,int age){
        System.out.println("name:"+name+";age="+age);
    }

用户自定义的分隔符: 


 如果参数当中包含逗号:",",就需要使用单引号转义字符串


5.3读取文件参数:@CsvFileSource(resources="/文件名称")

第一步:在resources目录下面新建一个文件,并且指定名称;

第二步:在文件当中以逗号的方式分割每一组参数;

然后运行程序:


 5.3.1读取其他磁盘文件的操作:指定文件为files=...

    @ParameterizedTest

    @CsvFileSource(files = "E:\\OJSystem\\src\\main\\resources\\my.csv")
    public void printStringAndAge3(String name,int age){
        System.out.println("name:"+name+";age="+age);
    }

5.4动态参数(单参数版本)

第一步:定义提供数据的方法,必须声明为静态;返回值为一个Stream对象;方法内部调用Stream.of(参数列表);

第二步:定义dyNatickTest(String x)方法获取参数;并用@MethodSource()指定

第三步:输出参数。

@ParameterizedTest
    @MethodSource("methodDemo")
    void dyNatickTest(String x){
        System.out.println(x);
    }

    static Stream<String> methodDemo(){
        return Stream.of("张三","李四","王五");
    }

如果@MethodSource当中不指定参数的名称,那么就会调用跟测试用例同名的静态方法


5.5动态参数(多参数版本)

第一步:新建一个测试方法,并且指定多个参数。使用@ParameterizedTest和@MethodSource注解同时作用

第二步:新建一个和测试用例同名的静态方法;

第三步:在静态方法当中调用Stream.of()方法,并且传入的参数为多个Arguments.arguments(第一步创建方法的参数列表)


 代码实现:

@ParameterizedTest
    @MethodSource
    void paramsTest(String name,int age){
        System.out.println("name:"+name+";age :"+age);
    }

    /**
     * 多参数的版本
     * Stream对象@return
     */
    static Stream<Arguments> paramsTest(){
        return Stream.of(Arguments.arguments("lucy",29),Arguments.arguments("lili",30)
        ,Arguments.arguments("lisi",40));
    }

六、对于重要测试场景的截图

第一步:定位到需要的页面

第二步:调用getSrceenshotAs方法,传入的擦参数是OutputTpye.FILE;

第三步:新建一个File类,指定路径;

第四步:调用copyFile方法,把生成的文件放到指定的目录当中

@Test
    public void screenShortTest() throws IOException, InterruptedException {
        //百度搜索关键字
        driver.findElement(By.cssSelector("#kw")).sendKeys("selenium");
        driver.findElement(By.cssSelector("#su")).click();
        //屏幕截图,把截图的文件存放到指定的位置
        //以文件的形式存储
        File srcFile=driver.getScreenshotAs(OutputType.FILE);
        //把截图的文件存放到指定的目录下面
        File destFile=new File("E:/OJSystem/src/test/Files/img.png");
        Thread.sleep(1000);
        FileUtils.copyFile(srcFile,destFile);
    }

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

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

相关文章

小白推荐|使用git建立自己的代码仓库

1 git 1.1 什么是git 版本控制工具&#xff0c;用于团队协作与项目管理 1.2 git 安装教程 step1&#xff1a;进入git下载官网Git for Windows step2&#xff1a;点击Download step3&#xff1a;打开下载好的文件&#xff0c;按照下面图片一步一步安装 剩下的一直点Next就完…

ansible-playbook task 指定位置执行

文章目录执行顺序指定执行--tags–start-at--skip-tags--step混合执行顺序 1.检查play中是否存在pre_tasks定义&#xff0c;存在的话则顺序执行pre_tasks中定义的所有tasks 2.如果存在pre_tasks定义&#xff0c;则检查是否存在触发handler&#xff0c;如存在则顺序执行相关触发…

Java中的锁是什么意思,有哪些分类?

Java锁&#xff08;Java Locks&#xff09;是Java编程语言中用于实现多线程同步和互斥的机制。在并发编程中&#xff0c;多线程同时访问共享资源可能导致竞态条件&#xff08;Race Condition&#xff09;和其他并发问题&#xff0c;Java锁提供了一种控制多线程并发访问的方式&a…

FluxMQ—物联网高性能MQTT网关

FluxMQ—物联网高性能MQTT网关 随着物联网技术的快速发展&#xff0c;人们越来越意识到实时、可靠、安全的数据传输对于智能化的生产与生活的重要性。因此&#xff0c;市场对于高性能的物联网数据传输解决方案有着强烈的需求。FluxMQ正是为满足这一需求而诞生的一款高性能、可…

Adobe 观察 |最低工资标准来了,学会这几招,让加薪更简单

最新调整后的全国各地区最低工资标准情况来了&#xff01; 人力资源和社会保障部新发布的数据显示&#xff0c;截至今年4月1日&#xff0c;共有15个地区第一档月最低工资标准在2000元及以上&#xff0c;分别是上海&#xff08;2590元&#xff09;、深圳&#xff08;2360元&…

Pandas 2.0发布——更快的速度更低的内存占用

【重磅】Pandas 2.0发布&#xff01;更快的速度更低的内存占用&#xff01; Pandas 是一个用于操作数据的 Python 库&#xff0c;在 Python 开发人员中非常流行。尤其在数据科学和机器学习领域中&#xff0c;Pandas已经成为不可或缺的基础库。 4月3日&#xff0c;Pandas 2.0正…

ESLint 与 Prettier 配合解决代码格式问题

可以了解下Prettier&#xff0c;官网&#xff1a;Prettier 中文网 Prettier 是一个“有态度”的代码格式化工具 Prettier常见的一些配置&#xff1a; tabWidth&#xff1a;指定缩进宽度&#xff0c;默认为 2&#xff0c;建议设置为 4&#xff1b;printWidth&#xff1a;指定代…

MyBatis核心配置文件详解

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><environments default"…

页面布局基础知识

一、布局方案 1、什么是静态布局 概念 静态布局&#xff0c;也称为固定布局&#xff0c;是一种传统网页设计。页面布局使用绝对长度单位&#xff0c;采用固定宽度。忽略浏览器实际&#xff0c;网页布局始终按照最初写代码时的布局来显示。 优点&#xff1a;简单 缺点&#xf…

可视化图表组件体系的构建(内附全套开源文件)

Part01————————前言 EasyV作为一个低代码数字孪生可视化搭建平台&#xff0c;其图表组件作为可视化项目建设的基础构成发挥着重要的作用。 经过多年可视化项目交付经验&#xff0c;沉淀了一套形态多样、样式精细、高配置度的数据可视化图表。 Figma开源文件社区获取入…

【MySQL | 进阶篇】05、MySQL 视图、触发器讲解

目录 一、视图 1.1 介绍 1.2 语法 1.2.1 演示示例 1.3 检查选项 1.3.1 CASCADED 级联 1.3.2 LOCAL 本地 1.3.3 示例演示 1.4 视图的更新 1.4.1 示例演示 1.5 视图作用 1.6 案例 二、触发器 2.1 介绍 2.2 语法 2.3 案例 2.3.1 插入数据触发器 2.3.2 修改数据…

国内版 ChatGPT值不值得上手----PlumGPT测评

前言&#xff1a;什么是PlumGPT&#xff08;国内版的chatgpt&#xff09;&#xff0c;PlumGPT国内版ChatGPT是一个基于GPT-3.5算法的人工智能聊天机器人&#xff0c;能够通过自然语言与用户交互&#xff0c;提供各种服务和解答各种问题。本文将对PlumGPT国内版ChatGPT进行全面测…

NetSuite GPT的辅助编程实践

作为GPT综合症的一种表现&#xff0c;我们今朝来探究下GPT会不会抢了我们SuiteScript的编程饭碗&#xff0c;以及如何与之相处。以下内容来自我个人的实践总结。 我们假设一个功能场景&#xff1a; 为了让用户能够在报价单上实现“一键多行”功能&#xff0c;也就是在报价中可…

【精华】AIGC之文生视频及实践应用

AIGC之文生视频及实践应用 &#xff08;一&#xff09;序言 从 Stable Diffusion 到 Midjourney&#xff0c;再到 DALLE-2&#xff0c;文生图模型已经变得非常流行&#xff0c;并被更广泛的受众使用。随着对多模态模型的不断拓展以及生成式 AI 的研究&#xff0c;业内近期的工…

78-Linux_tcp服务器客户端编程流程

tcp服务器客户端编程流程一.c/s模型1.什么是c/s模型?2.c/s模型的逻辑二.TCP服务器端和TCP客户端的工作流程1.流程2.TCP三次握手3.TCP四次挥手一.c/s模型 1.什么是c/s模型? 答:(c/s)模型即(客户端/服务器端)模型 所有的客户都通过服务器端访问所需资源. 模型如图所示: 2.c…

Python样条插值和坐标映射

文章目录样条插值基本原理scipy实现坐标映射样条插值基本原理 由于数组本身是格点化了的&#xff0c;所以对数组的旋转、平移和缩放&#xff0c;并不像实数空间中那么简单。以一维的平移为例&#xff0c;现有三个点&#xff0c;坐标为0,1,2&#xff0c;值对应为a,b,c&#xff…

小黑子—多媒体技术与运用基础知识二:数字音频处理技术

多媒体技术与运用2.0多媒体系列第二章1. 音频处理概述1.1 什么是声音1.2 声音的基本参数1.3 人的听觉特性1.4 音频信号处理过程2.音频的数字化2.1 音频的采样2.2 音频的量化2.3 声道数2.3 音频的编码与压缩2.4 数字音频的质量3.音频文件格式及标准3.1 波形文件格式3.2 MPEG音频…

打造高效Android应用,从Hilt注入框架开始

概述 在 Android 开发中&#xff0c;注入解耦是一种设计模式&#xff0c;用于解决代码耦合的问题。通过使用注入技术&#xff0c;可以将应用程序中的不同部分解耦&#xff0c;从而使得代码更加灵活、易于维护和升级。 在 Android 中&#xff0c;注入解耦通常使用依赖注入&…

R -- 如何处理缺失数据

brief 识别缺失值 当传入向量&#xff0c;返回的是包含逻辑向量的等长向量。complete.cases()用来识别矩阵或者数据框有没有包含缺失值的行&#xff0c;若整行数据完整则返回TRUE&#xff0c;若行数据包含缺失值&#xff0c;不管几个缺失值则返回FALSE。 探索缺失值模式 列表图…

高速存储器

由于CPU和主存储器之间的速度上的不匹配限制了计算机系统的工作速度&#xff0c;为了提高CPU和主存之间的数据传输率&#xff0c;可以采用并行技术的存储器&#xff1a; 双端口存储器多模块交叉存储器 双端口存储器 同一个存储器具有两组相互独立的读写控制线路&#xff0c;…