Playwright自动化测试

1.概述:

Playwright 是一个开源工具,用于自动化浏览器测试。它主要用于测试网站在不同浏览器和平台之间的功能兼容性。

Playwright 可以很好地模拟用户的操作,如点击按钮,输入文本等。它还可以模拟输入事件,如键盘和鼠标事件,以及浏览器的特定事件,如浏览器窗口的大小改变等。

 

2.优点:

playwright支持Chrome、Firefox、Safari、Microsoft Edge 等主流浏览器,支持以有头模式、无头模式运行浏览器。

playwright提供了同步和异步API,可以结合Pytest测试框架使用,并且支持自动录制浏览器端的操作脚本。

playwright环境搭建比selenium简单,还有他们两区别:传送门 ,传送门2

 

3.常用的元素定位(传送门)

 

     ##########################################基础元素定位##############################################
        # 定位文字信息(返回元素,exact表示是否精确匹配),并点击
        page.get_by_text('账密登录', exact=True).click()
        # 通过id定位并输入内容
        page.locator('#form_item_phone').fill("test123")
        # 根据元素角色进行定位,并点击
        page.get_by_role("button", name="登 录").click()
        # 定位提示信息为 请输入名称 的输入框
        page.get_by_placeholder('请输入名称', exact=True).click
        # 通过标题文本进行定位元素
        page.get_by_title("Issues count")

        ###################################css定位#########################################################
        # 定位id=user的元素
        page.locator('#user')

        # id定位并获取text
        menu = page.locator('#app > section > section > aside > div > ul > li:nth-child(1)')
        print("元素的text:", menu.text_content())

        # 定位css为 homepage的元素
        page.locator('.homepage')

        # xpath定位相对位置为/html/body/div[1]/div[3] 的元素
        page.locator('/html/body/div[1]/div[3]')

        ########################################高级css定位###################################################
        # 获取元素的text列表(可以通过浏览器复制selector)
        test = page.locator(
            '#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator(
            "._title_1ec6m_20").all_inner_texts()
        print(test)

        # 遍历元素的text列表
        menu = page.locator(
            '#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator(
            "._title_1ec6m_20").all()
        for div in menu:
            print("333333", div.inner_text())

        # 多级css定位并点击(nth指定子级下标)
        page.locator('#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator(
            "._title_1ec6m_20").nth(1).click()

        ########################################locator定位器#################################################
        ##https://blog.csdn.net/karl41/article/details/119334673
        page.locator('#username')  # d选择器: #username 【# 表示ID】
        page.locator('.btn-primary')  # class选择器:.btn-primary 【. 号表示class】
        page.locator('p')  # 标签选择器:p 【选择所有 p 元素】

        # 子元素及分组相关
        page.locator('div, p')  # 分组选择器:div,p 【同时选择所有 div 元素和所有 p 元素】
        page.locator('div p')  # 后端选择器:div p 【选择 div 元素内部的所有 p 元素(包括子元素、孙子元素】
        page.locator('div > p')  # 子元素选择器:div>p 【选择 div 元素下的 p 子元素】
        page.locator('div + p')  # 相邻选择器:div+p 【选择 div 元素之后的所有兄弟 p 元素

        # 子元素和后代元素
        page.locator('.Username > button')  # 子元素 >,定位和父级元素相邻的元素,只能定位“亲儿子”;
        page.locator('.Username >> button')  # 定位后代元素 >>,定位父级元素下的所有元素,只要位于父元素下,都可以定位 ;

        # nth的用法
        page.locator("button").nth(0)  # 选择第一个匹配的button,数字0表示元素在其父元素的子元素中的位置索引
        page.locator("button >> nth=1")  # 选择第二个匹配的button
        page.locator("button >> nth=-1")  # 选择最后一个匹配的button

        ## locator定位器(这三个效果是一样的)
        cell_locator = page.locator('.ant-table-tbody').locator("tr").nth(1).locator("td").all_text_contents()
        cell_locator = page.locator('.ant-table-tbody>tr').nth(1).locator("td").all_text_contents()
        cell_locator =.page.locator('.ant-table-tbody>tr>>nth=1').locator("td").all_text_contents()

        ##多层级定位
        page.locator('.parent-class').locator('.child-class')
        page.locator('.parent-class').locator('.child-class').nth(2)

        ## first和last
        page.locator("button").first  # 选择第一个button元素
        page.locator("button").last  # 选择最后一个匹配的button

        ## 属性选择器
        page.locator('input[id="username"]')  # input[id=“username”] 选择 id 属性等于 “username” 的所有元素,[ ] 表示属性】
        page.locator('input[id*="erna"]')  # input[id*=“erna”] 【选择 id 属性包含单词 “erna” 的所有元素】
        page.locator('input[id^="use"]')  # input[id^=“use”] 【选择 id 属性以 “use” 开头的所有元素】
        page.locator('input[id$="me"]')  # input[id$=“me”] 【选择 id 属性以 “me” 结尾的所有元素】
        page.locator('[title~=flower]')  # [title~=flower] 【选择 title 属性包含单词 “flower” 的所有元素】
        page.locator('[lang|=en]')  # [lang|=en] 【选择 lang 属性值以 “en” 开头的所有元素】
        page.locator('input[name="username"][id="username"]')  # input[name=“username”][id=“username”] 【选择同时满足多个属性的元素】


        ###解释nth()、nth-child()区别(nth:是Playwright库自带的函数, nth-child是css选择器里的方法)
        #这两个代码效果一样
        cell_locator = self.page.locator('.ant-table-tbody').locator("tr").nth(1).locator("td").nth(1)
        cell_locator1 = self.page.locator(".ant-table-body > tr:nth-child(1) > td:nth-child(1)")

 

