- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
网页在提测流转给 QA 后,如何能帮他们更有效而准确的完成测试,是我一直在思考的一个问题.
QA 他们会对网页编写测试用例,在提测之前会让我们将优先级最高的用例跑通,这在一定程度上能够避免频繁的返工,保证测试的顺畅.
自己之前想过做 UI 的单元测试,一有修改就跑一遍用例,但是维护成本太高,并且每次留给我们的开发时间并不多.
最近在看多份测试记录的 BUG 单中发现,45%~70% 之间的 BUG 都是内容性问题,例如网页中缺了个字、少了段话、图片呈现不对等问题.
这些用肉眼看,其实很容易辨别。只要有个工具,能呈现不同操作下的网页,就可以大大提升 QA 的验收效率.
于是就想到了 Puppeteer (傀儡师),它是一个 Node.js 库,提供了一套 API 控制 Chrome 或 Chromium 浏览器,可生成页面快照截图、模拟用户行为等.
Chromium 是 Chrome 的开源版本,两者在界面、功能等方面会存在些区别.
虽然 Puppeteer 可以模拟用户行为,但是它不能模拟用户在客户端 WebView 中的行为,例如点击头像进入用户客户端中的主页.
简单理解,就是 Puppeteer 能呈现 Chrome 浏览器中的页面,但如果要测试客户端的样式兼容性和各种交互行为,就无法实现了.
而内容展示异常的问题,无论是在哪一端,都能表现一致,因此可以用 Puppeteer 来作为自动化测试工具.
当前 Puppeteer 的最新版本是 19.2.2,API 分为 20 多个模块,可查找页面 DOM 元素、屏幕截图、处理 WebSocket、模拟移动端设备、植入脚本、请求拦截等操作.
我当前的目标是查看页面内容,所以在页面中也需要有些交互.
先基于 KOA,快速搭建一个新项目,因为 Puppeteer 库比较大,所以为了不影响其他项目的构建和运行,就单独开了个项目.
再引入相关的 Node 库,fs 用于创建目录,path 用于拼接绝对路径, config 用于读取配置文件.
const puppeteer = require('puppeteer' ); const fs = require('fs' ); const path = require('path' ); const config = require('config' ); const domain = config.get('domain');
接着是声明一条路由,例如用 get 方法访问 test/game,传递类型和环境.
router.get("/test/game", async (ctx) => { const { type, env = "www" } = ctx.query; let data = []; switch (type) { case "1" : data = await hot(env); break ; } ctx.body = { code: 0 , data }; });
hot() 函数就是自动化测试的主体,核心逻辑其实就是点击某一栏,呈现页面后,再截一张图.
async function hot(env) { const savePath = path.resolve(__dirname, "../static/hot"); // 将相对路径转换成绝对路径 const iPhone = puppeteer.KnownDevices["iPhone 6"]; // 模拟iPhone 6 // 当指定目录不存在时,就将其创建,Sync 后缀表示同步,recursive 参数表示递归创建 !fs.existsSync(savePath) && fs.mkdirSync(savePath, { recursive: true }); // 要返回的图片路径 const paths = []; /* * * 本地环境可以不需要配置 args * 但是在 Linux 服务器中在启动 puppeteer 时,默认要带上 --no-sandbox 参数 */ return puppeteer.launch({ args: [ "--no-sandbox", "--disable-setuid-sandbox" ] }).then(async (browser) => { const page = await browser.newPage(); // 创建新的浏览器上下文 await page.emulate(iPhone); // 模拟设备 // 默认主页 await page.goto(`https: // ${env}.xxx.com/game/hot.html`, { waitUntil: "networkidle0" // 等待到没有网络请求 }); // 截图 await screenshot(page, `${savePath}/1.png`); paths.push(`${domain}/static/hot/1.png`); // 查找符合样式的菜单栏 const tabs = await page.$$(".green_calss" ); // 点击第二个菜单栏 tabs[1 ].tap(); await page.waitForNetworkIdle(); await screenshot(page, `${savePath} /2.png`); paths.push(`${domain}/static/hot/2.png`); // 点击第三个菜单栏 tabs[2 ].tap(); await page.waitForNetworkIdle(); await screenshot(page, `${savePath} /3.png`); paths.push(`${domain}/static/hot/3.png`); await page.close(); await browser.close(); return paths; }); }
path.resolve()、fs.existsSync() 和 fs.mkdirSync() 都是 Node.js 提供的 方法 .
page. goto() 可跳转到指定 URL 的网页,networkidle0 可等待到页面无网络请求.
在自动化测试时,需要有个页面完成的时间点,如果用延时的方式,会不太准确,所以就想到了网络请求.
我们这边的网页以移动端居多,所以需要选择要模拟的设备,例如 iPhone 6.
page.$$() 是 ElementHandle 提供的一个方法,相当于 Document.querySelectorAll() 方法.
tabs[1]. tap() 就是模拟用户触摸屏幕,另外支持的事件还包括 click()、drag()、focus() 等.
screenshot() 是一个截屏函数,内部调用 page. screenshot() 方法,可截取完整页面,包括滚动区域.
async function screenshot(page, savePath) { await page.screenshot({ path: savePath, type: "png" , fullPage: true // 边滚动边截图 }); }
前端界面目前比较简洁,就一个活动下拉框和一个环境下拉框,以及一个提交按钮.
提交后,就会从后台拿到页面快照,这些快照都会按照写好的脚本生成.
1)遇到的问题 。
在实际使用中注意到,如果页面内包含一块定高区域,那么隐藏区域就需要滚动后才能呈现.
当网页中有一个资源阻塞加载时,若是 waitUntil 参数的值是 networkidle0,那页面就会报超时的错误.
await page.goto(url, { waitUntil: [ "networkidle0" ] });
但如果 goto() 方法不加等待时机,那就会一直等下去,没有结果.
await page.goto(url);
可以改成 networkidle2 ,networkidle0 是指在 500ms 内没有任何网络连接,而 networkidle2 是指网络连接个数不超过 2 个.
在部署到服务器后,由于字体的问题,页面内的中文会出现乱码,解决办法就是给服务器安装中文字体.
。
。
参考资料:
Automating Google Chrome with Node.js 。
京喜前端自动化测试之路 。
深入了解自动化:那些项目适合自动化测试 。
Puppeteer中文 。
Puppeteer 入门教程 。
最后此篇关于Node.js躬行记(25)——Web自动化测试的文章就讲到这里了,如果你想了解更多关于Node.js躬行记(25)——Web自动化测试的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 5 年前。 Improve t
背景 我有一个 Azure Runbook(名为 RunStoredProcedure2),定义如下: param( [parameter(Mandatory=$True)] [string] $Sq
我有一个名为“团队”的表,其中包含“非事件”列,另一个表“事件”,其中包含“时间”列。如果任何团队的“事件”中的最新日期发生在 X 时间之前,如何将“非事件”列更新(为 true)? 我知道这可以通过
下面的问题可能有点令人困惑,但我会尽力以最好的方式解释它。 假设我们为一家制造公司工作。它制造然后用于制造产品的组件。在以下示例中,有 3 个组件和 2 个最终产品。 组件和产品的需求如下: comp
我有代码可以让我在一个范围内选择一个项目: COleVariant vItems = cstrAddr; hr = AutoWrap(
我正在开发一个应用程序,该应用程序有 4 种语言的大约 50 个应用内购买,这给了我很多表单和子表单、框和子框,需要使用 iTunesConnect 的令人痛苦且设计糟糕的表单来填充。 我想知道是否有
我想在 Azure 自动化中使用 powershell 脚本来安排打开/关闭资源。 我想在不创建帐户的情况下执行此操作,因为我们的域强制重置密码。我知道自动化帐户会创建一个证书 - 当使用资源管理器(
我尝试从 azure 自动化 run book power shell 自动检索 azure SQL 数据库中的数据。我发现azure自动化帐户的模块中缺少SQL Server模块。我已经导入了该模块
我正在自动化 Outlook,并且需要控制电子邮件的发件人身份。用户将在 Outlook 中设置两个或多个帐户,我需要能够选择从哪个帐户发送电子邮件。有什么想法吗? 需要 Outlook 2003 及
我尝试从 azure 自动化 run book power shell 自动检索 azure SQL 数据库中的数据。我发现azure自动化帐户的模块中缺少SQL Server模块。我已经导入了该模块
假设我有一个网站,我可以(随时)登录并每隔 x 小时提交数据(单击登录后可见的链接),我将如何自动化此过程? 我构建了一个图形用户界面,它为用户(现在是我,为了我自己的方便)提供了一个包含一些信息的界
我正在开发一个程序,它的任务是我们为它定义一些号码(我们的一些手机号码)并且它应该在 Telegram 中注册它们,然后获取发送到该号码的所有消息。如您所知,在 Telegram 中注册需要提供电话号
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 3 年前。 Improve this qu
最近我在处理 CSS Sprite 。一切正常。 我创建了一个 sprite、.css 文件和 html 结构。看起来像 .sprites{ background-image:url
我想为一款名为 Dune 2000 的策略游戏创建一个叠加层。令人讨厌的是,要创建 10 个士兵,每次完成一个都必须单击该图标。没有队列。因此,在不干扰游戏运行方式的情况下,我想听听鼠标移动的声音,当
我是 python 的初学者,我想从自动化开始。以下是我正在尝试执行的任务。 ssh -p 2024 root@10.54.3.32 root@10.54.3.32's password: 我尝试通过
当我将一些 urlencoded Javascript 粘贴到 Firefox 和 Chrome 上的 URL 时,我看到了一些奇怪的事情发生。是否可以使用此技术告诉 Chrome 访问 URL,然后
我需要将大量请求自动提交到基于云的数据库接口(interface) (Intelex)。没有任何方法可以批量提交某些操作,但是提交单个请求所必需的只是让经过身份验证的用户尝试打开 Web 链接。因此,
假设我有一个进程的内存转储。我想对其运行报告,所以基本上我想打开 WinDBG,加载 SOS 并运行一个脚本,该脚本运行一些命令,解析输出,然后基于此运行更多命令。 除了像 SendKeys 这样的
我正在使用 ffmpeg 创建视频剪辑。我想自动化该过程并保存剪辑,而无需手动为要保存的每个文件命名。这是我拥有的代码。它将创建并保存剪辑,但只能使用扩展名和不是名字。 @echo off cd /d
我是一名优秀的程序员,十分优秀!