• 【自动化测试】selenium工具


    为什么要做自动化测试?

    自动化测试就是将手工执行测试转变为使用代码来执行测试,自动化测试能够代替一部分手工测试,提高测试效率,并且随着项目版本的更新,回归测试压力越来越大,可以借助自动化来进行回归测试

    为什么选用Selenium?

    Selenium是用来做Web自动化的框架

    selenium的特点:

    • 支持多浏览器(Chrome,Firefox,Edge…)
    • 支持多系统(Linux,Windows,Mac…)
    • 支持多语言(Python,Java,C#…)
    • 拥有丰富的API

    Selenium的工作原理

    在这里插入图片描述

    总结: 我们的脚本代码会发送一个http请求到驱动,驱动解析请求后操作浏览器执行相对应的操作,待浏览器执行完相应的操作后,会将执行结果返回给驱动,驱动收到结果后,又将结果返回给脚本代码

    Selenium+Java环境搭建

    这里推荐使用Chrome浏览器

    先查看Chrome浏览器的版本
    在这里插入图片描述
    链接: Chrome驱动下载地址

    点击上述链接下载对应的驱动版本,并将驱动放在jdk的bin目录
    在这里插入图片描述

    创建一个Maven项目,并添加selenium依赖

           <dependency>
                <groupId>org.seleniumhq.seleniumgroupId>
                <artifactId>selenium-javaartifactId>
                <version>4.0.0version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    验证环境是否搭建成功:

    public class Test {
        public static void main(String[] args) {
            ChromeOptions options = new ChromeOptions();
            //允许所有请求
            options.addArguments("--remote-allow-origins=*");
            WebDriver driver = new ChromeDriver(options);
            driver.get("https://www.baidu.com"); //访问百度网址
            driver.quit(); //退出浏览器
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    启动运行,发现代码会操作浏览器访问百度网址,说明环境搭建成功

    在这里插入图片描述

    Selenium常用API

    浏览器参数配置

    ChromeOptions options = new ChromeOptions(); //创建浏览器参数配置对象
    options.addArguments("-headless"); //无头模式
    options.addArguments("--remote-allow-origins=*");
    ChromeDriver driver = new ChromeDriver(options);
    
    • 1
    • 2
    • 3
    • 4

    无头模式不会在桌面打开浏览器

    定位元素

    定位元素的方式有以下方式:

    • id
    • name
    • tag name
    • class name
    • css 选择器(#id,.class,input,…)
    • XPath
    • linkText(链接内容)
    • partialLinkText(部分链接内容)
            //获取到页面元素,对应的类型为WebElement
            WebElement element = driver.findElement(By.cssSelector("#kw"));
            driver.findElement(By.id("kw")); //通过id
            driver.findElement(By.name("wd")); //通过name
            driver.findElement(By.tagName("input")); //通过tag name,也就是标签名
            driver.findElement(By.className("s_ipt")); //通过类名
            driver.findElement(By.cssSelector("#kw")); //通过css选择器
            driver.findElement(By.xpath("//*[@id=\"kw\"]")); //通过XPath
            driver.findElement(By.linkText("新闻")); //通过超链接内容
            driver.findElement(By.partialLinkText("123")); //通过超链接部分内容
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    操作测试对象

    • sendKeys(“str”):向输入框输入内容
    • click():模拟鼠标点击
    • getText():获取元素的文本内容(首标签与尾标签之间的文本)
    • clear():清除输入框输入内容
    • submit():提交(只能用于form标签内的元素)
    • getAttribute(“str”):获取标签属性值
            element.sendKeys("庆余年"); //输入
            element.click(); //点击
            element.getText(); //获取元素的文本信息
            element.clear(); //清除输入框内容
            element.submit(); //提交
            element.getAttribute("type"); //获取标签属性
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    时间等待

    • 强制等待:Thread.sleep()
    • 隐式等待:driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3))
    • 显示等待:显示指定等待某一个元素的加载时间(只作用于一条查询元素上
    sleep(3000); //强制等待
    driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); //隐式等待3秒,作用于driver的整个生命周期
    //显示等待
    new WebDriverWait(driver,Duration.ofSeconds(3)).until(driver1->driver.findElement(By.cssSelector("#id")));
    
    • 1
    • 2
    • 3
    • 4

    区别:

    • 强制等待会一直等待设置的时间,程序阻塞执行,直到时间结束
    • 隐式等待(等待页面的所有元素都加载好,),在等待的时间内,如果页面元素加载好了,就会提前结束等待(上述代码最多只等待3秒)

    信息打印

    • 打印title:getTitle()
    • 打印url:getCurrentUrl()
    String url = driver.getCurrentUrl(); //获取url
    System.out.println(url);
    String title = driver.getTitle(); //获取title
    System.out.println(title);
    
    • 1
    • 2
    • 3
    • 4

    对浏览器操作

    关闭浏览器

    driver.quit();
    driver.close();
    
    • 1
    • 2

    区别:

    • quit关闭整个浏览器,close关闭当前页面
    • quit会清除浏览器缓存,close不会清除缓存

    浏览器窗口大小设置

    • maximize():浏览器最大化
    • minimize():浏览器最小化
    • fullscreen():浏览器全屏
    • setSize(new Dimension(int width,int height)):手动设置浏览器窗口大小
    driver.manage().window().maximize(); //窗口最大化
    driver.manage().window().minimize(); //窗口最小化
    driver.manage().window().fullscreen(); //全屏
    driver.manage().window().setSize(new Dimension(1024,600)); //手动设置大小,第一个参数为宽,第二个参数为高
    
    • 1
    • 2
    • 3
    • 4

    浏览器窗口切换操作

    浏览器打开新的标签页的时候,浏览器此时操作元素的时候,还是操作的是跳转之前的页面,如果想操作新打开的标签页面的元素,可进行如下操作

    浏览器每次打开一个标签页的时候,会自动的给每个标签页进行标识(句柄

    Set<String> handles = driver.getWindowHandles(); //获取所有标签的句柄
    String curHandle = driver.getWindowHandle(); //获取当前页面(get打开)的句柄
    for(String handle : handles){
        if(!curHandle.equals(handle)){ //如果当前句柄与遍历的不相等
            driver.switchTo().window(handle); //跳转过去
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    浏览器的前进后退

    • back:浏览器后退
    • forward:浏览器前进
    • refresh:浏览器刷新
    //浏览器的前进后退及刷新
    driver.navigate().back(); //后退
    driver.navigate().forward(); //前进
    driver.navigate().refresh(); //刷新
    
    //访问url除get外的别种写法
    driver.navigate().to("https://www.baidu.com");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    借助js代码操作浏览器滚动条

    String js = "document.documentElement.scrollTop=10000"; //scrollTop为距浏览器顶部的距离
    ((JavascriptExecutor)driver).executeScript(js); //将driver强转为JavascriptExecutor
    
    • 1
    • 2

    键盘与鼠标操作

    键盘操作

    driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"A"); //ctrl+a
    driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"C"); //ctrl+c
    driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"V"); //ctrl+v
    driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.ENTER); //回车
    
    • 1
    • 2
    • 3
    • 4

    鼠标操作

    WebElement element = driver.findElement(By.cssSelector("#kw")); //定位元素
    Actions actions = new Actions(driver); //需要借助Actions,参数据传递浏览器驱动
    actions.moveToElement(element).contextClick().perform(); //鼠标移动到元素上,右击
    actions.moveToElement(element).doubleClick().perform(); //鼠标移动到元素上,双击
    
    • 1
    • 2
    • 3
    • 4

    屏幕截图

    先在pom.xml中添加依赖

    
            <dependency>
                <groupId>commons-iogroupId>
                <artifactId>commons-ioartifactId>
                <version>2.6version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    截图保存

    File file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); //截图赋值给file
    FileUtils.copyFile(file,new File("./0522.png")); //保存在硬盘
    
    • 1
    • 2

    弹窗处理

    弹窗的类型:

    • 警告弹窗

    在这里插入图片描述

    • 确认弹窗

    在这里插入图片描述

    • 提示弹窗

    在这里插入图片描述

    弹窗不能使用定位元素的方式定位

    操作弹窗的步骤:

    1. 将driver对象切换到弹窗上:driver.switchTo().alert()
    2. 进行确定,取消,输入,获取弹窗文本内容操作:acceptdismisssendKeys("xxx")getText
    //弹窗的处理
    Alert alert = driver.switchTo().alert(); //定位到弹窗
    alert.accept(); //确定
    alert.dismiss(); //取消
    alert.sendKeys("zs"); //输入
    alert.accept(); //输入内容后需要确认
    String alertText = alert.getText(); //获取弹窗文本内容
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    说明:

    • 虽然警告弹窗只有确定按钮,但是accept和dismiss操作都可关闭弹窗
    • 虽然警告和确认弹窗没有输入框,但是执行alert.sendkeys操作也不会报错

    选择框的处理

    在这里插入图片描述

    • 根据文本选择selectByVisibleText
    • 根据属性值选择selectByValue
    • 根据序号选择selectByIndex
    WebElement element = driver.findElement(By.cssSelector("body > select"));
    Select select = new Select(element); //创建选择框对象
    select.selectByVisibleText("深圳"); //根据文本选择
    select.selectByValue("02"); //根据属性值选择
    select.selectByIndex(1); //下标从0开始,1代表第二个
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上传文件

    //上传文件
    WebElement element1 = driver.findElement(By.cssSelector("body > input[type=file]:nth-child(5)"));
    element1.sendKeys("文件路径");
    
    • 1
    • 2
    • 3

    JUnit单元测试

    JUnit是Java的单元测试框架,此处的版本是JUnit5

    在pom.xml中添加JUnit的依赖

            <dependency>
                <groupId>org.junit.jupitergroupId>
                <artifactId>junit-jupiterartifactId>
                <version>5.8.2version>
                <scope>testscope>
            dependency>
            <dependency>
                <groupId>org.junit.platformgroupId>
                <artifactId>junit-platform-suiteartifactId>
                <version>1.8.2version>
                <scope>testscope>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注解

    • @Test:加在方法上,表示该方法是一个测试用例
    • @Disabled:加在方法上,表示当前方法不参与测试用例的执行
    • @BeforeEach:表示当前方法在每个用例执行前都会执行一次
    • @BeforeAll:表示当前方法(方法需用static修饰)在所有用例执行前执行一次
    • @AfterEach:表示当前方法在每个用例执行后都会执行一次
    • @AfterAll:表示当前方法(方法需用static修饰)在所有用例执行完执行一次

    在做UI自动化的时候,一般将驱动的创建,打开的url信息放到@BeforeAll方法里,将浏览器关闭的信息放到@AfterAll方法里

    参数化

    使用@ParameterizedTest@ValueSource注解进行参数化的设置

    单个参数

        @ParameterizedTest
        @ValueSource(ints = {1,2,3})
        void method2(int i){
            System.out.println(i);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

        @ParameterizedTest
        @ValueSource(strings = {"zs","ls","ww"})
        void method2(String s){
            System.out.println(s);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    多个参数

    使用@CsvSource,可以给多个参数类型传递参数

        @ParameterizedTest
        @CsvSource(value = {"zs,5","li,6","wu,7"})
        void method4(String name,int id){
            System.out.println(id+":"+name);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    CSV获取参数

    如果参数的用例非常多,则可以将测试的参数放进csv文件中,然后通过csv文件获取参数(每个参数类型对应文件的一列数据,列与列之间用 分割)

        @ParameterizedTest
        @CsvFileSource(files = "./dir/test01.csv") //文件路径
        void method3(String name,int i){
            System.out.println(name+":"+i);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    打印结果:

    在这里插入图片描述

    方法获取参数

    public class Test {
        @ParameterizedTest
        @MethodSource("test111")
        void method1(String name,int id){
            System.out.println(id+":"+name);
        }
        static Stream<Arguments> test111(){
            return Stream.of(Arguments.arguments("zs",2),
                    Arguments.arguments("ls",3),
                    Arguments.arguments("wu",4));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    用例的执行顺序

    使用@TestMethodOrder与@Order注解进行排序

    //该注解表示当前类下所有的用例需要使用order注解来进行排序
    @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
    public class Test04 {
    
        @Order(1)
        @Test
        void test_m1(){
            System.out.println("m1");
        }
        @Order(2)
        @Test
        void test_m2(){
            System.out.println("m2");
        }
        @Order(3)
        @Test
        void test_m3(){
            System.out.println("m3");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    断言

    • Assertions.assertEquals(s1,s2):匹配才通过

    • Assertions.assertNotEquals(s1,s2):不匹配才通过

    • Assertions.assertTrue(条件):条件为真通过

    • Assertions.assertFalse(条件):条件为假才通过

    • Assertions.assertNull(xxx):xxx为null才通过

    • Assertions.assertNotNull(xxx):xxx不为null才通过

    测试套件

    通过class运行测试用例

    @Suite
    //先跑01.class,接着02.class,最后03.class
    @SelectClasses({Test01.class, Test02.class, Test03.class})
    public class RunSuit {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    通过包运行测试用例

    @Suite
    //先跑autotest1包,再跑autotest2包
    @SelectPackages(value = {"autotest1","autotest2"})
    public class RunSuit1 {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    DeepLabV3(Rethinking Atrous Convolution for Semantic Image Segmentation)
    【Java】【集合】集合框架Collection
    vue中 table中的treeselect 下拉框不显示
    CSS基础教程
    【真题笔记】14年系统架构设计师要点总结
    VUE+webrtc-streamer实现实时视频播放(监控设备-rtsp)
    【可视化工具】二维矩形装箱可视化 + JS-Canvas实现
    golang学习笔记——条件表达式
    golang grpc——header和trailer元数据传输
    AXI协议(1):AMBA总线介绍,AXI概念与背景介绍,AXI协议特点与功能
  • 原文地址:https://blog.csdn.net/qq_58710208/article/details/130672269