【测试】⾃动化测试常⽤函数

本节重点

  • 元素定位
  • 操作测试对象
  • 窗⼝
  • 等待
  • 导航
  • 弹窗
  • ⽂件上传
  • 浏览器参数

1.元素的定位

web⾃动化测试的操作核⼼是能够找到⻚⾯对应的元素,然后才能对元素进⾏具体的操作。

常⻅的元素定位⽅式⾮常多,如id,classname,tagname,xpath,cssSelector

常⽤的主要由cssSelector和xpath

1.1 cssSelector

选择器的功能:选中⻚⾯中指定的标签元素

选择器的种类分为基础选择器和复合选择器,常⻅的元素定位⽅式可以通过id选择器和⼦类选择器来进⾏定位。

定位百度⾸⻚的"百度热搜"元素,可以使⽤通过id选择器和⼦类选择器进⾏定位:#s-hotsearch

wrapper > div

"搜索输⼊框元素":#kw

"百度⼀下按钮":#su

1.2 xpath

XML路径语⾔,不仅可以在XML⽂件中查找信息,还可以在HTML中选取节点。

xpath使⽤路径表达式来选择xml⽂档中的节点

xpath语法中:

1.2.1 获取HTML⻚⾯所有的节点

//*

1.2.2 获取HTML⻚⾯指定的节点

//[指定节点]

//ul :获取HTML⻚⾯所有的ul节点

//input:获取HTML⻚⾯所有的input节点

1.2.3 获取⼀个节点中的直接⼦节点

/

//span/input

1.2.4 获取⼀个节点的⽗节点

..

//input/.. 获取input节点的⽗节点

1.2.5 实现节点属性的匹配

@...

//*[@id='kw'] 匹配HTML⻚⾯中id属性为kw的节点

1.2.6 使⽤指定索引的⽅式获取对应的节点内容

注意:xpath的索引是从1开始的。

百度⾸⻚通过://div/ul/li[3] 定位到第三个百度热搜标签

更便捷的⽣成selector/xpath的⽅式:右键选择复制"Copy selector/xpath"

注意:元素的定位⽅法必须唯⼀。

案例:如果想要匹配到百度⾸⻚指定的新闻⽂本或者节点集:,直接使⽤ #hotsearch-content

wrapper > li 能够满⾜吗?

回答:不能满足。必须指定到选择哪一个新闻,后面需要加上:nth-child(i)

#hotsearch-content-wrapper > li:nth-child(5) > a

问题:既然可以⼿动复制 selector/xpath的⽅式 ,为什么还有了解语法?

⼿动复制的selector/xpath表达式并不⼀定满⾜上⾯的唯⼀性的要求,有时候也需要⼿动的进⾏修改表达式

案例:百度⾸⻚(需要登陆百度账号)右侧的热搜,复制li标签下的a标签,复制好的的selector为: #title-content ,xpath为: //*[@id="title-content"] ,可以⼿动操作⼀下,⼿动复制的表达式是否唯⼀呢?

2.操作测试对象

获取到了⻚⾯的元素之后,接下来就是要对元素进⾏操作了。常⻅的操作有点击、提交、输⼊、清

除、获取⽂本。

2.1 点击/提交对象

click()

driver .findElement(By.cssSelector("#su")).click();

注意:除了按钮之外,页面的绝大部分元素都是可以点击的,但是一些页面隐藏的标签、不可见的标签就不能点击

第一步:筛选:看标签type是否有hidden关键字

第二步:看每个标签对应的样式

2.2 模拟按键输⼊

sendKeys("")

driver .findElement(By.cssSelector("#kw")).sendKeys("输⼊⽂字");

2.3 清除⽂本内容

输⼊⽂本后⼜想换⼀个新的关键词,这⾥就需要⽤到 clear()

driver .findElement(By.cssSelector("#kw")).sendKeys("我爱游戏");

driver.findElement(By.cssSelector("#kw")).clear();

driver .findElement(By.cssSelector("#kw")).sendKeys("我爱学习");

2.4 获取⽂本信息

如果判断获取到的元素对应的⽂本是否符合预期呢?获取元素对应的⽂本并打印⼀下~~

