Playwright之初体验

参考文件

官方文档:https://playwright.dev/docs/intro
GitHub链接:https://github.com/microsoft/playwright-python

Playwright简介

Playwright Test是专门为满足端到端测试的需求而创建的。Playwright支持所有现代搜索引擎,包括Chrome、WebKit和Firefox。在Windows、Linux和macOS上测试,使用Android和mobile Safari的Google Chrome原生移动模拟进行测试。

环境安装

安装python环境
Playwright安装
使用pip install playwright命令进行安装
在这里插入图片描述
使用playwright install命令进行各种工具包和依赖,有报错,我们先不管,继续往下走
在这里插入图片描述
安装pytest插件:pip install pytest-playwright
在这里插入图片描述

简单跑一个demo,发现报错了,我们换一种执行方式
在这里插入图片描述

我们使用pytest命令执行发现没有报错
在这里插入图片描述

Playwright的自带工具

Playwright codegen
我们在pycharm中使用终端,输入该命令,之后,就会启用被测浏览器,并且启用inspector记录操作的脚本
在这里插入图片描述

Playwright inspector
在这里插入图片描述
之后我们可以将inspector里面的代码复制到pycharm里面自己编辑了

当然,我们也可以针对某个浏览器的网址,比如说https://www.baidu.com/

在这里插入图片描述

回车之后,浏览器自动启动一个标签,以及一个inspector来记录操作代码
在这里插入图片描述

也可以固定浏览器某个窗口的大小进行操作

Playwright codegen --viewport-size=800,600 www.baidu.com
在这里插入图片描述

在这里插入图片描述

访问移动端手机浏览器,比如说苹果13

Playwright codegen --device=“iPhone 13” www.baidu.com

在这里插入图片描述

在这里插入图片描述

帮助我们自动记录和管理cookie信息

首先我们使用如下命令Playwright codegen --save-storage=auth.json work-be.test.mi.com/main-buildstore/home/address:8000
然后浏览器启动一个窗口
在这里插入图片描述

接下来我们自动输入密码,如下:
在这里插入图片描述
之后,我们把启动的浏览器关掉
接下来,我们再次使用如下命令再次回车
Playwright codegen --load-storage=auth.json work-be.test.mi.com/main-buildstore/home/address:8000
在这里插入图片描述

浏览器会再次启动一个新窗口,但是此窗口浏览器的地址我们可以看到是登录状态的
在这里插入图片描述
Trace Viewer是Playwright的另一个神器,顾名思义就是痕迹查看,也就是我们后期可以查看我们之前都操作了哪些地方

Playwright架构技术介绍

Playwright是由Puppeteer-https://puppeteer.bootcss.com/改造过来的,Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。再加上,Playwright官方没有给出架构图,所以我们可以参考Puppeteer的架构图来学习Playwright
首先我们可以通过Puppeteer来控制浏览器的,他是通过谷歌开发者协议,简称CDP,该协议是建立在WebSocket协议之上
这里的Brower其实是一个浏览器实例,一个浏览器可以包含很多个上下文,也就是包含很多Context,通俗来讲,就跟我们打开了一个谷歌浏览器,又开启了一个无痕模式浏览器一样,Brower的Context具有独立的Session,cookie&cache
一个Context可以包含很多个Page页面,一个Page是一个独立页面
一个Page可以包含很多个Frame,一个Frame可以理解为是一个框架,可以包含多个子框架
再往下就是ExecutionContext,它是javascript的执行环境,每一个Frame都有一个默认的javascript的执行环境
在Playwright中,这些概念也是一样的
在这里插入图片描述

第一个Playwright脚本

from playwright.sync_api import sync_playwright

def test_pla():
    with sync_playwright() as p:
        #实例化一个浏览器,使用谷歌为例
        #代码运行默认是无头模式运行,如果要看运行效果,可以加入参数headless
        browser = p.chromium.launch(headless=False)
        #实例化一个页面
        page = browser.new_page()
        #打开一个网站
        page.goto("https://www.bilibili.com")
        #打印网页标题
        print(page.title())
        #关闭浏览器
        browser.close()

运行之后:
在这里插入图片描述

Playwright浏览器控制

