0


软件测试自动化Java篇【Selenium+Junit 5】

文章目录

Selenium

为什么选择selenium作为我们的web自动化测试工具?

  1. 开源免费
  2. 支持多浏览器
  3. 支持多系统
  4. 支持多语言【Java,Python,C#,Rubby,JavaScript,Kolin】
  5. selenium包提供了很多可供测试使用的API

环境部署

Chrome浏览器
在这里插入图片描述
Chrome驱动【驱动器版本要和浏览器版本对应越详细越好】
在这里插入图片描述
然后把驱动包放在安装jdk的bin目录下
在这里插入图片描述

selenium工具包
在这里插入图片描述

自动化测试例子

分为接口自动化测试和UI自动化测试

UI自动化测试包含界面测试

我们都知道用户的设备很多,有手机,平板和电脑。这些设备运行的项目在发布之初都需要经过测试,这些测试又分为web自动化测试 和 移动端自动化测试。这里以 web自动化测试 为主。
自动化测试的工具有很多,比如 QTP、Selenium,Jmeter、Loadrunner。本期就以 Selenium 为主进行介绍最简单的自动化测试

测试点击百度

importorg.openqa.selenium.By;importorg.openqa.selenium.chrome.ChromeDriver;privateclassAutoTest{// 模拟百度搜索关键词publicstaticvoidbaiduSearchKey(){String url ="https://www.baidu.com";String keyWords ="新闻";ChromeDriver chromeDriver=newChromeDriver();try{Thread.sleep(5000);// 输入框输入文字
            chromeDriver.findElement(newBy.ByXPath("//*[@id=\"kw\"]")).sendKeys(keyWords);Thread.sleep(5000);// 点击搜索按钮
            chromeDriver.findElement(newBy.ByXPath("//*[@id=\"su\"]")).click();Thread.sleep(5000);}catch(InterruptedException e){thrownewRuntimeException(e);}
        chromeDriver.quit();}publicstaticvoidmain(String[] args){baiduSearchKey();}}

获取元素方法有很多,但经常用的是 ByXPath和ByCssSelector
在这里插入图片描述

ByXpath
/:相当于子级一层一层的完整xpath路径
//:相当于越级,直接越过之前的html标签,根据id来查询标签

后文中只有之前的几个操作时获取部分xpath,以后的获取都是完整的获取xpath路径【看//数量即可知道是否根据带通配符或者id查询来区别】

常见的元素操作

  1. 输入文本 sendKeys(str) 对元素操作的前提是元素能够被找到,如果查询的元素不是可编辑的文本标签,那么前端不受影响,后端也不报错。按照程序的设定正常退出
  2. 点击操作 click()&提交操作 submit()
privatestaticvoidTestBlogLogin(){// 输入邮箱String url ="http://localhost:8080/index.html";String email ="[email protected]";String password ="admin";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{Thread.sleep(3000);// 输入邮箱
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"login\"]/div[1]/input")).sendKeys(email);Thread.sleep(3000);// 输入密码
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"login\"]/div[2]/input")).sendKeys(password);Thread.sleep(3000);// 点击登录【也可以回车登录】
        chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div/form[1]/button")).click();//chromeDriver.findElement(new By.ByXPath("/html/body/div/div/div/form[1]/button")).submit();Thread.sleep(3000);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

提交操作

submit

仅适用于form表单之类的submit操作,一般用的少
Selenium更推荐使用

click

,功能比

submit

更丰富

  1. 清除操作 clear()
privatestaticvoidTestBlogLogin(){// 输入正确的邮箱和密码String url ="http://localhost:8080/index.html";String email ="[email protected]";String password ="admin";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{Thread.sleep(3000);
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"login\"]/div[1]/input")).sendKeys("手滑输入错了");Thread.sleep(3000);// 清除文本
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"login\"]/div[1]/input")).clear();Thread.sleep(3000);
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"login\"]/div[1]/input")).sendKeys(email);Thread.sleep(3000);
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"login\"]/div[2]/input")).sendKeys(password);Thread.sleep(3000);
        chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div/form[1]/button")).click();Thread.sleep(3000);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}
  1. 获取文本值 getText()
