【测试开发】----自动化测试selenium篇

什么是自动化测试

自动化测试指软件测试的自动化,**在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最****后评估运行结果。**将人为驱动的测试行为转化为机器执行的过程。

单元测试

最大的投入应该在单元测试上,单元测试运行的频率也更加高。

为什么要使用自动化测试

web⾃动化测试

实际在企业中,我们需要对某⼀个特定的软件进⾏⾃动化的实施,包含但不限于软件所有界⾯的UI⾃动化测试、所有接⼝的接⼝⾃动化测试。

上⾯给⼤家已经介绍过,web系统的测试前提是需要打开浏览器,通过访问web服务器来对服务器界⾯进⾏⼀系列的操作。对于⼿⼯测试来说,这⼀系列的操作都需要测试⼈员⼿动的,⼀步⼀步的来执⾏测试。那么对于⾃动化程序来说,程序如何才能打开浏览器并执⾏我们预期的操作流程呢?
驱动⼀词应⽤⼴泛,同学们都不会陌⽣。⻋有了驱动才能够让⻋跑起来。
计算机有了驱动程序就可以与设备(⽿机,摄像头,⻨克⻛,键盘,显⽰器等等设备)进⾏通信。
程序想要打开web浏览器就需要安装web驱动(即WebDriver),WebDriver 以本地化⽅式驱动浏览器

安装驱动管理

引入依赖

复制代码
<dependency>
    <groupId>io.github.bonigarcia</groupId>
    <artifactId>webdrivermanager</artifactId>
     <version>5.8.0</version>
     <scope>test</scope>
</dependency>

Selenium

selenium是⼀个web⾃动化测试⼯具,selenium中提供了丰富的⽅法供给使⽤者进⾏web⾃动化测
试。

安装selenium库

复制代码
<dependency>
 <groupId>org.seleniumhq.selenium</groupId>
 <artifactId>selenium-java</artifactId>
 <version>4.0.0</version>
</dependency>

使⽤selenium编写代码