4.简单的方法

######################################等待元素#############################################
#在8秒内等待text为”知识中心“出现,并点击(超时会报错 )
page.wait_for_selector("text=知识中心", timeout=8000).click()
#在3秒内等待id为form_item出现
page.wait_for_selector("#form_item", timeout=3000)
# 设置最大等待超时时间(超过该时间则会报错 )
page.wait_for_timeout(3000)
#等待id为my-id元素,从DOM中完全移除
page.wait_for_selector("#my-id", state="detached")


###################################元素统计#################################################
##获取当前页面包含”知识中心“的个数
locator = page.locator("text=知识中心").count()
print("找到知识中心有:{}条".format(locator))


########################################判断################################################
##判断元素text为知识中心
if page.locator("text=知识中心").count():
    print("找到元素了")


######################################等待元素#############################################
#在8秒内等待text为”知识中心“出现,并点击(超时会报错 )
page.wait_for_selector("text=知识中心", timeout=8000).click()
#在3秒内等待id为form_item出现
page.wait_for_selector("#form_item", timeout=3000)
# 设置最大等待超时时间(超过该时间则会报错 )
page.wait_for_timeout(3000)
#等待id为my-id元素,从DOM中完全移除
page.wait_for_selector("#my-id", state="detached")


###################################元素统计#################################################
##获取当前页面包含”知识中心“的个数
locator = page.locator("text=知识中心").count()
print("找到知识中心有:{}条".format(locator))


#####################################键盘操作#############################################
page.get_by_placeholder("密码").press("Enter")
page.keyboard.insert_text("")
page.keyboard.press("Shift+A")
page.keyboard.press("Backspace")
page.keyboard.press(" ")  # 使用空格字符

 

 5.常用方法:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

###____________________________________登录操作________________________________________________
import time
from playwright.sync_api import sync_playwright
from datetime import datetime


def ai_01_login(url, username, password):
    """登录操作"""
    # ##使用同步的方式启动playwright
    playwright = sync_playwright().start()
    ##指定为有头模式,Ture为无头模式
    browser = playwright.chromium.launch(headless=False)
    ##新建一个浏览器上下文(相当于浏览器窗口,用于隔离各个页面之间的环境。)
    # context = browser.new_context()
    ##创建一个新的页面(_blank)
    page = browser.new_page()
    try:
        ##打开url
        page.goto(url)
        ## 暂停代码的执行,显示Playwright窗口,以便进行相关操作,如元素定位或录制操作。
        # page.pause()
        ## 设置最大等待超时时间(超过该时间则会报错 )
        # page.wait_for_timeout(3000)

        # 定位文字信息,返回元素
        page.get_by_text('账密登录', exact=True).click()
        # 通过id定位并输入内容
        page.locator('#form_item_phone').fill(username)
        page.locator('#form_item_password').fill(password)
        # 根据元素角色进行定位
        page.get_by_role("button", name="登 录").click()
        # 在8秒内等待元素出现,并点击
        page.wait_for_selector("text={}".format(username), timeout=8000).click()
        page.locator("text=知识中心").wait_for(timeout=8000)
        page.locator("text=知识中心").click()
        time.sleep(3)
        print("登录成功")

        # 多级css定位并点击(1表示文档)
        page.locator('#app > section > section > main > div > div._wrap_1ec6m_1 > div > div > div > div').locator(
            "._title_1ec6m_20").nth(1).click()
        time.sleep(3)
        timedata = page.locator(
            '#app > section > section > main > div > div._table_ywkou_56 > div > div > div > div > div > div > div > div > div > table > tbody > tr:nth-child(1) > td:nth-child(5)').text_content()
        timestamp = int(time.mktime(time.strptime(timedata, "%Y-%m-%d %H:%M:%S")))
        if int(time.time()) - timestamp < 30:
            print("上传成功,最新文件创建时间:{}".format(timedata))

    except Exception as e:
        print(f"发生错误:{e}")
    finally:
        # 确保即使发生异常,也不会关闭 playwright 实例
        pass