获取⽂本信息: getText()

java 复制代码
public void test04() throws InterruptedException {
        createDriver();

        List<WebElement> ll=driver.findElements(By.cssSelector("#hotsearch-content-wrapper > li> a > span.title-content-title")) ;
        for (WebElement wb:ll) {
            System.out.println(wb.getText());
        }

        driver.quit();
    }

问题:是否可以通过 getText() 获取到"百度⼀下按钮"上的⽂字"百度⼀下"呢?尝试⼀下

回答:不可以。因为百度一下实质上是该按钮的value值,是属性而不是元素值。

注意:⽂本和属性值不要混淆了。获取属性值需要使⽤⽅法 getAttribute("属性名称") ;

java 复制代码
    public void test05() throws InterruptedException {
        createDriver();
        WebElement ll=driver.findElement(By.cssSelector("#su")) ;
        System.out.println(ll.getAttribute("value"));
        driver.quit();
    }

2.5 获取当前⻚⾯标题

getTitle()

2.6获取当前⻚⾯URL

getCurrentUrl()

3.窗⼝

打开⼀个新的⻚⾯之后获取到的title和URL仍然还是前⼀个⻚⾯的?

当我们⼿⼯测试的时候,我们可以通过眼睛来判断当前的窗⼝是什么,但对于程序来说它是不知道当前最新的窗⼝应该是哪⼀个。对于程序来说它怎么来识别每⼀个窗⼝呢?每个浏览器窗⼝都有⼀个唯⼀的属性句柄(handle)来表⽰,我们就可以通过句柄来切换

3.1 切换窗⼝

1)获取当前⻚⾯句柄:

driver.getWindowHandle();

2)获取所有⻚⾯句柄:

driver.getWindowHandles();

3)切换当前句柄为最新⻚⾯:

java 复制代码
    public void test10() throws InterruptedException {
        createDriver();
        String windowHandle = driver.getWindowHandle();
        System.out.println(windowHandle);
        WebElement we=driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)"));
        we.click();
        Set<String> windowHandles = driver.getWindowHandles();
        for (String i:windowHandles) {
           if (i!=windowHandle) {
               driver.switchTo().window(i);
           }
        }

        driver.findElement(By.cssSelector("#headline-tabs > ul > li > a"));
        System.out.printf("title:"+driver.getTitle());
        Thread.sleep(3000);

        driver.quit();
    }

注意:执⾏了driver.close()之前需要切换到未被关闭的窗⼝

3.2 窗⼝设置⼤⼩

1)窗⼝的⼤⼩设置

java 复制代码
    public void test09() throws InterruptedException {
        createDriver();
        WebElement we=driver.findElement(By.cssSelector("#kw"));
        we.sendKeys("刘宇");
        driver.findElement(By.cssSelector("#su")).click();
        Thread.sleep(3000);
        driver.manage().window().maximize();
        Thread.sleep(3000);
        driver.manage().window().minimize();
        Thread.sleep(3000);
        driver.manage().window().fullscreen();
        Thread.sleep(3000);
        driver.manage().window().setSize(new Dimension(1624,728));
        Thread.sleep(3000);
        driver.quit();
    }

3.3 窗⼝切换

去掉等待后,获取跳转后的⻚⾯元素失败

// 获取所有句柄

// 获取当前停留⻚⾯句柄

java 复制代码
    public void test10() throws InterruptedException {
        createDriver();
        String windowHandle = driver.getWindowHandle();
        System.out.println(windowHandle);
        WebElement we=driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)"));
        we.click();
        Set<String> windowHandles = driver.getWindowHandles();
        for (String i:windowHandles) {
           if (i!=windowHandle) {
               driver.switchTo().window(i);
           }
        }

        driver.findElement(By.cssSelector("#headline-tabs > ul > li > a"));
        System.out.printf("title:"+driver.getTitle());
        Thread.sleep(3000);

        driver.quit();
    }

3.4 屏幕截图

我们的⾃动化脚本⼀般部署在机器上⾃动的去运⾏,如果出现了报错,我们是不知道的,可以通过抓拍来记录当时的错误场景

屏幕截图⽅法需要额外导⼊包:

