介绍几个自动化测试前端页面的时候使用到的,常用的 puppeteer
技巧,了解这些技巧,定能让你的自动化测试过程事半功倍。如果在此基础之上能够融会贯通,左右逢源,则前端测试之旅岂不直接起飞,入无人之境?
1. puppeteer 代码基本框架
- 首先,通过
require
引入 puppeteer 模块。 - 定义要打开的页面 URL。
- 使用异步自执行函数进行浏览器和页面的操作。
- 通过
puppeteer.launch
启动浏览器实例,可以设置启动参数如--no-sandbox
和--disable-setuid-sandbox
用于 Docker 或无头环境。但注意,headless:'new'
是不正确的,应该是headless: true
或headless: false
。 - 使用
browser.newPage()
创建一个新页面。 - 使用
page.goto
导航到指定的 URL,并等待页面加载完成。这里的waitUntil
数组定义了页面加载完成的标准。 - 在代码框架中编写自己的测试逻辑。
- 使用
browser.close()
关闭浏览器实例。 - 如果在过程中遇到错误,使用
console.error
输出错误信息,并使用process.exit(1)
结束进程。
javascript
const puppeteer = require("puppeteer");
const pageUrl = "http://127.0.0.1:8080";
(async () => {
try {
const browser = await puppeteer.launch({
args: ["--no-sandbox", "--disable-setuid-sandbox"],
headless:'new',
});
const page = await browser.newPage();
await page.goto(pageUrl, {
// 如果页面没有请求可以不加 waitUntil 数组中的后 2 项
waitUntil: ["domcontentloaded", "load", 'networkidle0', 'networkidle2'],
});
// 如果不是分步骤判分,使用 process.exit(1) 表示检查未通过;
// ...... 在下面编写自己的测试代码 start
//...... 你的测试代码
//.... 自己的测试代码 end
browser.close();
} catch (error) {
console.error(`测试未通过,报错为${error}`)
process.exit(1);
}
})();
2. 结束检测,提示错误信息
- 当检测失败时,使用
console.error
输出错误信息。 - 使用
process.exit(1)
结束进程,表示检测失败。
arduino
console.error("Error:.address、.user-info 元素获取不到!");
process.exit(1); // 结束进程,检测失败
3. 延时(用于 DOM 点击过后正确获取dom 等情况)
- 由于某些操作可能需要等待 DOM 更新或其他异步任务完成,因此需要使用延时。
- 这里提供了一个使用 Promise 的延时函数
delay
,可以替换已废弃的page.waitForTimeout
。
javascript
let delay = (ms)=>new Promise((r) => setTimeout(r, ms)); // ms 换成自己的延迟时间就可以
await delay(300)
4. 获取元素及相关信息
- 使用
page.$$eval
获取多个匹配选择器的元素。 - 使用
page.$$eval
对获取到的元素执行函数,并返回结果。例如,获取元素的 value 属性。 - 根据获取到的信息进行判断,如果不满足条件,则输出错误信息并结束进程。
javascript
// 获取多个元素
let optionEls = await page.$$(selector);
// 获取多个元素的相关信息
let leftSelect = await page.$$eval(selector,(el) => el);
optionValues = await page.$$eval(selector,
(optionEls) =>
optionEls.map((optionEl) => optionEl.value)
);
if (optionValues) {
if(optionValues.includes('闷油瓶')||optionValues.includes('三叔')){
console.error(
`Error:${selector == "left" ? "左" : "右"}边的多选选项并没有被移除掉!`
);
process.exit(1); // 结束进程,检测失败
}
}
5. 根据文本内容获取元素
- 使用 XPath 表达式
//*[text()='登录']
查找文本内容为"登录"的元素。注意,这种方式对文本内容非常敏感,如果文本中存在空格或其他不可见字符,可能会导致找不到元素。 - 找到元素后,可以进行点击等操作。
swift
// 假设按钮的文本内容为登录
let btn = await page.$x(`//*[text()='登录']`)
await btn[0].click()
6. 点击元素
- 提供了两种方式点击元素:直接通过选择器点击和使用
page.evaluate
执行 JavaScript 点击。第一种方式在某些情况下可能无效,特别是当元素是浮动定位或受到其他因素影响时。此时,可以尝试第二种方式。
javascript
// 方式一
const singleClick = async (page,selector) => {
let markEl = await page.$(selector);
if(!markEl){
console.error(`Error:找不到 ${selector} 元素!`);
process.exit(1); // 结束进程,检测失败
}
await page.click(selector); // 这种方式有时候会出现无效的情况,如果发现,请使用方式二
}
// 浮动定位的元素使用 page.click 可能会造成无法点击,使用下面方式
// 方式二
await page.evaluate((selector) => {
document.querySelector(selector) && document.querySelector(selector).click();
},selector);
7. 点击列表元素的某一个
- 可以通过
page.$$
获取元素列表,然后通过索引点击特定元素。 - 例如,
btn[0].click()
点击第一个按钮。 - 另一种方式是使用CSS选择器直接定位并点击特定元素,如
.item:nth−child(1)
表示点击第一个item
元素。
csharp
// 方式一 通过 $$获取 通过索引点击
await page.$$('.btn')
await btn[0].click() // 点击第一个 btn 元素
// 方式 2
// 以 item 为例,点击第一个 item
await page.click('.item:nth-type-of(1)')
8. 获取页面变量 (只能获取全局变量)
使用 page.evaluate
执行 JavaScrip t代码并返回结果。在这里,可以访问并返回页面中的全局变量。但需要注意的是,page.evaluate
中的代码是在页面上下文中执行的,所以只能访问页面中的全局变量和函数。
javascript
let res = await page.evaluate(() => option); // 将 option 替换成页面中的变量
9. 清空 input 并输入示例
提供了一个函数 clearAndType
,用于清空指定选择器的 input
元素并输入文本。首先,使用 page.evaluate
清空 input
元素的值,然后使用 page.type
输入文本。这个函数在需要自动化填写表单时非常有用。
javascript
const clearAndType = async (selector, text) => {
await page.evaluate((selector) => {
const textarea = document.querySelector(selector);
textarea.value = '';
}, selector);
await page.type(selector, text);
};
// 使用示例
await clearAndType('input','小')
10. 检测 ajax 请求是否成功
- 定义了一个函数
checkAjax
来检测页面是否发送了特定的 AJAX 请求。 - 首先,监听页面的所有响应并记录
URL
。 - 然后,导航到指定页面并等待所有网络请求完成。
- 最后,检查记录的
URL
列表中是否包含要检测的AJAX
请求的URL
。如果不包含,则输出错误信息并结束进程。 - 这个函数在需要验证页面功能是否通过
AJAX
请求实现时非常有用。但需要注意的是,这种方式只能检测是否发送了请求,并不能直接判断请求是否成功或返回了期望的结果。如果需要进一步验证请求的结果,可能需要结合其他方法或工具来实现。
javascript
/**
* 异步请求数据检测
* url: 接口地址(域名与待检测域名相同)
**/
const checkAjax = async (page,pageUrl,jsonUrl)=>{
const urls = [];
page.on("response", (response) => {
urls.push(response.url());
});
await page.goto(pageUrl, {
waitUntil: "networkidle0", //一直等待所有网络请求完成后再触发
});
// console.log(urls);
// 验证是否发送 ajax 请求
if (!urls.includes(jsonUrl)) {
console.error(`没有请求到数据!`);
process.exit(1); // 结束进程,检测失败
}
}