ai_01_login("https://home.qa.lightai.cn/#/login", "17388963381", "xiawei1314")



###____________________________________获取每一行每一列____________________________________
from playwright.sync_api import sync_playwright

# 启动 Playwright 的同步 API
with sync_playwright() as p:
    # 创建浏览器并打开新页面
    browser = p.chromium.launch()
    page = browser.new_page()

    # 假设我们导航到了一个包含表格的页面
    page.goto('http://example.com/some-page-with-table')

    # 定位到表格中的所有行 <tr>
    rows = page.locator('table tr')

    # 异步获取所有行元素
    row_elements = rows.all()

    # 遍历每一行
    for row in row_elements:
        # 定位到当前行的所有单元格 <td> 或 <th>
        cells = row.locator('td')

        # 异步获取当前行的所有单元格元素
        cell_elements = cells.all()

        # 遍历当前行的每个单元格,并打印文本内容
        for cell in cell_elements:
            cell_text = cell.text_content()
            print(cell_text)

        # 打印行分隔符
        print('-----')

    # 关闭浏览器
    browser.close()



###__________________________________获取每一行的指定列__________________________________________
from playwright.sync_api import sync_playwright

# 启动 Playwright 的同步 API
with sync_playwright() as p:
    # 创建浏览器并打开新页面
    browser = p.chromium.launch()
    page = browser.new_page()

    # 导航到包含表格的页面
    page.goto('http://example.com/some-page-with-table')

    # 定位到每一行的第2列单元格
    # 注意:索引从0开始,所以第2列的索引是1
    cells = page.locator('table tr td:nth-child(2)')

    # 异步获取所有匹配的单元格元素
    cell_elements = cells.all()

    # 遍历每个单元格,并打印其文本内容
    for cell in cell_elements:
        cell_text = cell.text_content()
        print(cell_text)

    # 关闭浏览器
    browser.close()




#___________________________________________执行后不要关闭浏览器(链接传送门传送门2)___________________________________________________
import time,os
from playwright.sync_api import Playwright, sync_playwright

def initialize_browser22():
    """打开浏览器,指定调试端口"""
    import subprocess
    # 定义要执行的命令
    command = (
        'cd C:\\Program Files\\Google\\Chrome\\Application && '
        'start chrome.exe --remote-debugging-port=9222 --user-data-dir=d:\\playwright\\user_data'
    )
    try:
        # 使用subprocess.run来执行命令
        result = subprocess.run(command, shell=True, text=True, capture_output=True)
        # 检查命令的返回码
        if result.returncode == 0:
            print("命令执行成功")
        else:
            print("命令执行失败,返回码:", result.returncode)
    except:
        print("执行出现异常")


def ai_01_login22(url,username,password):
    """登录操作"""
    with sync_playwright() as playwright:
        browser = playwright.chromium.connect_over_cdp("http://localhost:9222")
        default_context = browser.contexts[0]
        page = default_context.pages[0]
        print(page)
        ##直接打开网址
        page.goto(url)

        ##新建上下文后打开网址(相当于新标签窗口)
        # page = default_context.new_page()
        # page.goto(url)

        # 定位文字信息,返回元素
        page.get_by_text('账密登录', exact=True).click()
        # 通过id定位并输入内容
        page.locator('#form_item_phone').fill(username)
        page.locator('#form_item_password').fill(password)
        # 根据元素角色进行定位
        page.get_by_role("button", name="登 录").click()
        # 在8秒内等待元素出现,并点击
        page.wait_for_selector("text={}".format(username), timeout=8000).click()
        page.locator("text=知识中心").wait_for(timeout=8000)
        page.locator("text=知识中心").click()
        time.sleep(10)
        print("登录成功")

        #----------------
        # #关闭上下文
        # page.close()
        # #关闭浏览器
        # browser.close()


