自动化视觉测试提供了一种强大的,尽管有时无法预测的软件质量保证方法。剧作家简化了网站的过程,尽管可能需要微调。
最近的系统停机时间激发了我解决一个长期存在的问题:由于不断增加的功能,我维护的网站的CSS变得笨拙。有了更清楚的了解,现在是内部CSS重构来减少技术债务并利用现代CSS功能的时候了(例如嵌套的选择器以改善结构)。清洁器代码库还将促进急需的黑暗模式,从而通过尊重首选配色方案来增强用户体验。
但是,犹豫不决地通过重大更改引入错误,我需要一个强大的视觉回归测试解决方案。传统的快照测试证明太慢和脆弱。
在这种情况下,快照测试涉及捕获屏幕截图,以建立与未来结果进行比较的基线。但是,这些屏幕截图容易受到各种无法控制的因素(例如,时机问题,变化的硬件资源或动态内容)。在测试运行之间管理状态(保存屏幕截图)会增加复杂性,并使仅测试代码很难完全定义期望。
长时间的拖延后,我终于实施了一个解决方案,最初期望快速解决问题。这不会成为主要测试套件的一部分;只是该重构任务的临时工具。
幸运的是,我回想起了以前的研究,并很快发现了剧作家的内置视觉比较功能。欣赏剧作家的最小外部依赖关系,我继续实施。
设置环境
虽然npm init playwright@latest
提供了一个很好的起点,但我选择了手动设置来更好地了解组件。考虑到快照测试的使用很少使用,我创建了一个专用的子目录, test/visual
作为我们的工作目录。 package.json
文件声明依赖项和辅助脚本:
{ “脚本”:{ “测试”:“剧作家测试”, “报告”:“剧作家表演报告”, “ Update”:“剧作家测试 - update-snapshots”, “ reset”:“ rm -r ./playwright-report ./test-results ./viz.test.js-snapshots || true” },, “ devDectiencies”:{ “@playwright/test”:“^1.49.1” } }
为了避免使用这种很少使用的依赖性使主项目混乱,请考虑在需要时在根目录中直接在根目录中运行npm install --no-save @playwright/test
。
安装必要的软件包( npm install
然后是npx playwright install
)后,我们使用playwright.config.js
配置测试环境:
从“@playwright/test”中导入{decteConfig,devices}; 令浏览器= [“桌面firefox”,“桌面chrome”,“桌面Safari”]; 令base_url =“ http:// localhost:8000”; 令server =“ cd ../../dist && python3 -m http.server”; 让IS_CI = !! process.env.ci; 导出默认decteConfig({ testdir:“ ./”, 完全比较:是的, 禁止:is_ci, 重试:2, 工人:is_ci? 1:未定义, 记者:“ html”, WebServer:{ 命令:服务器, URL:base_url, reuseexisterserver:!is_ci },, 使用: { baseurl:base_url, 痕迹:“首先退休” },, 项目:browsers.map(ua =>({{ 名称:ua.tolowercase()。替换(“”,“ - ”), 使用:{...设备[ua]} }))) });
该配置在dist
目录中假定一个静态网站,该网站在本地localhost:8000
(使用Python的http.server
)。可以调整浏览器的数量以进行性能。对于此特定的非CI场景,省略了IS_CI
逻辑。
捕获和比较视觉效果
sample.test.js
中的最小测试证明了核心功能:
从“@playwright/test”中导入{test,Expect}; test(“主页”,async({page})=> { 等待page.goto(“/”); 等待期望(page).tohavescreenshot(); });
第一次运行会生成基线快照。随后的运行与这些相比,如果检测到视觉差异,则报告失败。剧作家提供了视觉比较快照和检查基线图像的工具。
自动测试生成
为了避免为每个页面的手动测试创建,我实现了一个简单的Web爬网,以动态生成测试。
站点地图创建
playwright.config.js
文件已扩展到包含globalSetup
和导出相关配置值:
导出让浏览器= [“桌面firefox”,“桌面chrome”,“桌面Safari”]; 导出令base_url =“ http:// localhost:8000”; // ...其余的配置... 导出默认decteConfig({ // ...其余的配置... GlobalsEtup:require.sroove(“ ./ setup.js”) });
setup.js
文件使用无头浏览器来爬网站并创建一个站点地图:
导入{base_url,浏览器}来自“ ./playwright.config.js”; 导入{createSiteMap,readSiteMap}从“ ./sitemap.js”; 从“@playwright/test”中导入剧作家; 导出默认异步函数globalsetup(config){ //仅创建站点地图,如果它尚不存在 尝试 { readSiteMap(); 返回; } catch(err){} //启动浏览器并启动爬网 令浏览器= playwright.devices [浏览器[0]]。defaultBrowserType; 浏览器=等待剧作家[浏览器] .launch(); 令page =等待浏览器.newpage(); 等待createSiteMap(base_url,page); 等待browser.close(); }
sitemap.js
文件包含轨道逻辑:
导入{readfilesync,writefilesync}来自“ node:fs”; 从“ node:path”导入{join}; 令Entry_point =“/topics”; 让SiteMap = join(__ dirname,“ ./sitemap.json”); 导出异步函数createSiteMap(baseurl,page){ 等待页面。 令URL =等待页面。 令data = json.stringify(url,null,4); writefilesync(sitemap,data,{engoding:“ utf-8”}); } 导出函数readsitemap(){ 尝试 { var data = readfilesync(sitemap,{engoding:“ utf-8”}); } catch(err){ if(err.code ===“ enoent”){ 投掷新错误(“缺少站点地图”); } 投掷错误; } 返回JSON.PARSE(数据); } 函数ExtractLocallinks(baseurl){ 令URLS = new Set(); let offset = baseurl.length; for(令document.links的{href}){ if(href.startswith(baseurl)){ 令路径= href.slice(offset); urls.add(路径); } } 返回array.from(urls); }
这使用page.evaluate
在浏览器上下文中提取链接。
动态测试生成
viz.test.js
文件基于站点地图动态生成测试:
从“ ./sitemap.js”导入{readSiteMap}; 从“@playwright/test”中导入{test,Expect}; 从“ node:path”导入{join}; 让选项= { stylepath:join(__ dirname,“ ./viz.tweaks.css”) }; 让SiteMap = []; 尝试 { siteMap = readSiteMap(); } catch(err){ 测试(“站点地图”,({page})=> { 投掷新错误(“缺少站点地图”); }); } for(让站点地图的URL){ test(`page at $ {url}`,async({page})=> { 等待Page.goto(url); 等待期望(page).tohavescreenshot(options); }); }
由于剧作家当前对测试文件中的顶级await
限制,因此需要同步readSiteMap
。 OPTIONS
对象允许自定义CSS调整。
处理异常和片状
视觉测试需要处理异常。 viz.tweaks.css
中的自定义CSS可以抑制影响一致性的特定元素:
/ *抑制状态 */ 主a:访问{ 颜色:var( - 颜色链接); } / *抑制随机性 */ iframe [src $ =“/articles/stignals-reactivity/demo.html”] { 可见性:隐藏; } / *抑制片状 */ 身体:h1 a [href =“/wip/unicode-symbols/“”] { 主Tbody> TR:Last-Child> TD:First-Child { 字体大小:0; 可见性:隐藏; } }
解决视口限制
最初,测试未能检测到样式的变化,因为.toHaveScreenshot
仅捕获视口。要捕获完整页面, playwright.config.js
已修改:
导出让宽度= 800; 导出LET Height = width; // ...其余的配置... 项目:browsers.map(ua =>({{ // ...其余的配置... 使用: { // ...其余的配置... 视口:{ 宽度:宽度, 高度:高度 } } })))
和viz.test.js
已更新以确定和设置页面高度:
从“ ./playwright.config.js”导入{width,height}; // ...其余的进口... for(让站点地图的URL){ test(`page at $ {url}`,async({page})=> { checksnapshot(url,page); }); } 异步函数checksnapshot(url,page){ 等待Page.setViewPortsize({width:width:width,height:height}); 等待Page.goto(url); 等待页面。 让高度=等待页面。 等待Page.setViewPortsize({width:width:width,height:Math.ceil(height)}); 等待页面。 等待期望(page).tohavescreenshot(options); } 函数getfullheight(){ 返回document.documentElement.getBoundingClientRect()。高度; }
这确保了整个页面的捕获,尽管它增加了资源消耗,并且可能会由于布局变化或超时而引起片状。
结论
这种视觉回归测试解决方案(虽然比最初预期的更为复杂,但都可以有效地解决该问题。仍然存在重构和随后的黑暗模式实现。
以上是与剧作家的自动视觉回归测试的详细内容。更多信息请关注PHP中文网其他相关文章!

文章讨论了CSS保证金属性,特别是“保证金:40px 100px 120px 80px”,其应用程序以及对网页布局的影响。

本文讨论了CSS边境属性,重点是自定义,最佳实践和响应能力。主要论点:边境 - 拉迪乌斯(Border-Radius)对响应式设计最有效。

本文讨论了CSS中评论的使用,详细介绍了单线和多行评论语法。它认为注释可以增强代码可读性,可维护性和协作,但如果无法正确管理,可能会影响网站性能。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

Dreamweaver Mac版
视觉化网页开发工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 Linux新版
SublimeText3 Linux最新版

Atom编辑器mac版下载
最流行的的开源编辑器

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具