谷歌官方相关命令地址:https://peter.sh/experiments/chromium-command-line-switches/

from playwright.sync_api import sync_playwright

def test_pla():
    with sync_playwright() as p:
        #实例化一个浏览器,使用谷歌为例
        #代码运行默认是无头模式运行,如果要看运行效果,可以加入参数headless
        #--start-maximized表示窗口最大化,no_viewport表示的是默认窗口大小失效
        #slow_mo表示的是每一步操作,默认等待3s
        browser = p.chromium.launch(headless=False,args=["--start-maximized"],slow_mo=3000)
        #实例化一个页面
        page = browser.new_page(no_viewport=True)
        #打开一个网站
        page.goto("https://www.zhihu.com")
        #打印网页标题
        print(page.title())
        #点击开通机构号
        page.get_by_text("开通机构号").click()
        #后退
        page.go_back()
        #前进
        page.go_forward()
        #刷新
        page.reload()
        #关闭浏览器
        browser.close()

Playwright浏览器启动参数详解

executable_path——数据路径
channel——指定使用哪种浏览器
args——参数数组
ignore_default_args——忽略默认参数,慎用,使用不当,脚本无法执行
timeout——等待浏览器实例启动的最长时间,单位毫秒,一般是30s,设置为0,功能失效
headless——有头和无头模式运行的设置
traces_dir——数据报错路径
chromium_sandbox——是否启动谷歌沙盒浏览器
等等,基本所有参数都是launch()函数里面的,可以自行查看
在这里插入图片描述

Playwright xpath元素定位

XML Path Language

from playwright.sync_api import sync_playwright

def test_pla():
    with sync_playwright() as p:
        #实例化一个浏览器,使用谷歌为例
        #代码运行默认是无头模式运行,如果要看运行效果,可以加入参数headless
        #--start-maximized表示窗口最大化,no_viewport表示的是默认窗口大小失效
        #slow_mo表示的是每一步操作,默认等待3s
        browser = p.chromium.launch(headless=False,args=["--start-maximized"],slow_mo=3000)
        #实例化一个页面
        page = browser.new_page(no_viewport=True)
        #打开一个网站
        page.goto("https://www.baidu.com")
        """
        /:从根节点选取
        //:从非根节点选取
        *:任意节点选取
        @:根据属性筛选
        text():根据文本筛选
        and:关联属性或者链接文本
        []:可以防止下标/属性/链接文本
        .:选取当前节点
        ..:选取当前节点的父节点
        contains:包含
        """
        #使用单一属性定位,   点击百度首页设置按钮,使用text_content获取内容
        t_1 = page.locator("//span[@name='tj_settingicon']").text_content()
        print(t_1)
        #多属性定位
        t_2 = page.locator("//span[@id='s-usersetting-top' and @name='tj_settingicon']").text_content()
        print(t_2)
        #父节点定位
        t_3 = page.locator('//div[@id="u1"]/span').text_content()
        print(t_3)
        #通过下标进行定位,新闻这个按钮
        t_4 = page.locator('//div[@id="s-top-left"]/a[1]').text_content()
        print(t_4)
        #通过.和..来定位
        t_5= page.locator('//a[@name="tj_fanyi"]/div/../../../../../a[1]').text_content()
        print(t_5)
        #通过文本定位
        t_6 = page.locator('//a[text()="新闻"]').text_content()
        print(t_6)
        #通过模糊匹配定位
        t_7 = page.locator('//a[contains(text(),"hao")]').text_content()
        print(t_7)
        #关闭浏览器
        browser.close()

运行之后:
在这里插入图片描述

Playwright css定位

css定位方式有五种,分别是:
id选择器
class选择器
元素选择器
属性选择器
层级选择器

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
page = browser.new_page()
page.goto("https://www.baidu.com/")

#id属性定位
page.locator("#kw").fill("playwright")
page.locator("#su").click()

page.go_back()
page.locator(".s_ipt").fill("playwright")
page.locator("#su").click()

page.go_back()
page.locator("input#kw").fill("playwright")
page.locator("#su").click()

page.go_back()
page.locator("div>form>span>input.s_ipt").fill("playwright")  #层级关系
page.locator("#su").click()

browser.close()

Playwright特有定位方式