privatestaticvoidTestBlogLogin(){// 输入正确的邮箱和密码String url ="http://localhost:8080/index.html";String email ="[email protected]";String password ="admin";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{// 获取第一道题目的标题String text = chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div[2]/div/div/div/div/div/div/table/tbody/tr[1]/td[2]")).getText();System.out.println("getText()获取到的文本:"+ text);Thread.sleep(3000);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

在这里插入图片描述

在这里插入图片描述

发现即使 URL 跳转到了别的网页,由于线程休眠3s的缘故,并不会很快就去获取页面元素而是给了页面一个加载的时间,因此可以完全获取到跳转到其它页面的标签

  1. 获取属性 getAttribute(attr)在这里插入图片描述
privatestaticvoidTestBlogLogin(){// 输入正确的邮箱和密码String url ="http://localhost:8080/index.html";String email ="[email protected]";String password ="admin";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{// 获取属性String role = chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div[2]/div/div/div/div/div/div/table/tbody/tr[1]/td[5]/div/div")).getAttribute("role");Thread.sleep(3000);String aria_valuenow = chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div[2]/div/div/div/div/div/div/table/tbody/tr[1]/td[5]/div/div")).getAttribute("aria-valuenow");Thread.sleep(3000);String aria_valuemin = chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div[2]/div/div/div/div/div/div/table/tbody/tr[1]/td[5]/div/div")).getAttribute("aria-valuemin");Thread.sleep(3000);String aClass = chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div[2]/div/div/div/div/div/div/table/tbody/tr[1]/td[5]/div/div")).getAttribute("class");Thread.sleep(3000);String style = chromeDriver.findElement(newBy.ByXPath("/html/body/div/div/div[2]/div/div/div/div/div/div/table/tbody/tr[1]/td[5]/div/div")).getAttribute("style");Thread.sleep(3000);System.out.printf("role=%s\naria_valuenow=%s\naria_valuemin=%s\naClass=%s\nstyle=%s\n", role, aria_valuenow, aria_valuemin, aClass, style);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

在这里插入图片描述
6. 获取标题

getTitle()

和url

getCurrenturl()
// 模拟百度搜索关键词privatestaticvoidbaiduSearchKey(){String url ="https://www.baidu.com";String keyWords ="新闻";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);HashMap<String,List<String>> info =newHashMap<>();try{Thread.sleep(5000);ArrayList<String> before =newArrayList<String>(){{add(chromeDriver.getTitle());add(chromeDriver.getCurrentUrl());}};// 输入框输入文字
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"kw\"]")).sendKeys(keyWords);Thread.sleep(5000);// 点击搜索按钮
        chromeDriver.findElement(newBy.ByXPath("//*[@id=\"su\"]")).click();Thread.sleep(5000);System.out.println("搜索之后");ArrayList<String> after =newArrayList<String>(){{add(chromeDriver.getTitle());add(chromeDriver.getCurrentUrl());}};
        info.put("before", before);
        info.put("after", after);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();System.out.println(info);}

在这里插入图片描述

窗口

  1. 窗口大小 窗口大小的设置:最大/小化,全屏窗口,手动设置窗口大小