File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);

FileUtils.copyFile(file,new File(filename));

代码演⽰

java 复制代码
//简单版本

File srcfile = driver.getScreenshotAs(OutputType.FILE);

FileUtils.copyFile(srcfile,new File("my.png"));

这里提出了新的要求:

1)每次生成的屏幕截图都能保存下来,避免覆盖

2)屏幕截图文件统一放到test下的image文件夹下

3)生成的屏幕截图名称,要见名知义---即看到这个屏幕截图我就知道是哪个测试方法的屏幕截图

java 复制代码
  public void getshot(String str) throws IOException {
        SimpleDateFormat sim1=new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sim2=new SimpleDateFormat("HHmmss");
        String dirTime=sim1.format(System.currentTimeMillis());
        String fileTime=sim2.format(System.currentTimeMillis());

        String filename="./src/test/img/"+dirTime+"/"+str+"-"+fileTime+".png";
        File srcShot= ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        FileUtils.copyFile(srcShot,new File(filename));
    }

3.5关闭窗⼝

driver.close();

注意:该方法使用场景较少,只有当当前标签页要关掉,重新操作原先标签页才需要,记得窗⼝关闭后driver要重新定义

假如写自动化代码出现了NoSuchElement错误

第一步:在报错的代码前添加Thread.sleep(秒),设置的时间长一点

第二步:执行自动化,在自动化打开的页面里打开前端开发者工具,手动检査元素是否真的不存在

1)自动化打开的页面确实不存在该元素

--手动打开的页面和自动化打开的页面不一样(很可能是登陆和未登录状态下页面不一样) --元素为动态元素

解决方法:先定位动态元素的前一级标签,再增加要定位的元素标签

2)自动化打开的页面确实存在该元素

代码执行的速度比页面消染的速度要快,页面还没消染出来,程序已经开始找了,导致元素没有找到

解决办法----添加等待

4、等待

通常代码执⾏的速度⽐⻚⾯渲染的速度要快,如果避免因为渲染过慢出现的⾃动化误报的问题呢?可以使⽤selenium中提供的三种等待⽅法:

4.1 强制等待

Thread.sleep()

优点:使⽤简单,直接阻塞程序,调试的时候⽐较有效

缺点:影响运⾏效率,浪费⼤量的时间

4.2 隐式等待

隐式等待是⼀种智能等待,他可以规定在查找元素时,在指定时间内不断查找元素。如果找到则代码-继续执⾏,直到超时没找到元素才会报错。

implicitlyWait() 参数:Duration类中提供的毫秒、秒、分钟等⽅法

⽰例:

java 复制代码
//隐式等待1000毫秒

driver.manage().timeouts().implicitlyWait(Duration.ofMillis(1000));

//隐式等待5秒

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

隐式等待作⽤域是整个脚本的所有元素。即只要driver对象没有被释放掉(driver.quit()),隐式等待就⼀直⽣效。

优点:智能等待,作⽤于全局

缺点:只能查找元素,每次查找元素都要等待,不能查找弹窗

4.3 显⽰等待

显⽰等待也是⼀种智能等待,在指定超时时间范围内只要满⾜操作的条件就会继续执⾏后续代码

new WebDriverWait(driver, Duration.ofSeconds(3)).until($express)

$press:涉及到selenium.support.ui.ExpectedConditions包下的ExpectedConditions类

返回值:boolean

⽰例:

java 复制代码
public void test14() throws InterruptedException, IOException {
        createDriver();
        WebDriverWait webDriverWait = new WebDriverWait(driver, Duration.ofSeconds(2));
        webDriverWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#su")));
        driver.findElement(By.cssSelector("#su")).click();
        webDriverWait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#kw")));
        driver.findElement(By.cssSelector("#kw")).sendKeys("dilireba");
        webDriverWait.until(ExpectedConditions.textToBe(By.cssSelector("#s-top-left > a:nth-child(1)"), "新闻"));
        driver.close();
    }

ExpectedConditions预定义⽅法的⼀些⽰例:

• elementToBeClickable(By locator) ‒ ⽤于检查元素的期望是可⻅的并已启⽤,以便您可以单击它。