"""
特有元素定位方法
locator.get_by_alt_text(text,**kwargs),  alt属性
locator.get_by_label(text,**kwargs),label属性
locator.get_by_placeholder(text,**kwargs),placeholder属性
locator.get_by_role(role,**kwargs),role属性
locator.get_by_text(text,**kwargs)
locator.get_by_title(text,**kwargs)
"""

Playwright元素常用操作

我们以该网页为例子进行测试
登陆页面,我们输入用户名、密码、验证码,点击登录

同时,我们介绍怎么处理iframe进行上传文件以及自动化,在上传文件中,我们要注意,每一个图片都有一个随机的字符串

在这里插入图片描述
所以我们可以使用父节点定位方式进行定位处理
“//*[@id=‘filePicker’]/div[2]/input”
在这里插入图片描述
接下来是图片的上传,图片我们先使用set_input_files函数,绝对路径处理,前面添加r
r"C:\Users\jinlai\111.jpg"
具体代码如下:

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#进入个人信息页面
page.goto("http://testingedu.com.cn:8000/Home/User/info.html")
#点击图片
page.click('//*[@id="preview"]')
#点击点击选择图片按钮
page.frame_locator('//*[@id="layui-layer-iframe1"]').locator("//*[@id='filePicker']/div[2]/input").set_input_files(r"C:\Users\jinlai\111.jpg")
#点击确认使用
page.frame_locator('//*[@id="layui-layer-iframe1"]').locator("//div[@class='saveBtn']").click()
#点击页面的确认保存
page.click("//input[@class='save']")

#关闭浏览器
browser.close()



接下来我们看下拉框怎么处理

#下拉框收货地址处理,我们需要定位到要操作的输入框,然后根据内容属性处理即可

page.select_option('//*[@id="province"]',value='19280')
page.select_option('//*[@id="city"]',value='19281')
page.select_option('//*[@id="district"]',value='19283')
page.select_option('//*[@id="twon"]',value='19285')
from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#打开地址管理页面
page.goto("http://testingedu.com.cn:8000/Home/User/address_list.html")
#点击增加新地址
page.click("//*[@class='co_blue']")
#点击并输入收货人
page.fill("//*[@name='consignee']","ceshi")
#点击并输入手机或者电话
page.fill("//*[@name='mobile']","13176358824")


#下拉框收货地址处理
page.select_option('//*[@id="province"]',value='19280')
page.select_option('//*[@id="city"]',value='19281')
page.select_option('//*[@id="district"]',value='19283')
page.select_option('//*[@id="twon"]',value='19285')

#点击并输入详细地址
page.fill("//*[@name='address']","凯胜家园小区2号楼2单元802")
#点击报错按钮
page.click("//*[@id='address_submit']")

#刷新页面
page.reload()
#删除新增的地址
page.click('//span[text()="ceshi"]/../..//a[text()="删除"]')
#关闭浏览器
browser.close()

如何获取多个元素

比如说获取所有搜索商品的名字
我们可以使用query_selector_all方法

goods = page.query_selector_all('//div[@class="shop-list-splb p"]//div[@class="shop_name2"]')
for good in goods:
    print(good.text_content().strip())  #strip去除空格

具体代码如下:

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=2000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#进入地址管理页面
page.goto("http://testingedu.com.cn:8000/Home/User/address_list.html")

#点击搜索框输入内容
page.fill('//input[@class="search_usercenter_text"]','手机')
#点击搜索
page.click('//a[text()="搜索"]')
#query_selector_all方法获取所有元素
goods = page.query_selector_all('//div[@class="shop-list-splb p"]//div[@class="shop_name2"]')
for good in goods:
    print(good.text_content().strip())  #strip去除空格

#关闭浏览器
browser.close()

运行结果之后:
在这里插入图片描述
页面上显示:
在这里插入图片描述
两者相对应。

Playwright元素常用操作

import re

from playwright.sync_api import Playwright, sync_playwright, expect