复制代码
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class depend {
    public static void test1(){
        //使用 WebDriverManager 自动管理 ChromeDriver 的初始化语句
        WebDriverManager.chromedriver().setup();
        //允许访问所有链接
        ChromeOptions chromeOptions=new ChromeOptions();
        chromeOptions.addArguments("--remote-allow-origins=*");
        //使用 Selenium WebDriver 创建了一个 Chrome 浏览器实例,并应用了自定义配置 chromeOptions。
        WebDriver driver=new ChromeDriver(chromeOptions);
        //2.输⼊百度⽹址:https://www.baidu.com
        driver.get("https://www.baidu.com");
        //3、找到输⼊框并输⼊"迪丽热巴"
        driver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
        //4、找到"百度⼀下"按钮并点击
        driver.findElement(By.cssSelector("#su")).click();
        try {
            //强制等待3秒
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        //5、关闭浏览器
        driver.quit();
    }
}

selenium+驱动+浏览器的⼯作原理

实现web⾃动化测试需要浏览器、浏览器驱动、selenium⾃动化脚本。这三者是如何交互最终实现
web的⾃动化测试?

元素的定位

web⾃动化测试的操作核⼼是能够找到⻚⾯对应的元素,然后才能对元素进⾏具体的操作。
常⻅的元素定位⽅式⾮常多,如id,classname,tagname,xpath,cssSelector
常⽤的主要由cssSelector和xpath

cssSelector

选择之后,点哪里,就可以定位到那里的代码


ctrl+f是大部分的选择框

在复制之后,可能会出现一些意外,我们可以在这个选择框里面复制进去试试
定位百度⾸⻚的"百度热搜"元素,可以使⽤通过id选择器和⼦类选择器进⾏定位:#s-hotsearch
wrapper > div

如果想要匹配到百度⾸⻚指定的新闻⽂本或者节点集:,直接使⽤ #hotsearch-content
wrapper > li 能够满⾜吗?
问题:既然可以⼿动复制 selector/xpath的⽅式 ,为什么还有了解语法

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

操作测试对象

点击/提交对象
click()

复制代码
driver.findElement(By.cssSelector("#su")).click();

模拟按键输⼊
sendKeys("")

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

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

复制代码
driver.findElement(By.cssSelector("#kw")).sendKeys("我爱游戏");
driver.findElement(By.cssSelector("#kw")).clear();
driver.findElement(By.cssSelector("#kw")).sendKeys("我爱学习");

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

复制代码
String text=driver.findElement(By.cssSelector("#hotsearch-content-wrapper > li:nth-child(1) > a > span.title-content-title")).getText();
        System.out.println(text);

问题:是否可以通过 getText() 获取到"百度⼀下按钮"上的⽂字"百度⼀下"呢?尝试⼀下
注意:⽂本和属性值不要混淆了。获取属性值需要使⽤⽅法 getAttribute("属性名称")
获取当前⻚⾯标题
getTitle()
获取当前⻚⾯URL
getCurrentUrl()

窗⼝

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

切换窗⼝

获取当前⻚⾯句柄:

java 复制代码
driver.getWindowHandle()

获取所有⻚⾯句柄:

java 复制代码
driver.getWindowHandles()

切换当前句柄为最新⻚⾯:
Selenium 默认仍聚焦在原始窗口 ,若要操作新窗口中的元素(如输入账号密码、点击新窗口的按钮),必须先切换到新窗口,否则会因 "找不到元素" 而报错。

java 复制代码
public void test2(){
        createDriver();
        String curWindow = driver.getWindowHandle();
        driver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
        Set<String> allWindow = driver.getWindowHandles();
        for( String w : allWindow){ if(w!=curWindow){
            driver.switchTo().window(w);
        }
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        String  text= driver.findElement(By.cssSelector("#pane-news > div > ul > li.hdline0 > strong > a")).getText();
        System.out.println(text);
    }
}
java 复制代码
String curWindow = driver.getWindowHandle(); 
Set<String> allWindow = driver.getWindowHandles();
 for( String w : allWindow){ if(w!=curWindow){
 driver.switchTo().window(w);
 }
}

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

java 复制代码
//窗⼝最⼤化
driver.manage().window().maximize();
//窗⼝最⼩化
driver.manage().window().minimize();
//全屏窗⼝
driver.manage().window().fullscreen();
//⼿动设置窗⼝⼤⼩
driver.manage().window().setSize(new Dimension(1024, 768));

屏幕截图

我们的⾃动化脚本⼀般部署在机器上⾃动的去运⾏,如果出现了报错,我们是不知道的,可以通过抓 拍来记录当时的错误场景
屏幕截图⽅法需要额外导⼊包:

java 复制代码
<dependency>
 <groupId>commons-io</groupId>
 <artifactId>commons-io</artifactId>
 <version>2.6</version>
 </dependency>

简单版本

复制代码
 File file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        try {
            FileUtils.copyFile(file,new File("my.png"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

高级版本

复制代码
 public void createShots(String str){
        SimpleDateFormat sim1 =new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sim2 =new SimpleDateFormat("HHmmssSS");
        String dirTime= sim1.format(System.currentTimeMillis());
        String fileTime=sim2.format(System.currentTimeMillis());
        String fileName="./src/test/img/"+dirTime+"/"+str+"-"+fileTime+".png";
        File file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        try {
            FileUtils.copyFile(file,new File(fileName));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

调用这个函数

复制代码
 createShots(Thread.currentThread().getStackTrace()[1].getMethodName());

关闭窗⼝

复制代码
driver.close();

注意:窗⼝关闭后driver要重新定义

复制代码
 driver.close();
        driver.switchTo().window(curWindow);
        Set<String> windows = driver.getWindowHandles();
        for(String s:windows){
            System.out.println(s);
        }
        driver.close();
        driver.quit();

等待

为什么要有等待呢?

因为我们在访问一些网页的时候,会出现跳转的情况,跳转后我们可能进行了一些元素查找等操作,我们如果不等待直接进行查找,就会找不到元素(自动化太快了)

怎么处理动态元素的问题呢?

强制等待

Thread.sleep()
优点:使⽤简单,调试的时候⽐较有效
缺点:影响运⾏效率,浪费⼤量的时间

隐式等待

隐式等待是⼀种智能等待,他可以规定在查找元素时,在指定时间内不断查找元素。如果找到则代码
继续执⾏,直到超时没找到元素才会报错。
implicitlyWait() 参数:Duration类中提供的毫秒、秒、分钟等⽅法

复制代码
  driver.manage().timeouts().implicitlyWait(Duration.ofMillis(3000));

隐式等待作⽤域是整个脚本的所有元素。即只要driver对象没有被释放掉(driver.quit()),隐式等待就⼀直⽣效。
优点:智能等待,作⽤于全局
缺点:只对查找元素起效果

这个时候,我们只负责找,但后面的传送,点击,清理.....不管
我们当前行能找到那个名字,但是这个名字现在还是迪丽热巴的名字,没有转化成邓紫棋的名字。

那怎么解决呢?我们可以引进显示等待

显示等待

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

复制代码
new WebDriverWait(driver, Duration.ofSeconds(3)).until($express)

$press:涉及到selenium.support.ui.ExpectedConditions包下的ExpectedConditions类
返回值:boolean

复制代码
WebDriverWait foo = new WebDriverWait(driver, Duration.ofSeconds(3))
foo.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#id")));

ExpectedConditions预定义⽅法的⼀些⽰例

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

  • 可以单击它。

  • textToBe(Bylocator,String str) - 检查元素。

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

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

    WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10));
    boolean ispass = wait.until(ExpectedConditions.textToBe(By.cssSelector("#s-topleft > a:nth-child(1)"), "新闻"));
    if(ispass){
    System.out.println("测试通过");
    }else {
    System.out.println("测试失败");
    }

优点:显⽰等待是智能等待,可以⾃定义显⽰等待的条件,操作灵活
缺点:写法复杂
隐式等待和显⽰等待⼀起使⽤效果如何呢?
测试⼀下

复制代码
//隐式等待设置为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:nthchild(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....
结论:不要混合隐式和显式等待,可能会导致不可预测的等待时间。

浏览器导航

打开⽹站

复制代码
// 更⻓的⽅法
driver.navigate().to("https://selenium.dev");
// 简洁的⽅法
driver.get("https://selenium.dev");

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

复制代码
driver.navigate().back();
driver.navigate().forward();
driver.navigate().refresh();

弹窗

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

警告弹窗+确认弹窗

复制代码
Alert alert = driver.switchTo.alert();
//确认
alert.accept()
//取消
alert.dismiss()

提⽰弹窗

复制代码
Alert alert = driver.switchTo.alert();
alert.sendKeys("hello");
alert.accept();
alert.dismiss();
相关推荐
上官鹿离5 小时前
Selenium教程(Python 网页自动化测试脚本)
python·selenium·测试工具
whabc1001 天前
ubuntu24.04安装selenium、chrome、chromedriver
chrome·selenium·测试工具
惜.己1 天前
selenium获取元素 出现的错误AttributeError: ‘TestPage‘ object has no attribute ‘driver‘
python·selenium·pycharm
吃饱了想撑死1 天前
Postman四种请求教程
测试工具·postman
大白曾是少年2 天前
基于Postman进行http的请求和响应
测试工具·http·postman
成成成成成成果3 天前
揭秘动态测试:软件质量的实战防线
python·功能测试·测试工具·测试用例·可用性测试
卓码软件测评3 天前
软件测评中网站类测评测试使用的BurpSuite-Web安全测试流程
测试工具·安全·web安全
测试狗科研平台3 天前
TEM在量子点发光材料领域的应用-测试GO
测试工具·量子计算·材料工程
测试老哥3 天前
如何写好测试用例?
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例