同为 Web UI 的测试框架,本文将 Selenium 、TestCafe 和 Puppeteer 与 Cypress 作了一番对比。 三篇相关文章 当selenium遇上docker 前端测试工具 TestCafe 简介 Puppeteer 实现 web 自动测试 对比一览 从多个维度指标做对比见下表: 指标 Selenium Puppeteer TestCafe Cypress 语言 多种语言:Java、Python、Ruby JavaScript JavaScript JavaScript 实现原理 Json wire 协议 chrome CDP 协议 JS注入页面 JS注入页面 等待方式 阻塞等待 异步 异步 异步 支持的浏览器 IE、Firefox、Chrome等 仅Chrome IE、Firefox、Chrome等 Chrome、Edge、Electron、Firefox 测试断言库 无 无 无 内含 Mocha/Chai 用途 测试 广泛 测试 测试 Selenium 已明显过时,TestCafe 和 Puppeteer 更多是一款工具,具体的用法则跟随使用者的习惯。Cypress 则提供了一套相对完整的系统,并提供了Cypress 的指导思想和最佳实践最佳实践 下面我们通过一些场景的实现,读者可自行对比异同。 场景1:登录 最常见的场景:用户名、密码两个文本框+提交按钮 比如上图中,用户名的输入框的 id 为 #username , 而密码输入框的 id 为 #password,提交按钮的 id 为 #submit ,希望用代码实现登录的过程。 Selenium 实现(略) Puppeteer 实现 async login(user){ await (await this.page.waitForSelector('#username')).type(user.name) await (await this.page.waitForSelector('#password')).type(user.password) await (await this.page.$('#submit')).click() await this.page.waitForNavigation() } TestCafe 实现 async login(user){ await t .typeText(Selector('#username'), user.name) .typeText(Selector('#password'), user.password) .click(Selector('#submit')) } Cypress 实现 login(user){ cy.visit('/') .get('#username') .type(user.name) .get('#password') .type(user.password) .get('#submit') .click() } 场景2:寻找包含某文字的链接并点击 找到并点击包含特定文字的元素 比如上图中希望找到 “百度一下"的按钮,并点击 Selenium 实现(略) Puppeteer 实现 let button= await page.$x('//button[contains(text(),"百度一下")]') if(button){ button[0].click() } TestCafe 实现 Selector('button').withExactText("百度一下").click() Cypress 实现 cy.contains('button', "百度一下").click() 场景3:获取页面某个元素的样式 场景描述:希望找到某一元素后,检查样式表的某项信息是否满足要求。 比如上图中希望核对 logo 的宽度和长度分别为 272 和 92 Puppeteer 实现 参照 用 Puppeteer 获取页面元素的样式 这篇文章的做法 async function () { let logoStyle = await page.$eval('img.lnXdpd', (elem) => { return JSON.parse(JSON.stringify(window.getComputedStyle(elem))) }) expect(logoStyle.width).to.equal('272px') expect(logoStyle.height).to.equal('92px') } 这里的 expect 使用了 chai 提供的断言库。 TestCafe 实现 test('logo has exact dimensions', async t => { let logo = await Selector('img.lnXdpd') await t .expect(logo.clientWidth).eql(272) .expect(logo.clientHeight).eql(92) }) 这里使用了 test cafe 自带的 expect 方法 Cypress 实现 cy.get('img.lnXdpd') .should('have.css', 'width') .and('eq','272px')