textToBe(Bylocator,String str) - 检查元素。(精确匹配)

• presenceOfElementLocated(Bylocator) ‒ 检查⻚⾯的 DOM 上是否存在元素。

• urlToBe(java.lang.String url) ‒ 检查当前⻚⾯的 URL 是⼀个特定的 URL。

优点:显⽰等待是智能等待,可以⾃定义显⽰等待的条件,操作灵活

缺点:写法复杂

隐式等待和显⽰等待⼀起使⽤效果如何呢?

测试⼀下

java 复制代码
//隐式等待设置为5s,显⽰等待设置为10s,那么结果会是5+10=15s吗?

SimpleDateFormat sim =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

System.out.println(sim.format(System.currentTimeMillis()));

        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));

        driver.findElement(By.cssSelector("#hotsearch-content-wrapper > li:nth

        child(1) > a > span.title-content"));

WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10));

        try{

        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#hotsear

        ch-content-wrapper > li:nth-child(1) > a > span.title-content")));

        }catch (Exception e){

        System.out.println("nosuelement!");

}

        System.out.println(sim.format(System.currentTimeMillis()));

结果:重试多次,最终打印的等待时间有10s、11s....

结论:不要混合隐式和显式等待,可能会导致不可预测的等待时间。

5.浏览器导航

常⻅操作:

1)打开⽹站

// 更⻓的⽅法

driver.navigate().to("https://selenium.dev");

// 简洁的⽅法

driver.get("https://selenium.dev");

2)浏览器的前进、后退、刷新

driver.navigate().back();

driver.navigate().forward();

driver.navigate().refresh();

案例:百度⾸⻚测试https://tool.lu/标签⼊⼝

6. 弹窗

弹窗是在⻚⾯是找不到任何元素的,这种情况怎么处理?使⽤selenium提供的Alert接⼝

6.1 警告弹窗+确认弹窗

Alert alert = driver.switchTo.alert();

//确认

alert.accept()

//取消

alert.dismiss()

6.2 提⽰弹窗

Alert alert = driver.switchTo.alert();

alert.sendKeys("hello");

alert.accept();

alert.dismiss();

7. ⽂件上传

点击⽂件上传的场景下会弹窗系统窗⼝,进⾏⽂件的选择。

selenium⽆法识别⾮web的控件,上传⽂件窗⼝为系统⾃带,⽆法识别窗⼝元素

但是可以使⽤sendkeys来上传指定路径的⽂件,达到的效果是⼀样的

WebElement ele = driver.findElement(By.cssSelector("body > div > div > input[type=file]"));

ele.sendKeys("D:\\selenium2html\\selenium2html\\upload.html");

8、浏览器参数设置

1)设置⽆头模式

无头模式:在后台执行,不会显示打开浏览器,看不到效果

2)设置浏览器加载策略

options.setPageLoadStrategy(PageLoadStrategy.NONE);

注意:存在网页的特殊情况,手动打开页面立即渲染,但通过自动化打开却很慢,甚至超过隐式时间等待

相关推荐
KnowSafe4 天前
使用HTTPS对搜索引擎SEO有用吗?
dubbo
程序员小潘6 天前
Dubbo 序列化类检查和自动信任机制
java·dubbo
武子康8 天前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
百度SEO专员10 天前
2025最新蜘蛛池在百度SEO中的应用
dubbo
程序员的世界你不懂10 天前
Jmeter常见问题分析(1)乱码问题
jmeter·dubbo
武子康13 天前
Java-78 深入浅出 RPC Dubbo 负载均衡全解析:策略、配置与自定义实现实战
java·数据库·分布式·后端·缓存·rpc·dubbo
武子康16 天前
Java-77 深入浅出 RPC Dubbo 负载均衡全解析:策略、配置与自定义实现实战
java·分布式·后端·spring·微服务·rpc·dubbo
武子康18 天前
Java-75 深入浅出 RPC Dubbo Java SPI机制详解:从JDK到Dubbo的插件式扩展
java·分布式·后端·spring·微服务·rpc·dubbo
Easonmax19 天前
文心一言4.5深度评测:国产大模型的崛起之路
dubbo