privatestaticvoidwindControl(){String url ="https://www.baidu.com";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{Thread.sleep(1500);// 窗口最大化
        chromeDriver.manage().window().maximize();Thread.sleep(1500);// 窗口最小化
        chromeDriver.manage().window().minimize();Thread.sleep(1500);// 全屏
        chromeDriver.manage().window().fullscreen();Thread.sleep(1500);// 手动设置窗口大小
        chromeDriver.manage().window().setSize(newDimension(1024,768));Thread.sleep(1500);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}
  1. 切换窗口 一般的窗口切换可能会导致找不到元素的BUG
privatestaticvoidwindControl(){String url ="https://www.baidu.com";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{Thread.sleep(1500);// 点击准备跳转
        chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[3]/a[6]")).click();String value = chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[3]/div/div/div/div/div/div[2]/form/span[2]/input")).getAttribute("value");System.out.println(value);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

在这里插入图片描述
由于无法获取跳转页面的元素,所以就会报错。因此需要一个页面切换功能

privatestaticvoidwindControl(){String url ="https://www.baidu.com";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{Thread.sleep(1500);// 获取当前页面句柄String currentHandle = chromeDriver.getWindowHandles().toString();System.out.println("当前首页句柄:"+currentHandle);Thread.sleep(1500);// 点击准备跳转
        chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[3]/a[6]")).click();// 获取跳转之后所有标签页的句柄Set<String> handles = chromeDriver.getWindowHandles();for(String handle : handles){if(currentHandle != handle){
                chromeDriver.switchTo().window(handle);}}String value = chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[3]/div/div/div/div/div/div[2]/form/span[2]/input")).getAttribute("value");System.out.println(value);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

运行的退出码已经恢复正常
在这里插入图片描述
3. 屏幕截图
需要导入一个常用的commons-io库

<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency>
privatestaticvoidwindControl(){String url ="https://www.baidu.com";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);try{Thread.sleep(1500);// 点击准备跳转
        chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[3]/a[6]")).click();File screenshotAs = chromeDriver.getScreenshotAs(OutputType.FILE);// 把屏幕截图好的文件放在指定的路径下String fileName ="my.png";try{FileUtils.copyFile(screenshotAs,newFile(fileName));}catch(IOException e){thrownewRuntimeException(e);}String value = chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[3]/div/div/div/div/div/div[2]/form/span[2]/input")).getAttribute("value");System.out.println(value);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

这里会发生报错,由于屏幕截图原因。所以会保存当时的获取状态。
在这里插入图片描述
会把当前的现场截图保存下来【由于没有切换页面,所以也就会报错,截图代码发生在报错之前的代码,所以也就保留了事故现场

等待

程序执行的速度比页面渲染速度快很多,因此之前的等待都是使用线程的强制等待,这并不合理。等待一共分为四种。
强制等待、隐式等待、显示等待、流畅等待

  1. 强制等待 程序阻塞运行,Thread.sleep()。会用到,但是自动化里不能用的特别多,否则拖慢速度
  2. 隐式等待 隐式等待会一直轮询判断元素是否存在,如果不存在就等待设置好的时间里不断地进行轮询知道元素能够被找到
privatestaticvoidwaitController(){String url ="https://www.baidu.com";ChromeDriver chromeDriver=newChromeDriver();// 添加隐式等待:会作用于chromeDriver整个生命周期
    chromeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    chromeDriver.get(url);
    chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input")).sendKeys("迪丽热巴");
    chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[5]/div/div/form/span[2]/input")).click();
    chromeDriver.findElement(newBy.ByXPath("/html/body/div[2]/div[3]/div[1]/div[3]/div[1]/div[1]/div/div/div/div/div[2]/div/a/div/p/span/span"));
    chromeDriver.quit();}
  1. 显示等待 隐式等待针对的是 driver的整个生命周期,所以对全部元素有效,但有时候并非全部都需要等待,我们可以只针对其中一个元素进行等待操作,其余元素交给程序快速运行进而提高自动化测试的效率
privatestaticvoidwebDriverWait(){String url ="https://www.baidu.com";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.get(url);
    chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input")).sendKeys("迪丽热巴");
    chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[5]/div/div/form/span[2]/input")).click();// 只针对某个元素显示等待newWebDriverWait(chromeDriver,Duration.ofSeconds(3)).until(lambda -> chromeDriver.findElement(newBy.ByXPath("/html/body/div[2]/div[3]/div[1]/div[3]/div[1]/div[1]/div/div/div/div/div[2]/div/a/div/p/span/span")));
    chromeDriver.get(url);}

这里使用了 lambda表达式 的语法,我们查看一下 until的源码
在这里插入图片描述
参数是一个泛型,所以可以传入任何泛型函数。然后就是执行的循环,获取页面元素操作。

  • 隐式等待 和 显式等待 并不能同时使用,可能会出现意想不到的结果
  • 隐式等待 和 显示等待 均不出现效果的时候可以使用 强制等待

浏览器的操作

浏览器的回退,前进和刷新操作

privatestaticvoidnavigateControl(){String url ="https://www.baidu.com";ChromeDriver chromeDriver =newChromeDriver();// 简写//        chromeDriver.get(url);// 非简写
    chromeDriver.navigate().to(url);
    chromeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));// 想要回退到访问百度网址之前的状态
    chromeDriver.navigate().back();// 前进,有进入到了百度首页
    chromeDriver.navigate().forward();// 刷新百度首页
    chromeDriver.navigate().refresh();
    chromeDriver.quit();}