playwright = sync_playwright().start()
browser = playwright.chromium.launch(headless=False,slow_mo=5000)
context = browser.new_context()
page = browser.new_page()
page.goto("http://testingedu.com.cn:8000/Home/user/login.html")
#输入用户名
page.fill('//*[@id="username"]','13800138006')
#输入密码
page.fill('//*[@id="password"]','123456')
#输入验证码,这里做了处理
page.fill('//*[@id="verify_code"]','1111')
#点击登录
page.click('//*[@id="loginform"]/div/div[6]/a')

#进入产品站
page.goto("http://testingedu.com.cn:8000/Home/Goods/goodsInfo/id/55.html")

#点击加入购物车
page.click('//*[@id="join_cart"]')
#点击弹层叉号
page.click('//*[@class="layui-layer-ico layui-layer-close layui-layer-close1"]')

#鼠标悬停,我的购物车按钮,以及点击去购物车结算
page.hover('//span[text()="我的购物车"]')
page.click('//a[@class="c-btn"]')

#点击去结算
page.click('//a[text()="去结算"]')

#点击提交订单
page.click('//button[@class="checkout-submit"]')

#获取订单号,我们可以使用正则表达式获取
t = page.locator('//p[@class="succ-p"]').text_content()
print(t)
text = re.findall(r'\d{18}',t)[0]
print(text)

"""
接下来,我们进入到我的订单页面,点击我的订单的时候,我们发现打开了一个新的网页,在selenium中,是通过切换句柄实现的,而在playwright中,我们可以使用新的写法
"""
print("444")
with context.expect_page() as new_page_info:
    page.click('a[target="_blank"]')   #点击我的订单
new_page = new_page_info.value
new_page.wait_for_load_state()
print(new_page.title())

#点击取消订单,并格式化
new_page.click('//em[text()="{}"]/../..//a[text()="取消订单"]'.format(text))

#点击弹层里面的确定按钮
new_page.click('//*[@class="layui-layer-btn layui-layer-btn-"]/a[text()="确定"]')
#刷新页面
new_page.reload()

#关闭浏览器
browser.close()

Playwright自动化框架设计

Playwright作为一个新进的自动化特殊工具,在易用性方面做了很多工作。针对Playwright我们甚至可以不用做任何处理,把它当成一个封装好的第三方库去使用即可。
那么整体的框架又该怎么去设计呢?又该考虑哪些问题呢?
如果我们站在公司的角度上来说,公司层面需要打造一个通用性很强的自动化框架。也就是说a项目能用,b项目也能用。另外还需要将测试结果、测试过程等都完整的输出出来,这是基本条件。不然我们花了很多时间写代码,换一个项目就不能用了,几乎需要从头到尾的再写写一遍,那就没有任何意义。而测试人员都是拿结果的,画的结果越详细越好。除此之外,我们也应该考虑到,在一个公司写一个完整的框架和使用框架,不太可能是一个人去完成。我们需要考虑代码托管和持续集成等等问题。所以大体的思路呢便有了。我们也可以根据刚刚的这个思路细化出一个架构图来
我们可以将整体的架构,从上到下可以分成五个层次。一是数据层、服务层、对象层,用例层和输出层。
数据方面,为了拥有一定的适应性,我们可以设计框架,让它支持多种外部数据格式。如说新老版本的excel、yaml等等。
而服务层方面,因为需要针对excel文件的操作,所以需要自己去封装excel读写库等等。
对象层面,我们实际上是借助于PO思想进行设计就可以了。
用例方面主要是考虑用例该如何去组织,该如何去执行。
当然我们选择pytest,在用例执行的过程中,我们是需要进行日志和报告的输出的。所以我们需要封装日志,并且加入allure测试报告。最后我们需要考虑的是,在整个框架的实现过程中,可能某些第三方库有些人没有安装。为了让框架的执行更加简单一点,我们可以直接将整个框架打包到docker里面,这样去执行。就不用担心环境的问题了。框架设计好之后,我们可以打开pycharm,把目录结构呢大体的来设计一下。
我们新建一个工程。新建好之后呢,按照我们刚刚的设计思路,将整体的目录结构呢可以设置成下面这种样子。
首先我们新建一个python package,比如叫做common,在common中,我们要做的事情呢,一般就是把一些公共用的库在这儿。比如excel的读写啊、日志啊等等,
再新建一个package,比如叫做ddt。我们在利用外部文件来执行测试用例的时候呢,实际上就是一个数据驱动。那我们可以把数据驱动的一些执行的逻辑代码放到此处。
再接着我们需要存放文件。比如说我们的测试用例、日志结果等等,我们可以新建一个文件夹,叫做lib。在lib文件下我们可以再新建一个cases,用来存放用例,再新建一个日志的文件夹,log用于存放日志。
最后我们还可以将结果和报告单独的进行设计。result和report。为了运行方便,我们也可以在根目录下创建一个runner。运行入口,我们可以新建一个runner的文件。那么整体的结构呢我们就可以按照这种格式设计完成了
在这里插入图片描述

