playwright介绍 任何浏览器·任何平台·一套 API
跨浏览器: Playwright支持所有现代洁染引擎,包括Chromium、WebKit和Firefox。
跨平台:在Windows、Linux和macOS上测试,本地或CI上测试, headless 或 headed。
跨语言: 在TypeScript、JavaScript、Python、.NET和Java中使用PlaywrightAPI.
测试Mobile Web:为移动端chrome和Safari提供原生移动模拟的。相同的染引警工作在你的桌面和云。
flexible
自动等待:plawright在执行动作之前等待元素可操作。它还有一系列丰富的自省事件(inrospection events),两者的结合消除了人工超时的需要.
Web优先断言: Paywright断言是专门为动态web创建的。检查将自动重试,直到满足必更乐件,追踪: 配置测过量试策略,抓获执行过程追踪、视频和截图以所除碎片。
无限制 浏览器在不同的进程中运行输入不同来源的web内容。playwright与现代浏览器架构保持一致,并在进程外运行测试。这使得它可以在任何浏览器中运行,而不会受到浏览器安全限制。
跨多个选项卡、多个来源和多个用户的测试场景。为不同用户创建具有不同上下文的场景,并在一个测试中对服务器运行他们。
可信事件: 悬停元素与动态控件交互,生成可信事件,Playwright使用与真实用户无法区分的真实浏览器输入管道。
测试表单: 穿透DOM的阴影。Playwright选择器穿透阴影DOM并允许无缝输入表单。
完全隔离·快速执行
浏览器上下文:playwright为每个测试创建浏览器上下文,浏览器上下文相当于一个全新的浏览器配置文件。这提供了零开销的完全测试隔高,创建新的浏览器上下文只需要几毫秒。
登录一次:保存上下文的身份验证状态,并在所有测过中重用它。这绕过了每个测试中的重复登录操作,但提供了独立测试的完全隔离.
强大的工具
代码生成器(Codegen)。通过您的操作生成测试,将它们保存为任何语言。
Playwright检查(inspector):检查页面,生成选择器,逐步执行测试,查看单击点,刘览执行日志。
跟踪查看器(Trace Viewer):捕获所有信息以调查测试失败,Playwright跟踪包含测试执行屏幕广播、实时DOM快照、动作资源管理路、测试源等等。
Playwright vs Selenium vs Puppeteer vs Cypress 支持语言
Playwright: JavaScript, Python, C#, Java
Selenium: JavaScript, Python, C#, Java, Ruby, Perl, PHP, Objective-C, Swift, R, Groovy, Scala,
Puppeteer: JavaScript
Cypress: JavaScript
支持浏览器
Playwright: Chromium, Firefox, WebKit
Selenium: Chromium, Firefox, WebKit, IE, Edge, Safari
Cypress: Chromium, Firefox
Puppeteer: Chromium, Firefox
支持多标签 + 表单
Playwright: 支持,通过上下文支持
Selenium: 支持,通过switch_to
切换,但不好用
Cypress: 不支持
Puppeteer: 支持
测试创建速度
Playwright: 基于playwright codegen
命令录制脚本
Selenium: 基于Selenium IDE
录制脚本
Cypress: 基于Cypress Recorder
录制脚本
Puppeteer: 基于Puppeteer Recorder
录制脚本
稳定性 主要评估用例编写之后的失败率,不包括真正的发现bug之后的失败
Playwright: 最好等待某些元素,但必须手工等待其他元素
Selenium:复杂的自动等待机制
Cypress: 复杂的机制,并且不能与框架一起工作
Puppeteer: 等待某些元素,但必须手工等待其他元素
智能定位
Playwright: 支持自定义选择器引擎
Selenium: 不支持以多种方式选择元素
Cypress: 不支持以多种方式选择元素
Puppeteer: 不支持以多种方式选择元素
playwright定位器 playwright提供locator()
来实现元素的定位
选择器类型
示例
locator('text=foo')
:选择文本为foo的元素
locator('css=div')
:选择第一个div元素
locator("[data-test=login-button]")
:选择data-test
属性值为login-button
的元素
locator("xpath=//*[@id='kw']")
: 选择id为kw
的元素
常用API 启动浏览器 1 2 3 browser = await playwright.chromium .launch (headless=False ) browser = await playwright.firefox .launch (headless=False ) browser = await playwright.webkit .launch (headless=False )
创建上下文 & 打开页面 1 2 3 context = await browser.newContext () page = await context.newPage ()
执行js 1 await page.evaluate('alert("hello world")' )
表单 1 username = page.frame_locator ('.frame-class' ).locator ('#username' )
输入 1 2 3 4 5 await username.fill ('admin' )page.locator ('#agree' ).check () page.locator ('#name' ).press ('Enter' ) page.on ('dialog' , lambda dialog : dialog.accept ())
playwright断言 断言一般是单元测试框架所提供的概念,一般包括assertEqual
、assertNotEqual
、assertTrue
、assertFalse
、assertIn
、assertNotIn
等等,playwright提供了expect
来实现断言。这些断言将等待并重试,直到断言成功或超时。
1 2 page.locator ('#submit-button' ).click () expect (page.locator ('#message' )).toHaveText ('Thank you' )
page object模式(一种设计模式) 什么是page object模式 page object模式是一种设计模式,它将页面的每个页面封装为一个类,每个类都有自己的方法,这些方法用于与页面进行交互。这种模式的好处是,如果页面发生变化,我们只需要更新页面对象类,而不需要更新测试用例。也就是将定位元素的过程与操作元素的过程分离开来,这样当页面发生变化时,只需要修改page object类即可,而不需要修改测试用例。
示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import { expect, type Locator , type Page } from '@playwright/test' ;export class PlaywrightDevPage { readonly page : Page ; readonly getStartedLink : Locator ; readonly gettingStartedHeader : Locator ; readonly pomLink : Locator ; readonly tocList : Locator ; constructor (page: Page ) { this .page = page; this .getStartedLink = page.locator ('a' , { hasText : 'Get started' }); this .gettingStartedHeader = page.locator ('h1' , { hasText : 'Installation' }); this .pomLink = page.locator ('li' , { hasText : 'Guides' }).locator ('a' , { hasText : 'Page Object Model' }); this .tocList = page.locator ('article div.markdown ul > li > a' ); } async goto ( ) { await this .page .goto ('https://playwright.dev' ); } async getStarted ( ) { await this .getStartedLink .first ().click (); await expect (this .gettingStartedHeader ).toBeVisible (); } async pageObjectModel ( ) { await this .getStarted (); await this .pomLink .click (); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import { test, expect } from '@playwright/test' ;import { PlaywrightDevPage } from './playwright-dev-page' ;test ('getting started should contain table of contents' , async ({ page }) => { const playwrightDev = new PlaywrightDevPage (page); await playwrightDev.goto (); await playwrightDev.getStarted (); await expect (playwrightDev.tocList ).toHaveText ([ `How to install Playwright` , `What's Installed` , `How to run the example test` , `How to open the HTML test report` , `Write tests using web first assertions, page fixtures and locators` , `Run single test, multiple tests, headed mode` , `Generate tests with Codegen` , `See a trace of your tests` ]); }); test ('should show Page Object Model article' , async ({ page }) => { const playwrightDev = new PlaywrightDevPage (page); await playwrightDev.goto (); await playwrightDev.pageObjectModel (); await expect (page.locator ('article' )).toContainText ('Page Object Model is a common pattern' ); });