⾃动化
⾃动化测试
- ⾃动的代替⼈的⾏为完成操作
- ⾃动化在⽣活中处处可⻅
制造业自动化:
- 机器人装配线:在汽车制造中,机器人可以自动组装汽车的各个部件。
- 自动化焊接:在金属加工中,自动化焊接机器人可以精确地焊接金属部件。家庭自动化:
- 智能恒温器:可以根据居住者的习惯自动调节室内温度。
- 智能照明系统:可以根据时间或光线强度自动开关灯。办公自动化:
- 电子邮件过滤:自动将电子邮件分类到不同的文件夹或标记为垃圾邮件。
- 文档审批流程:自动化的工作流程可以加快文档审批过程。金融服务自动化:
- 自动取款机(ATM):允许用户无需银行职员即可进行现金提取和存款。
- 算法交易:在金融市场中,算法可以自动执行交易指令。农业自动化:
- 自动驾驶拖拉机:可以在没有驾驶员的情况下耕种和收割作物。
- 无人机监测:使用无人机来监测作物的生长状况和健康。物流自动化:
- 自动化仓库:使用机器人和自动化系统来存储、检索和运输货物。
- 自动化包裹分拣系统:在快递中心,自动化系统可以快速准确地将包裹分拣到正确的目的地。医疗自动化:
- 实验室自动化:自动化设备可以进行样本分析和测试。
- 药物分配系统:在医院中,自动化系统可以管理药物的存储和分发。客户服务自动化:
- 聊天机器人:在线客服可以通过聊天机器人自动回答常见问题。
- 自动语音响应系统:电话系统中的IVR(Interactive Voice Response)可以自动处理客户的查询。内容创作自动化:
- 文章生成器:可以自动生成新闻报道或博客文章的初稿。
- 图像和视频编辑:软件可以自动调整图像和视频的色彩、对比度等。网络安全自动化:
- 入侵检测系统:可以自动监测和响应网络安全威胁。
- 漏洞扫描:自动化工具可以扫描系统以识别潜在的安全漏洞。
回归测试
- 软件有多个版本需要进⾏功能的整体回归
- 为了避免新增功能影响到历史的功能需要进⾏功能的回归
常⻅⾯试题
⾃动化测试能够取代⼈⼯测试吗?
⾃动化测试不⼀定⽐⼈⼯测试更能保障系统的可靠性,⾃动化测试是测试⼈员⼿⼯编写,后续如果有 功能的变更⾃动化也需要进⾏不定期的维护和更新
⾃动化测试可以⼤幅度降低⼯作量?
错误 坑!!“⼀定程度上”和“⼤幅度”的表达⽅式也需要注意 tips:测试笔试中的选择题尽量不要选择说的太死或者太绝对的选项~~~~
⾃动化分类
- 讲⾃动化分类的⽬的是避免同学们将⾃动化混淆,同时避免讲不同的⾃动化如何实施造成的课时 压⼒
- 很多同学经常听到⾃动化这个词,但是很容易误以为⾃动化就是⼀个东西,⾃动化是个统称,同 学们可以理解为我们常说的吃⽠这样的表达⽅式和⾃动化是⼀样的,吃⽠可以是吃西⽠,吃哈密 ⽠,吃⾹⽠,⾃动化也包含多种,如接⼝⾃动化,web⾃动化,移动端⾃动化等等...
- 主要介绍各测试分类为什么需要实施⾃动化,⽬的和意义
接⼝⾃动化
什么是接⼝⾃动化测试?
为什么要做?解决了什么问题,⽬的是什么
UI⾃动化
UI测试也称为界⾯测试,常⻅的UI⾃动化测试包含web⾃动化测试、移动端⾃动化测试等等。
移动端⾃动化测试
移动端⾃动化测试 什么是移动端⾃动化测试?
为什么要做?解决了什么问题,⽬的是什么
移动端,顾名思义,就是部署在⼿机上的应⽤程序。移动端⾃动化测试主要测试程序部署在⼿机上能 否按照预期的结果的进⾏操作。
- 移动端测试通常不是将程序部署在移动端上进⾏测试,⽽是需要安装模拟器,在电脑上编写⾃动化测 试脚本代码对模拟器上的软件进⾏操作
- 移动端测试难度相对较⼤,移动端测试的稳定性要⽐接⼝⾃动化测试和web⾃动化测试的稳定性要差 很多,原因主要是移动端测试收到的环境影响⽐较多,诸如什么呢????
Web⾃动化测试
- 什么是web⾃动化测试?
- 为什么要做?解决了什么问题,⽬的是什么
- 如何进⾏百度搜索?
- 通常来说我们⼿动进⾏百度搜索的步骤如下,web⾃动化能够代替我们⾃动的执⾏
模拟⼈在浏览器上的操作⾏为,⾃动的打开浏览器,访问百度⾸⻚,并进⾏⼀系列的搜索和验证等⾏为。
⾃动化测试⾦字塔
理想的⾃动化测试⾦字塔表达了⾃动化测试的理想情况,利⽤较少的时间和精⼒在单元测试上就能够 发现更多有效的问题
然后实际上在企业中,⾃动化往往是“冰淇淋蛋筒反模式”
⾃动化需要⼤量的初始投资,找到“突破点”,与⼿动测试相⽐,我们开始看到它对⻓期成本产⽣的 积极影响,也能够清楚,这两种测试活动都是完全兼容,产⽣短期和⻓期利益。
web⾃动化测试
驱动
上⾯给⼤家已经介绍过,web系统的测试前提是需要打开浏览器,通过访问web服务器来对服务器界 ⾯进⾏⼀系列的操作。对于⼿⼯测试来说,这⼀系列的操作都需要测试⼈员⼿动的,⼀步⼀步的来执 ⾏测试。那么对于⾃动化程序来说,程序如何才能打开浏览器并执⾏我们预期的操作流程呢?
驱动⼀词应⽤⼴泛,同学们都不会陌⽣
⻋有了驱动才能够让⻋跑起来。
计算机有了驱动程序就可以与设备(耳机,摄像头,麦克风,键盘,显示器等等设备)进行通信
程序想要打开web浏览器就需要安装web驱动(即WebDriver),WebDriver 以本地化⽅式驱动浏览 器
安装驱动管理
驱动管理
WebDriverManager是⼀个开源Java库,以完全⾃动化的⽅式对Selenium WebDriver所需的驱动程 序(如chromedriver、geckodriver、msedgedriver等)进⾏管理(即下载、设置和维护),⾃版 本5起,WebDriverManager还提供了其他相关功能,如发现本地系统中安装的浏览器的能⼒,构建 WebDriver对象(如ChromeDriver、FirefoxDriver、EdgeDriver等)
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.8.0</version>
</dependency>
Selenium
- 万事俱备,只⽋东⻛
- 接下来就是使⽤selenium来编写web⾃动化测试脚本
- selenium是⼀个web⾃动化测试⼯具,selenium中提供了丰富的⽅法供给使⽤者进⾏web⾃动化测 试
- ⼀个简单的web⾃动化⽰例
安装selenium库
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.21.0</version>
</dependency>
使⽤selenium编写代码
public class FirstTest {
//测试百度搜索关键词;迪丽热巴
void test01() throws InterruptedException {
//1. 打开浏览器 使用驱动来打开
WebDriverManager.chromedriver().setup();
//增加浏览器配置:创建驱动对象要强制指定允许访问所有的链接
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
WebDriver driver = new ChromeDriver(options);
Thread.sleep(3000);
//2. 输入完整的网址:https://www.baidu.com
driver.get("https://www.baidu.com");
Thread.sleep(3000);
//3. 找到输入框,并输入关键词:迪丽热巴
driver.findElement(By.cssSelector("#kw")).sendKeys("迪丽热巴");
Thread.sleep(3000);
//4. 找到百度一下按钮,并点击
driver.findElement(By.cssSelector("#su")).click();
Thread.sleep(3000);
//5. 关闭浏览器
driver.quit();
}
}
selenium+驱动+浏览器的⼯作原理
实现web⾃动化测试需要浏览器、浏览器驱动、selenium⾃动化脚本。这三者是如何交互最终实现 web的⾃动化测试?
- 通过selenium编写的⾃动化脚本代码中在ChromeDriverService中创建⼀个服务
- 通过创建好的服务打开webdriver,安装在本地的驱动服务IP为localhost,PORT为 ChromeDriverService中创建的端⼝号,该服务地址为selenium向webdriver发送请求的服务地 址
- 向浏览器驱动程序发送HTTP请求,浏览器驱动程序解析请求,打开浏览器,并获得sessionid,如 果再次对浏览器操作需携带此id
- 打开浏览器后,所有的selenium的操作(访问地址,查找元素等)均通过创建好的服务链接到 webdriver,然后使⽤execute发送请求
- 驱动收到请求并对请求进⾏解析,转成浏览器能够解析的脚本并发送给浏览器,浏览器通过请求的 内容执⾏对应动作
- 浏览器再把执⾏的动作结果通过浏览器驱动程序返回给测试脚本
驱动需要接收、解析请求,发送请求给浏览器,那么驱动到底是什么样的⻆⾊呢?
验证⽅式:
执⾏selenium编写的⾃动化脚本代码中,可以在终端看到创建的驱动服务地址。
⾃动化测试常⽤函数
元素的定位
web⾃动化测试的操作核⼼是能够找到⻚⾯对应的元素,然后才能对元素进⾏具体的操作
常⻅的元素定位⽅式⾮常多,如id,classname,tagname,xpath,cssSelector
常⽤的主要由cssSelector和xpath
cssSelector
选择器的功能:选中⻚⾯中指定的标签元素
选择器的种类分为基础选择器和复合选择器,常⻅的元素定位⽅式可以通过id选择器和⼦类选择器来 进⾏定位。
- 定位百度⾸⻚的“百度热搜”元素,可以使⽤通过id选择器和⼦类选择器进⾏定位:#s-hotsearchwrapper > div
- “搜索输⼊框元素”:#kw “
- 百度⼀下按钮”:#su
xpath
XML路径语⾔,不仅可以在XML⽂件中查找信息,还可以在HTML中选取节点
xpath使⽤路径表达式来选择xml⽂档中的节点
xpath语法中:
- 获取HTML⻚⾯所有的节点
//*
- 获取HTML⻚⾯指定的节点
//[指定节点]
//ul :获取HTML⻚⾯所有的ul节点
//input:获取HTML⻚⾯所有的input节点
- 获取⼀个节点中的直接⼦节点
//span/input
- 获取⼀个节点的⽗节点
..
//input/.. 获取input节点的⽗节点
- 实现节点属性的匹配
[@...]
//*[@id='kw'] 匹配HTML⻚⾯中id属性为kw的节点
- 使⽤指定索引的⽅式获取对应的节点内容
- 注意:xpath的索引是从1开始的。
百度⾸⻚通过://div/ul/li[3] 定位到第三个百度热搜标签
更便捷的⽣成selector/xpath的⽅式:右键选择复制"Copy selector/xpath"
注意:元素的定位⽅法必须唯⼀
- 案例:如果想要匹配到百度⾸⻚指定的新闻⽂本或者节点集,直接使⽤ #hotsearch-contentwrapper > li 能够满⾜吗?
- 问题:既然可以⼿动复制 selector/xpath的⽅式 ,为什么还有了解语法?
- ⼿动复制的selector/xpath表达式并不⼀定满⾜上⾯的唯⼀性的要求,有时候也需要⼿动的进⾏修改表 达式
- 案例:百度⾸⻚(需要登陆百度账号)右侧的热搜,复制li标签下的a标签,复制好的的selector为: #title-content ,xpath为: //*[@id="title-content"] ,可以⼿动操作⼀下, ⼿动复制的表达式是否唯⼀呢?
操作测试对象
获取到了⻚⾯的元素之后,接下来就是要对元素进⾏操作了。常⻅的操作有点击、提交、输⼊、清 除、获取⽂本
点击/提交对象
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 bdtext = driver.findElement(By.xpath("//*[@id="title-content"]/span[1]")).getText();
System.out.println("打印的内容是:"+bdtext);
问题:是否可以通过 getText() 获取到“百度⼀下按钮”上的⽂字“百度⼀下”呢?尝试⼀下
注意:⽂本和属性值不要混淆了。获取属性值需要使⽤⽅法 getAttribute("属性名称")
获取当前⻚⾯标题
getTitle()
获取当前⻚⾯URL
getCurrentUrl()
窗⼝
打开⼀个新的⻚⾯之后获取到的title和URL仍然还是前⼀个⻚⾯的?
当我们⼿⼯测试的时候,我们可以通过眼睛来判断当前的窗⼝是什么,但对于程序来说它是不知道当 前最新的窗⼝应该是哪⼀个。对于程序来说它怎么来识别每⼀个窗⼝呢?每个浏览器窗⼝都有⼀个唯一的属性句柄(handle)来表⽰,我们就可以通过句柄来切换
切换窗⼝
获取当前⻚⾯句柄
driver.getWindowHandle();
获取所有⻚⾯句柄
driver.getWindowHandles()
切换当前句柄为最新⻚⾯
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for( String w : allWindow){
if(w!=curWindow){
driver.switchTo().window(w);
}
}
注意:执⾏了driver.close()之前需要切换到未被关闭的窗⼝
窗⼝设置⼤⼩
窗⼝的⼤⼩设置
//窗⼝最⼤化
driver.manage().window().maximize();
//窗⼝最⼩化
driver.manage().window().minimize();
//全屏窗⼝
driver.manage().window().fullscreen();
//⼿动设置窗⼝⼤⼩
driver.manage().window().setSize(new Dimension(1024, 768));
窗⼝切换
去掉等待后,获取跳转后的⻚⾯元素失败
//获取所有句柄
//获取当前停留⻚⾯句柄
String curWindow = driver.getWindowHandle();
Set<String> allWindow = driver.getWindowHandles();
for( String w : allWindow){
if(w!=curWindow){
driver.switchTo().window(w);
}
}
屏幕截图
我们的⾃动化脚本⼀般部署在机器上⾃动的去运⾏,如果出现了报错,我们是不知道的,可以通过抓 拍来记录当时的错误场景
屏幕截图⽅法需要额外导⼊包:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(file,new File(filename));
代码演⽰
//简单版本
File srcfile = driver.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcfile,new File("my.png"));
//⾼阶版本
List<String> times = getTime();
//⽣成的⽂件夹路径./src/test/autotest-2022-08-01/goodsbroser-20220801-214130.png
String filename ="./src/test/autotest-"+times.get(0)+"/"+str+"-
"+times.get(1)+".png";
File srcfile = driver.getScreenshotAs(OutputType.FILE);
//把屏幕截图放到指定的路径下
FileUtils.copyFile(srcfile,new File(filename));
关闭窗⼝
driver.close();
注意:窗⼝关闭后driver要重新定义
等待
通常代码执⾏的速度⽐⻚⾯渲染的速度要快,如果避免因为渲染过慢出现的⾃动化误报的问题呢?可 以使⽤selenium中提供的三种等待⽅法
强制等待
Thread.sleep()
- 优点:使⽤简单,调试的时候⽐较有效
- 缺点:影响运⾏效率,浪费⼤量的时间
隐式等待
隐式等待是⼀种智能等待,他可以规定在查找元素时,在指定时间内不断查找元素。如果找到则代码 继续执⾏,直到超时没找到元素才会报错。
implicitlyWait() //参数:Duration类中提供的毫秒、秒、分钟等⽅法
//隐式等待1000毫秒
driver.manage().timeouts().implicitlyWait(Duration.ofMillis(1000));
//隐式等待5秒
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
- 隐式等待作⽤域是整个脚本的所有元素。即只要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();
案例:百度⾸⻚测试https://tool.lu/标签⼊⼝
弹窗
弹窗是在⻚⾯是找不到任何元素的,这种情况怎么处理?使⽤selenium提供的Alert接⼝
Alert alert = driver.switchTo.alert();
//确认
alert.accept()
//取消
alert.dismiss()
提⽰弹窗
Alert alert = driver.switchTo.alert();
alert.sendKeys("hello");
alert.accept();
alert.dismiss();
⽂件上传
- 点击⽂件上传的场景下会弹窗系统窗⼝,进⾏⽂件的选择
- selenium⽆法识别⾮web的控件,上传⽂件窗⼝为系统⾃带,⽆法识别窗⼝元素
- 但是可以使⽤sendkeys来上传指定路径的⽂件,达到的效果是⼀样的
WebElement ele = driver.findElement(By.cssSelector("body > div > div >
input[type=file]"));
ele.sendKeys("D:\\selenium2html\\selenium2html\\upload.html");
浏览器参数设置
设置⽆头模式
ChromeOptions options = new ChromeOptions();
options.addArguments("-headless");
ChromeDriver driver = new ChromeDriver(options);
driver.get("https://www.baidu.com");
driver.quit();
设置浏览器加载策略
options.setPageLoadStrategy(PageLoadStrategy.NONE);