弹窗

弹窗一共有3大类型,如下所示分别为:alert、confirm和prompt
在这里插入图片描述
但是却发现,浏览器进入检查时候无法获取到弹窗的元素
处理弹窗的步骤

  1. 将driver对象作用到弹窗上(切换到弹窗)
  2. 选择确认/取消(提示弹窗输入文本)作用到弹窗上:driver.switchTo.alert()``````确认:driver.accept()``````取消:`driver.dismiss()``````输入:driver.sendKeys()

前端代码

<divid="alertVue"><buttonv-on:click="f()">{{value}}</button></div><divid="confirmVue"><buttonv-on:click="f()">{{value}}</button></div><divid="promptVue"><buttonv-on:click="f()">{{value}}</button></div><scripttype="text/javascript"src="vue.js"></script><script>const alertVue =newVue({el:'#alertVue',data:{value:"Alert弹窗",},methods:{f(){
                window.alert("alert弹窗");}}});const confirmVue =newVue({el:'#confirmVue',data:{value:"Confirm确认框",},methods:{f(){if(window.confirm("是否确认?")){
                    confirmVue.value ="true";}else{
                    confirmVue.value ="false";}}}});const promptVue =newVue({el:'#promptVue',data:{value:"输入框",},methods:{f(){
                promptVue.value = window.prompt("输入框");}}});</script>

测试代码

privatestaticvoidalertController(){String url ="file:///D:/Documents/Program/Java/SeleniumTest/Autotest/src/test/java/alertHTML.html";ChromeDriver chromeDriver=newChromeDriver();
    chromeDriver.navigate().to(url);try{Thread.sleep(1500);// 点击 alert
        chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/button")).click();Thread.sleep(1500);// 切换到弹窗Alert alert = chromeDriver.switchTo().alert();// 确认操作:accept/取消操作:dismiss
        alert.dismiss();Thread.sleep(1500);// 点击 confirm
        chromeDriver.findElement(newBy.ByXPath("/html/body/div[2]/button")).click();Thread.sleep(1500);// 切换到弹窗
        alert = chromeDriver.switchTo().alert();// 确认操作
        alert.accept();Thread.sleep(1500);// 点击 prompt
        chromeDriver.findElement(newBy.ByXPath("/html/body/div[3]/button")).click();Thread.sleep(1500);// 切换到弹窗
        alert = chromeDriver.switchTo().alert();Thread.sleep(1500);// 在页面上看不到输入的文本效果,但是其实已经输入了
        alert.sendKeys("阿斯顿马丁");// 接受文本
        alert.accept();Thread.sleep(1500);// 确认操作}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}
  • prompt 弹窗进行 sendKeys(str) 的时候不会在页面出现效果,但是程序已经输入有文本信息
  • alert 警告弹窗虽然只有确认选项,但是也可以用 dismiss和accept 都可以进行取消操作
  • url 一定要复制浏览器中选择而不是从资源路径中选择【浏览器的url前边会多一个file:///

选择器

选择框的处理困难在于无法将下拉框的元素进行定位,每当点击检查的时候,下拉框就会消失
这个时候我们可以根据三个条件进行选择

  1. 文本
  2. 属性
  3. 下标

html代码

<divid="selectVue"><select><optionv-for="(month, index) in monthes"v-bind:value="index+1">{{month}}</option></select></div><script>const selectVue =newVue({el:'#selectVue',data:{monthes:["January","February","March","April","May","June","July","August","September","October","November","December",],},});</script>

Java代码

privatestaticvoidalertController(){String url ="file:///D:/Documents/Program/Java/SeleniumTest/Autotest/src/test/java/alertHTML.html";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.navigate().to(url);try{// option选择器WebElement element = chromeDriver.findElement(newBy.ByXPath("/html/body/div[4]/select"));Thread.sleep(1500);// 先创建选择框对象Select select =newSelect(element);Thread.sleep(1500);// 根据文本来选择【并不会像正常操作一样点击一下选择框而是直接选中下拉框】
        select.selectByVisibleText("September");Thread.sleep(1500);// 根据属性值选择
        select.selectByValue("1");Thread.sleep(1500);// 根据下标选择【0开始】,选取九月
        select.selectByIndex(8);Thread.sleep(1500);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

XPath的选择器是从1开始;而下标选择从0开始

执行脚本

执行 js 代码,有时候会遇到输入文本不完全或者不生效的情况下,可以使用执行原生js脚本进行解决

privatestaticvoidscriptControl(){String url ="https://image.baidu.com/";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.navigate().to(url);try{// 执行 js 代码让页面置底
        chromeDriver.executeScript("document.documentElement.scrollTop = 500");Thread.sleep(1500);// 执行 js 代码让页面置顶
        chromeDriver.executeScript("document.documentElement.scrollTop = 0");Thread.sleep(1500);// 百度输入框输入指定文本
        chromeDriver.navigate().to("https://www.baidu.com/");
        chromeDriver.executeScript("var ss=document.querySelector('#kw'); ss.value='英雄钢笔'");Thread.sleep(1500);}catch(InterruptedException e){thrownewRuntimeException(e);}

    chromeDriver.quit();}

文件上传

文件上传的难点在于当点击上传文件时的弹窗是系统自己的弹窗,并不是浏览器的弹窗。对于Selenium而言并不能控制系统。
在这里插入图片描述

privatestaticvoidfileUploadControl(){String url ="file:///D:/Documents/Program/Java/SeleniumTest/Autotest/src/test/java/alertHTML.html";ChromeDriver chromeDriver =newChromeDriver();
    chromeDriver.navigate().to(url);try{Thread.sleep(1500);
        chromeDriver.findElement(newBy.ByXPath("/html/body/div[5]/input")).sendKeys("D:\\Documents\\Program\\Java\\SeleniumTest\\Autotest\\src\\test\\java\\alertHTML.html");Thread.sleep(1500);}catch(InterruptedException e){thrownewRuntimeException(e);}
    chromeDriver.quit();}

这里运行完毕之后并不是把文件上传到服务器而是要把上传的文件路径+文件以名称的方式放到这里

浏览器参数

实际工作中,测试人员将自动化部署在机器上自动的执行,测试人员不会每次都一直盯着自动化执行的过程,而是直接查看自动化执行的结果。
无头模式:类似于Linux的

&

模式运行命令挂载在后台进程,不在前台显示。浏览器而言的话就是没有画面的运行一些自动化测试脚本,这样可以节约一定的机器内存资源。

privatestaticvoidparamControl(){// 百度搜索 ”测试开发工程师“// 先创建选项对象然后设置浏览器参数String url ="https://www.baidu.com/";ChromeOptions chromeOptions =newChromeOptions();
    chromeOptions.addArguments("-headless");// 添加浏览器参数设置ChromeDriver chromeDriver =newChromeDriver(chromeOptions);
    chromeDriver.navigate().to(url);
    chromeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input")).sendKeys("测试开发工程师");
    chromeDriver.findElement(newBy.ByXPath("/html/body/div[1]/div[1]/div[5]/div/div/form/span[2]/input")).click();
    chromeDriver.quit();}

Junit 5

自动化是Selenium脚本来实现的,Junit是java的单元测试工具.只不过我们在实现自动化的时候需要借用Junit库里面提供的一些方法
Junit 5支持最低支持jdk8
目前Java领域内最为流行的单元测试框架 ------ JUnit
Junit 5 = Junit Platform + Junit Jupiter + Junit Vintage
Junit Platform: Junit Platform是在JVM上启动测试框架的基础,不仅支持Junit自制的测试引擎,其他测试引擎也都可以接入
Junit Jupiter: Junit Jupiter提供了JUnit5的新的编程模型,是JUnit5新特性的核心。内部 包含了一个测试引擎,用于在Junit Platform上运行
Junit Vintage: 由于JUnit已经发展多年,为了照顾老的项目,JUnit Vintage提供了兼容JUnit4.x,Junit3.x的测试引擎
在这里插入图片描述

导入依赖

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.9.2</version><scope>test</scope></dependency><!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite --><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.9.2</version><scope>test</scope></dependency>

Junit 4 和 Junit5 注解对比

Junit 5Junit 4说明@Test@Test被注解的是一个测试方法,和Junit 4相同@BeforeAll@BeforeClass被注解的(静态)方法将在当前类中的所有@Test方法前执行一次@BeforeEach@Before被注解的方法将在当前类中的么欸个@Test方法前执行@AffterAll@AfterClass被注解的(静态)方法将在当前类中的所有@Test方法后执行一次@AffterEach@After被注解的方法将在当前类中的么欸个@Test方法后执行@DIsable@Ignore被注解的方法不会执行(将被跳过),但会报告为已执行
Junit 4 中

@Test

org.junit.Test;

Junit 5 中

@Test

org.junit.jupiter.api.Test;
@BeforeAll

注解必须用在

static

修饰的代码块上,否则会报错

importorg.junit.jupiter.api.BeforeAll;importorg.junit.jupiter.api.BeforeEach;importorg.junit.jupiter.api.Test;publicclassJunitTest{// 当前方法要在所有测试用例之前执行一次@BeforeAllstaticvoidbeforeAll(){System.out.println("@BeforeAll");}// 当前方法要在每个测试用例执行之前执行一次@BeforeEachvoidbeforeEach(){System.out.println("@BeforeEach");}@Testvoidt1(){System.out.println("@Test1");}@Testvoidt2(){System.out.println("@Test2");}@Testvoidt3(){System.out.println("@Test3");}}

在这里插入图片描述
After效果和Before效果相反

importorg.junit.jupiter.api.*;publicclassJunitTest{// 当前方法要在所有测试用例之前执行一次@BeforeAllstaticvoidbeforeAll(){System.out.println("@BeforeAll");}// 当前方法要在每个测试用例执行之前执行一次@BeforeEachvoidbeforeEach(){System.out.println("@BeforeEach");}@Testvoidt1(){System.out.println("@Test1");}@Testvoidt2(){System.out.println("@Test2");}@Testvoidt3(){System.out.println("@Test3");}@AfterEachvoidafterEach(){System.out.println("@AfterEach");}@AfterAllstaticvoidafterAll(){System.out.println("@AfterAll");}}

在这里插入图片描述

断言

断言方法说明assertEquals(expected, actual)如果 expected 不等于 actual ,则断言失败assertFalse(booleanExpression)如果 booleanExpression 不是 false ,则断言失败assertNull(actual)如果 actual 不是 null ,则断言失败assertNotNull(actual)如果 actual 是 null ,则断言失败assertTrue(booleanExpression)如果 booleanExpression 不是 true ,则断言失败

@TestvoidtestAttributeValue(){String url ="https://www.baidu.com/";ChromeOptions chromeOptions =newChromeOptions();
    chromeOptions.addArguments("-headless");ChromeDriver chromeDriver =newChromeDriver(chromeOptions);
    chromeDriver.navigate().to(url);
    chromeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));String value = chromeDriver.findElement(By.cssSelector("#su")).getAttribute("value");// 假如这里获取到的属性值不是 百度一下 而是百度两下System.out.println("value:"+ value);Assertions.assertEquals("百度两下", value);
    chromeDriver.quit();}

断言失败
在这里插入图片描述
断言成功

@TestvoidtestAttributeValue(){String url ="https://www.baidu.com/";ChromeOptions chromeOptions =newChromeOptions();
    chromeOptions.addArguments("-headless");ChromeDriver chromeDriver =newChromeDriver(chromeOptions);
    chromeDriver.navigate().to(url);
    chromeDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));String value = chromeDriver.findElement(By.cssSelector("#su")).getAttribute("value");// 假如这里获取到的属性值不是 百度一下 而是百度两下System.out.println("value:"+ value);Assertions.assertNotEquals("百度两下", value);
    chromeDriver.quit();}

在这里插入图片描述

不会提示错误地方

测试顺序

importorg.junit.jupiter.api.*;publicclassJunitTest{// 当前方法要在所有测试用例之前执行一次@BeforeAllstaticvoidbeforeAll(){System.out.println("@BeforeAll");}// 当前方法要在每个测试用例执行之前执行一次@BeforeEachvoidbeforeEach(){System.out.println("@BeforeEach");}@Testvoidae(){System.out.println("@Test1");}@Testvoidbc(){System.out.println("@Test2");}@Testvoidab(){System.out.println("@Test3");}@AfterEachvoidafterEach(){System.out.println("@AfterEach");}@AfterAllstaticvoidafterAll(){System.out.println("@AfterAll");}}@BeforeAll@BeforeEach@Test3@AfterEach@BeforeEach@Test1@AfterEach@BeforeEach@Test2@AfterEach@AfterAll

发现执行顺序按照方法名排序一样,这里的顺序并不是按照程序中代码的顺序执行。有时候我们需要按照顺序执行代码,比如测试系统的时候必须要用户先登陆才可以后续的一些操作的时候就需要按照顺序执行测试代码
添加一个

@TestMethodOrder

注解,然后添加参数

MethodOrderer.OrderAnnotation.class

,最后再给每个执行的代码编辑顺序即可

importorg.junit.jupiter.api.*;@TestMethodOrder(MethodOrderer.OrderAnnotation.class)publicclassJunitTest{// 当前方法要在所有测试用例之前执行一次@BeforeAllstaticvoidbeforeAll(){System.out.println("@BeforeAll");}// 当前方法要在每个测试用例执行之前执行一次@BeforeEachvoidbeforeEach(){System.out.println("@BeforeEach");}@Test@Order(1)voidae(){System.out.println("@Test1");}@Test@Order(2)voidbc(){System.out.println("@Test2");}@Test@Order(3)voidab(){System.out.println("@Test3");}@AfterEachvoidafterEach(){System.out.println("@AfterEach");}@AfterAllstaticvoidafterAll(){System.out.println("@AfterAll");}}@BeforeAll@BeforeEach@Test1@AfterEach@BeforeEach@Test2@AfterEach@BeforeEach@Test3@AfterEach@AfterAll

参数化

  1. 尽可能地通过一个用例,多组参数来模拟用户的行为
  2. 使用了参数化注解之后就不能再使用 @Test 注解

单参数

@ParameterizedTest// 使用参数化注解之前需要先声明该方法为参数化方法@ValueSource(strings ={"[email protected]","[email protected]"})// 通过注解提供数据源voidSingleParamsTest(String email){System.out.println(email);}

在这里插入图片描述
可以看到

@ValueSource(数据类型={参数1, 参数2, 参数3...})

提供的数据源类型有很多
在这里插入图片描述

多参数

@ParameterizedTest@CsvSource({"[email protected], admin","[email protected], root"})voidmuchParamsTest(String email,String password){System.out.printf("email:%s<==>password:%s\n", email, password);}

email:[email protected]<==>password:admin
email:[email protected]<==>password:root

当参数很多的时候,我们可以把参数放入文件中然后通过文件读取获取参数

@ParameterizedTest@CsvFileSource(files ="D:\\Documents\\Program\\Java\\SeleniumTest\\Autotest\\src\\test\\resources\\userData.csv")voidcsvFileParamsTest(String email,String password){System.out.printf("email:%s<==>password:%s\n", email, password);}

在这里插入图片描述
发现

@CsvFileSource

的源码可以放入很多参数来设置文件,这里只放了

files

一个参数的值,文件默认编码已经是 UTF-8 所以就可以不用管编码问题
在这里插入图片描述

动态参数

这里导入一个随机工具类 common-util–使用方法

// 动态参数staticStream<Arguments>methodParams(){// 构造动态参数String[] arr =newString[10];for(int i =0; i < arr.length; i++){
        arr[i]=RandomUtil.randomNumbers(10)+"@qq.com";}returnStream.of(Arguments.arguments(arr[0],RandomUtil.randomString(8)),Arguments.arguments(arr[1],RandomUtil.randomString(8)),Arguments.arguments(arr[2],RandomUtil.randomString(8)),Arguments.arguments(arr[3],RandomUtil.randomString(8)),Arguments.arguments(arr[4],RandomUtil.randomString(8)),Arguments.arguments(arr[5],RandomUtil.randomString(8)),Arguments.arguments(arr[6],RandomUtil.randomString(8)),Arguments.arguments(arr[7],RandomUtil.randomString(8)),Arguments.arguments(arr[8],RandomUtil.randomString(8)),Arguments.arguments(arr[9],RandomUtil.randomString(8)));}@ParameterizedTest@MethodSource(value ="methodParams")voiddynamicMethodParams(String email,String password){System.out.printf("email:%s<==>password:%s\n", email, password);}
email:[email protected]<==>password:5knqh9nd
email:[email protected]<==>password:jndm1vx6
email:[email protected]<==>password:9e6yaky2
email:[email protected]<==>password:56vjv9ff
email:[email protected]<==>password:0uq2mx9r
email:[email protected]<==>password:k5xcauzb
email:[email protected]<==>password:q9zltwfd
email:[email protected]<==>password:wrgn7fxr
email:[email protected]<==>password:f3l255bc
email:[email protected]<==>password:mnpveuxj

在这里插入图片描述

这里为了方便,就直接使用

Arguments

来替代

小技巧
如果数据源与测试方法同名,则无需执行数据源是来自哪里的

// 动态参数staticStream<Arguments>dynamicMethodParams(){// 构造动态参数String[] arr =newString[10];for(int i =0; i < arr.length; i++){
        arr[i]=RandomUtil.randomNumbers(10)+"@qq.com";}returnStream.of(Arguments.arguments(arr[0],RandomUtil.randomString(8)),Arguments.arguments(arr[1],RandomUtil.randomString(8)),Arguments.arguments(arr[2],RandomUtil.randomString(8)),Arguments.arguments(arr[3],RandomUtil.randomString(8)),Arguments.arguments(arr[4],RandomUtil.randomString(8)),Arguments.arguments(arr[5],RandomUtil.randomString(8)),Arguments.arguments(arr[6],RandomUtil.randomString(8)),Arguments.arguments(arr[7],RandomUtil.randomString(8)),Arguments.arguments(arr[8],RandomUtil.randomString(8)),Arguments.arguments(arr[9],RandomUtil.randomString(8)));}@ParameterizedTest@MethodSource// 自动寻找与方法名同名的数据源voiddynamicMethodParams(String email,String password){System.out.printf("email:%s<==>password:%s\n", email, password);}
email:[email protected]<==>password:wewp75wh
email:[email protected]<==>password:q57n49kf
email:[email protected]<==>password:dkyfns0t
email:[email protected]<==>password:kfxow9gw
email:[email protected]<==>password:a5dwh5g4
email:[email protected]<==>password:g9gszroo
email:[email protected]<==>password:er521mby
email:[email protected]<==>password:qhftn0rh
email:[email protected]<==>password:zsjkkyns
email:[email protected]<==>password:fu8g79om

测试套件

指定类来运行测试用例

packageTestSuite;importorg.junit.platform.suite.api.SelectClasses;importorg.junit.platform.suite.api.Suite;// 测试套件:通过 @Suite 注解@Suite@SelectClasses(value ={aaa.class, bbb.class})publicclass runSuite {}

测试套件测试 aaa.java, bbb.java, ccc.java 的测试结果,类下想要运行的用例必须要被

@Test

注解修饰
在这里插入图片描述

@Suite

注解标识该类是测试套件类而不是测试类

@SelectClasses

部分源码告知我们需要填上

class

类名
在这里插入图片描述

指定包名来运行包下测试用例

packageTestSuite;importorg.junit.platform.suite.api.SelectClasses;importorg.junit.platform.suite.api.SelectPackages;importorg.junit.platform.suite.api.Suite;// 测试套件:通过 @Suite 注解@Suite//@SelectClasses(value = {aaa.class, bbb.class})@SelectPackages("TestSuite")publicclass runSuite {}

发现连

ccc.java

的测试也打印输出了
在这里插入图片描述

最好是把要测试的文件以 xxxTest 结尾比较好,但是因为文件夹是

TestSuite

的缘故,所以现在即使不是 xxxTest 结尾的包文件也能被扫描到并执行

@Test

注解的方法,否则就会执行报错。

报错问题如下所示
在这里插入图片描述
解决方案如下所示
在这里插入图片描述

标签: 自动化 java selenium

本文转载自: https://blog.csdn.net/weixin_45364220/article/details/129228773
版权归原作者 面向丈母娘编程 所有, 如有侵权,请联系我们删除。

“软件测试自动化Java篇【Selenium+Junit 5】”的评论:

还没有评论