以下为作者观点:
在我们 Zenjob 的质量保证 (QA) 实践中,自动化回归测试作用巨大,这对于顺利、快速发布至关重要。在过去五年中,自动化测试行业经历了许多变化,为了跟上行业步伐,Zenjob 一直在工作流程中进行自动化尝试,以增强我们的测试自动化套件。
根据实践,在使用 Selenium 多年后,我们发现需要进一步寻求更新我们的自动化测试,并开始寻找合适的自动化框架。而 Playwright 被认为是 Selenium 的最佳替代品,它可以提高测试效率,简化维护,并减少管道中的测试执行时间,从而为我们的应用程序和 Web 用户提供高质量的应用程序。
Selenium和Playwright
Selenium 面临的挑战
尽管 Selenium 一直以来都是一个受欢迎的选择,但它也给我们的团队带来了各种挑战。比如:
1.管道运行时和资源 -- Selenium 测试由8个Jenkins作业并行执行。即便如此,这仍需要35分钟才能完成100个测试用例的执行,速度不是很快。
Jenkins中的Selenium测试执行有8个并行作业
2.不稳定测试 -- 为了消除不稳定测试,我们添加了同步步骤和专用测试数据。然而,不稳定测试仍然存在,这需要不断的返工。
3.缺乏内置的报告支持 -- 自动化测试中的报告非常重要,因为它使我们能够了解测试失败的原因。不幸的是,Selenium 没有内置的报告功能。过去,我们曾使用 Gradle 和 Jenkins 文件来生成 HTML 报告,但这会增加额外的工作量。
4.处理同步 -- 隐式和显式等待无法解决同步问题,因此我们针对几种不同的场景开发了自定义方法来解决这些问题。其中一种场景是单击按钮不会自动启动目标页面,通过在 Selenium 中创建自定义方法来处理同步,如以下代码所示:
void syncWithTagsUpdatePage() {
int attempts = 0
while (attempts < 100) {
sleep(2000)
if (tags.size() > 0) {
println("tags btn displayed")
break
} else {
driver.findElement(By.tagName("body")).sendKeys("Keys.ESCAPE")
}
if (otherSkills.size() > 0) {
println("otherSkills btn still exist")
clickButton(otherSkills)
} else {
println("both btn not displayed")
browser.driver.navigate().refresh()
}
attempts++
}
}
Selenium 中的自定义函数来处理同步
5.维护工作量巨大 -- 上述所有问题,如运行时间较长、不稳定、没有内置报告以及创建自定义方法,都使得我们不得不不断重构测试以提高其稳定性。这导致了巨大的维护工作量。
Playwright 为何被选为Selenium的替代品
当我们着手寻找 Selenium 的替代品时,我们创建了一份征求意见书 (RFC),比较了 Selenium、Cypress 和 Playwright——它们都是具有类似功能的流行 QA 工具。我们与整个工程团队分享了这份 RFC,以征求所有利益相关者的意见。
选择Playwright的原因如下:
-
浏览器上下文
-
内置报告
-
并行测试执行
-
重复使用登录状态
-
追踪
-
内置等待
-
内置可配置重试
此次变革的目标是提高测试效率、简化维护、减少流程中的测试执行时间,从而实现更频繁的发布。
如何处理向Playwright的迁移
通过精心规划并保持现有测试的运行,我们花了大约8个月的时间迁移到 Playwright。测试被分解成更小的步骤,我们同时运行 Selenium 和 Playwright 测试,同时逐渐增加 Playwright 测试并减少 Selenium 测试。
并行执行Selenium和Playwright测试
成功因素
我们很高兴地报告,迁移提高了性能和效率。接下来的部分概述了我们看到的一些改进。
文本执行
使用 Playwright 后,测试执行时间明显减少。更具体地说,我们将测试执行时间缩短了80%,并且与 Selenium 相比,不稳定的情况更少。
Selenium 测试执行时间。
Playwright测试执行时间
因此,我们可以在管道中添加更多测试以获得足够的回归测试覆盖率。
Playwright装置和页面对象的合并
在 Selenium 中,需要为访问方法的每个步骤定义对象。以下代码显示了如何为每个页面和访问方法创建对象:
import com.zenjob.uitests.apps.company.pages.Page1
import com.zenjob.uitests.apps.company.pages.Page2
import com.zenjob.uitests.apps.company.pages.Page3
this.metaClass.mixin(cucumber.api.groovy.Hooks)
this.metaClass.mixin(cucumber.api.groovy.EN)
Page1 page1
Page2 page2
Page3 page3
Then(~/Login with valid credentials/) { String user->
page1 = to(Page1)
page1.verifyLoggedInUserInformation(user)
}
Then(~/check user details in home page/) { String user ->
page2 = to(Page2)
page2.verifyHomePageInformation(user)
}
Then(~/verify user payment information/) { String user ->
page3 = to(Page3)
page3.verifyPaymentDetails(user)
}
Selenium 中的导入方法
Fixture是 Playwright 的一大特色。它们有助于对页面对象进行分组,并使其在 spec 文件中易于访问。通过将 Fixture 合并到spec 文件中,可以在单个测试中导入多个 Fixture:
import { test as base } from '@playwright/test';
import { Page1 } from '../pages/page1';
import { Page2 } from '../pages/page2';
import { Page3 } from '../pages/page3';
export type Pages = {
page1: Page1;
page2: Page2;
page3: Page3;
};
export const test = base.extend<Pages>({
page1: async ({ page }, use) => {
await use(new Page1(page));
},
page2: async ({ page }, use) => {
await use(new Page2(page));
},
page3: async ({ page }, use) => {
await use(new Page3(page));
},
});
export { expect } from '@playwright/test';
Playwright 中的装置文件
import { expect, mergeTests } from '@playwright/test';
import { test as fixture1PageObjects } from '../fixtures/fixture1';
import { test as fixture2PageObjects } from '../fixtures/fixture2';
import { TestUsers } from '../test-data/loginData';
const test = mergeTests(fixture1PageObjects, fixture2PageObjects)
test.describe("Verify User Information", ()=> {
test("Login with valid credentials", async( {page1} )=>{
await page1.verifyLoggedInUserInformation(TestUsers.globalManager)
})
test("check user details in home page", async( {page2} )=>{
await page2.verifyHomePageInformation(TestUsers.globalManager)
})
test("verify user payment information", async( {page3} )=>{
await page3.verifyPaymentDetails(TestUsers.globalManager)
})
})
Playwright中的Fixture的使用
Playwright workers
在 Playwright 中,测试可以与多个工作程序一起运行,以实现并行测试执行。这在 Selenium 中是不可行的,至少不是开箱即用的。并行运行测试的解决方法是将它们与其他框架相结合,但这需要大量的时间/精力。迁移到 Playwright 后,通过在 Playwright 配置文件中指定这一点,很容易启用测试的并行执行,如下所示,其中测试套件配置为在管道上使用八个工作程序运行测试,在本地运行时使用两个工作程序运行测试:
workers: process.env.CI ? 8 : 2
编剧工作者配置
完全并行
默认情况下,单个文件中的所有测试都会按顺序运行。Playwright 提供了一个选项,可以在每个文件内并行运行所有测试。 为此,必须在 Playwright 配置文件中将“fullyParallel”选项设置为“true”。
迁移到 Playwright 后,在发布期间,我们的团队发现失败的测试有所增加。我们后来确定,设置“fullyParallel”配置选项会导致某些测试失败。为了解决这个问题,我们将此选项设置为“false”,从而使管道中的测试性能稳定:
export default defineConfig<TestOptions>({
fullyParallel: false,
Playwright 中的完全平行设置
结论
迁移现已完成,我们已经看到 Playwright 对我们来说是更好的选择。这归因于许多因素,例如易于配置、执行时间更快、在采取行动之前使用内置同步的能力、TypeScript 的强大功能等等。我们很高兴这个项目取得了积极的成果,我们向寻求 Selenium 替代品的用户推荐 Playwright。
最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。