Playwright自动化框架之excel文件读取

直接上代码吧
在这里插入图片描述
在这里插入图片描述

import os

import openpyxl


class Reader:
    """
    pip install openpyxl
    读取excel数据文件
    """
    def __init__(self):
        """
        全局变量
        """
        self.workbook = None
        self.sheet = None
        self.rows = 0
        self.r = 0  #表示当前读取到的行数

    def open_excel(self, srcfile):
        """
        打开文件
        :param srcfile:
        :return:
        """
        if not os.path.isfile(srcfile):
            print("%s not exist" % (srcfile))
            return
        #设置读取文件使用编码
        openpyxl.Workbook.encoding = 'utf-8'
        self.workbook = openpyxl.load_workbook(filename=srcfile)
        #默认从第一个sheet文件读取
        self.sheet = self.workbook[self.workbook.sheetnames[0]]
        self.rows = self.sheet.max_row
        self.r = 0
        return

    def get_sheet(self):
        """
        获取sheet名称
        :return:
        """
        sheets = self.workbook.sheetnames
        return sheets

    def set_sheet(self,name):
        """
        切换sheet
        :param name:
        :return:
        """
        self.sheet = self.workbook[name]
        self.rows = self.sheet.max_row
        self.r = 0
        return

    def readline(self):
        """
        逐行读取文件数据
        :return:
        """
        lines = []
        for row in self.sheet.rows:
            line = []
            for cell in row:
                #如果是空行,添加一个空字符串
                if cell.value is None:
                    line.append('')
                else:
                    line.append(cell.value)
            lines.append(line)
        return lines




import os

from common.Excel import NewExcel


def get_reader(srcfile='') -> NewExcel.Reader:
    reader = None

    if not os.path.isfile(srcfile):
        print("%s not exist" % (srcfile))
        return reader

    if srcfile.endswith('.xlsx'):
        reader = NewExcel.Reader()
        reader.open_excel(srcfile)
        return reader


好了,先介绍这里吧~后面再更新哈哈

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
使用 Playwright 进行元素定位并获取文本内容可以通过以下步骤实现: 1. 首先,使用 `page.locator(selector)` 方法选择要定位的元素。其中,`selector` 参数可以是 CSS 选择器、XPath 或其他支持的选择器。 2. 然后,可以使用 `element.innerText()` 或 `element.innerHTML()` 方法获取元素的文本内容。其中,`innerText()` 方法仅返回元素的文本内容,而 `innerHTML()` 方法返回元素的 HTML 内容。 下面是一个示例代码,演示如何使用 Playwright 定位并获取一个元素的文本内容: ``` const { chromium } = require('playwright'); (async () => { const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://www.example.com'); // 定位元素并获取文本内容 const element = await page.locator('#myElement'); const textContent = await element.innerText(); console.log(`元素的文本内容为:${textContent}`); await browser.close(); })(); ``` 在上面的示例中,我们首先使用 `page.goto(url)` 方法打开了一个网页,并使用 `page.locator(selector)` 方法选择了一个 ID 为 `myElement` 的元素。然后,我们使用 `element.innerText()` 方法获取了该元素的文本内容,并将其输出到控制台上。最后,我们使用 `browser.close()` 方法关闭了浏览器。 需要注意的是,如果元素包含子元素,那么 `innerText()` 方法只会返回其子元素的文本内容,而 `innerHTML()` 方法则会返回整个元素的 HTML 内容,包括其子元素。因此,在实际使用中需要根据具体情况选择使用哪种方法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木土雨成小小测试员

你的鼓励将是我最大的创作动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值