# if __name__ == '__main__':
    #初始化浏览器(打开浏览器)
    initialize_browser22()
    ai_01_login22("https://home.qa.lightai.cn/#/login","17388963381","xiawei1314")
#!/usr/bin/env python3
# coding: utf-8

######################################元素高亮、指定调试(调试用的)############################################################
"""为了避免重复操作等麻烦步骤,这里我使用playwright连接指定浏览器,手动进入相关网址,页面直接进行相关事件操作"""
__author__ = "梦无矶小仔"
import subprocess
from playwright.sync_api import sync_playwright, Page, BrowserContext

def initialize_browser22():
    """打开浏览器,指定调试端口"""
    # 定义要执行的命令(--remote-debugging-port 指定浏览器调试端口号,,--user-data-dir 用户配置文件目录)
    command = (
        'cd C:\\Program Files\\Google\\Chrome\\Application && '
        'start chrome.exe --remote-debugging-port=9222 --user-data-dir=d:\\playwright\\user_data'
    )
    try:
        # 使用subprocess.run来执行命令
        result = subprocess.run(command, shell=True, text=True, capture_output=True)
        # 检查命令的返回码
        if result.returncode == 0:
            print("命令执行成功")
        else:
            print("命令执行失败,返回码:", result.returncode)
    except:
        print("执行出现异常")


class Demo05:
    def __init__(self):
        """
        使用playwright连接谷歌浏览器(主要创建浏览器相关方法给后面使用)
        """
        self.playwright = sync_playwright().start()
        # 连接已经打开的浏览器,找好端口
        browser = self.playwright.chromium.connect_over_cdp("http://127.0.0.1:9222")
        self.default_context = browser.contexts[0]
        self.page = self.default_context.pages[0]

    def highlight(self):
        """打开网址,基础操作语法"""
        self.page.goto("https://www.baidu.com")
        ##高亮id=kw
        self.page.locator("#kw").highlight()

        ##执行并按回车
        self.page.locator("#kw").fill("testhome")
        self.page.locator("#kw").press("Enter")

        ##高亮多个元素,文本testhome
        # self.page.get_by_text("testhome").highlight()

        ##将定位器返回到第n个元素。下标是从0开始的。nth(0)表示选择第一个元素。
        #banana = self.page.get_by_role("listitem").nth(2)

        ##指定xx个高亮
        # self.page.get_by_text("testhome").nth(8).highlight()

        ##使用first定位第一个
        self.page.get_by_text("梦无矶").first.highlight()

        ##使用last定位最后一个
        self.page.get_by_text("梦无矶").last.highlight()


    def locator_position(self):
        """locator定位操作"""
        #这这里可以直接操作不用重新创建page,也不用打开url(比较适合调试)
        self.page.locator("#kw").fill("testhome")
        self.page.locator("#kw").press("Enter")


if __name__ == '__main__':
    ###启动浏览器(启动一次后面可以不用启动,常用于调试)
    #initialize_browser22()

    ##实例化用于连接浏览器
    mwj = Demo05()
    #调用相关方法
    #mwj.highlight()
    mwj.locator_position()

 

 

 

 

 

 

 

 

相关链接:

https://blog.csdn.net/liwenxiang629/article/details/129118199.........................................................运行环境问题:ImportError: DLL load failed,,汇总教程

https://cloud.tencent.com/developer/article/2326430........................................................................基础讲解 ,pytest的使用,,pytest执行后不显示日志

https://blog.csdn.net/lzf9651/article/details/134962943 ..................................................................元素定位基础,,元素定位和CSS技巧定位进阶,,分类元素定位,,元素定位,,locator定位

https://blog.csdn.net/LIFENG0402/article/details/121550064..........................................................汇总用法 ,断言相关,,汇总教程入门教程

https://blog.csdn.net/seanyang_/article/details/132252268.............................................................Playwright- 模拟接口,,api测试,,api测试2 ,,函数

https://cloud.tencent.com/developer/article/1890385 .....................................................................录制生成代码生成代码

 

posted on 2024-04-29 11:54  chen_2987  阅读(316)  评论(0)    收藏  举报

导航