51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

测试开发精英班,通向高级软件测试工程师【好消息】企业内训服务上线啦!项目为王,自动化测试提升加速器 !横扫BAT,Python全栈测试开发技能大全
【第122期】:如何入门接口自动化测试!参与调查问卷 缔造行业趋势 月薪15K+的测试开发必备技能? 【活动】为视频UP主打CALL,互动领福利!
查看: 477|回复: 0

[原创] 整合playwright和pytest框架实施自动化测试实践

[复制链接]
  • TA的每日心情

    2021-9-6 09:30
  • 签到天数: 537 天

    连续签到: 1 天

    [LV.9]测试副司令

    发表于 2021-4-27 11:43:24 | 显示全部楼层 |阅读模式
    一、工具介绍
            playwright是微软公司开发的一款非常强大的开源自动化测试工具。之所以强大有以下原因:
            1. 支持所有主流浏览器:Chrome、Firefox、Safari、MS Edge。
            2. 支持无头模式和有头模式运行。
            3. 提供同步、异步的API,可以结合Pytest使用。
            4. 支持浏览器端的自动化脚本录制。
            5. 针对Python语言的自动化工具。
            6. 支持的操作系统有Linux、Mac OS以及Windows。
            7. 可以使用docker进行运行环境的安装。
    二、安装环境
            1. 安装python,playwright需要3.7及以上版本的Python,因此至少要安装Python3.7以上的版本(最好用3.7,我试了下3.8有兼容问题)
            2. 到https://github.com/microsoft/playwright-python去下载项目代码,主要是那个local_requirements.txt
            3. 使用pip3 install playwright==1.8.0a1(这里最好指定版本)
            3. 使用 pip3 install -r local_requirements.txt安装所有的依赖包。
            4. 使用python3 -m playwright install 安装浏览器驱动模块。(用清华的镜像)
    这里在命令窗口运行:pip3 -v config list查看系统中的pip.ini文件,下面这个是我的。
    1. <font size="3">[global]
    2. index-url = https://pypi.tuna.tsinghua.edu.cn/simple
    3. #index-url=http://mirrors.aliyun.com/pypi/simple/
    4. #[install]
    5. #trusted-host=mirrors.aliyun.com</font>
    复制代码

    这里需要注释掉aliyun,最好在白天或早上安装这个,速度会快些。其他时候还是用aliyun的镜像会快些。
            5. 检查安装是否成功,看到如下图界面,则表示安装成功。
    三、脚本录制
            playwright的脚本录制需要使用命令codegen,下面详细解释以下这个命令的用法
    这个命令需要用的参数如下:
    -o或--output <file name> 指定保存脚本的文件路径及文件名
    --target <language>  指定生成脚本的语言:python、JavaScript,C#等
    -b  指定录制使用的浏览器:如, -b chromium(Chrome浏览器);-b firefox;-b webkit三种。
    四、项目实战
            项目:        在线商城
            1. 脚本录制
    python3 -m playwright codegen -o 'login_b2c.py' --target python -b chromium http://localhost:8080/b2c/index.html
    以上为命令执行后进入的界面,当鼠标滑过元素的时候,会自动提示元素的xpath,而且启动的是无痕浏览模式,很容易和本地浏览的页面进行区分。
    点击登录链接,弹出下图:
    输入必要的信息,进行登录。
    关闭浏览器,输出脚本文件:这里可以看到我们的脚本文件正是命令中指定的那个文件名,右侧为脚本文件代码,这里使用的是同步模式。源码如下
    1. <font size="3">rom playwright import sync_playwright
    2. def run(playwright):
    3.     browser = playwright.chromium.launch(headless=False)
    4.     context = browser.newContext()
    5.     # Open new page
    6.     page = context.newPage()
    7.     # Go to http://localhost:8080/b2c/index.html
    8.     page.goto("http://localhost:8080/b2c/index.html")
    9.     # Click text=/.*登录.*/
    10.     page.click("text=/.*登录.*/")
    11.     # assert page.url == "http://localhost:8080/b2c/login.html"
    12.     # Click input[name="username"]
    13.     page.click("input[name=\"username\"]")
    14.     # Fill input[name="username"]
    15.     page.fill("input[name=\"username\"]", "tester")
    16.     # Press Enter
    17.     page.press("input[name=\"username\"]", "Enter")
    18.     # Click input[name="password"]
    19.     page.click("input[name=\"password\"]")
    20.     # Fill input[name="password"]
    21.     page.fill("input[name=\"password\"]", "123456")
    22.     # Click input[name="validcode"]
    23.     page.click("input[name=\"validcode\"]")
    24.     # Fill input[name="validcode"]
    25.     page.fill("input[name=\"validcode\"]", "1111")
    26.     # Click input[type="button"]
    27.     # with page.expect_navigation(url="http://localhost:8080/b2c/index.html"):
    28.     with page.expect_navigation():
    29.         page.click("input[type=\"button\"]")
    30.     page.close()
    31.     # ---------------------
    32.     context.close()
    33.     browser.close()
    34. with sync_playwright() as playwright:
    35.     run(playwright)</font>
    复制代码

    从这个录制的脚本中发现以下问题:
            1playwright一开始是建立了一个浏览器,这里用的是chromium,然后使用浏览器实例化一个上下文对象context,再通过context实例化一个page对象,也就是说,使用context.newPage()可以实例化多个页面,页面之间不共享session和cookie。
            2page可以通过定位器,定位页面上的各个元素,所以要用好playwright,page对象肯定是要好好研究的。
            3、不足之处,playwright没有提供录制的时候断言,虽然内建的断言方法不少,但是只能手动写上去。
            4、需要参数化,好在playwright集成了pytest功能,这个我们就得好好利用下了。
    2. 整合pytest和playwright
            经过研究,发现playwright自己没有参数化的能力,如果要参数化,还是得自己写代码去赋值,这里考虑和pytest结合,使用pytest的参数化和fixture可以完整实现参数化和关联的效果。
    代码解释
    1. <font size="3"># coding=utf-8
    2. from playwright.sync_api import Page
    3. import pytest
    4. # 此处构造测试用例所需的数据,第一位是用户名,第二位是密码,第三位为预期结果
    5. data=[['tester','123456','您好:tester'],['tester1','123456','您好:tester1'],['tester2','1234567','账号密码错误']]
    6. # 使用pytest.mark.parametrize引入用户数据
    7. @pytest.mark.parametrize('userdata',data)
    8. # 测试函数的第一个参数为引用playwright提供的Page,这是一个fixture,需要安装
    9. # pytest-playwright
    10. def test_login(page:Page,userdata):
    11.     page.goto("http://localhost:8080/b2c/index.html")
    12.      # Click text=/.*登录.*/
    13.     page.click("text=/.*登录.*/")
    14.     # assert page.url == "http://localhost:8080/b2c/login.html"
    15.     # Click input[name="username"]
    16.     page.click("input[name=\"username\"]")
    17.     # Fill input[name="username"]
    18.     # page.fill("input[name=\"username\"]", "tester")
    19.     page.fill("input[name=\"username\"]", userdata[0])
    20.     # Press Enter
    21.     page.press("input[name=\"username\"]", "Enter")
    22.     # Click input[name="password"]
    23.     page.click("input[name=\"password\"]")
    24.     # Fill input[name="password"]
    25.     page.fill("input[name=\"password\"]", userdata[1])
    26.     # Click input[name="validcode"]
    27.     page.click("input[name=\"validcode\"]")
    28.     # Fill input[name="validcode"]
    29.     page.fill("input[name=\"validcode\"]", "1111")
    30.     # Click input[type="button"]
    31.     # 因为需要转换页面,这里需要主动等待1秒钟,这个wait_for_timeout的单位是毫秒
    32.     page.wait_for_timeout(1000)
    33.     page.click("input[type=\"button\"]")
    34.    # 页面刷新较慢,这里我设了3秒等待
    35.     page.wait_for_timeout(3000)
    36.    # 断言,这里使用了in的方式,为了简便。playwright提供了很多的assert断言方式
    37.    # 可以阅读官方文档:https://playwright.dev/python/docs/assertions
    38.     assert userdata[2] in page.content()
    39.     # Close page
    40.     page.close()

    41. if __name__ == '__main__':
    42.    # 使用pytest.main来运行测试,--headful是有界面运行,删掉,就是无头模式
    43.    # 这里可以看出playwright的有头指的是要启动浏览器,无头模式就是不看到浏览器运行
    44.     pytest.main(['-v','login_b2c.py','--headful'])</font>
    复制代码
    测试运行结果:
    1. <font size="3">/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7 /Users/huminghai/dev/py_pro/demo/login_b2c.py
    2. ========================test session starts ====================
    3. platform darwin -- Python 3.7.1, pytest-6.1.0, py-1.10.0, pluggy-0.13.1 -- /Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7
    4. cachedir: .pytest_cache
    5. rootdir: /Users/huminghai/dev/py_pro/demo
    6. plugins: base-url-1.4.2, sugar-0.9.4, flaky-3.7.0, xdist-2.1.0, cov-2.10.1, asyncio-0.14.0, playwright-0.0.11, timeout-1.4.2, forked-1.3.0
    7. collecting ... collected 3 items

    8. login_b2c.py::test_login[chromium-userdata0] PASSED                      [ 33%]
    9. login_b2c.py::test_login[chromium-userdata1] PASSED                      [ 66%]
    10. login_b2c.py::test_login[chromium-userdata2] PASSED                      [100%]

    11. ======================= 3 passed in 41.42s ====================

    12. <a href="http://h.atstudy.com/atstudy/17yearesActivity/public/index.html?secret=49ba59abbe56e057"><font style="background-color: deepskyblue;">Process finished with exit code 0</font></a></font>
    复制代码

    五、总结
            palywright-python的优点非常突出,在脚本录制方面非常方面,而且元素抓取很精准,这点比webdriver要好用。最重要的是palywright-python和pytest结合真的可以为所欲为啊。pytest提供报告模块,各种好用的插件,而palywright-python提供精准的界面元素定位抓取,二者双剑合璧,使得UI自动化测试的未来变得光明起来。
            另外别相信palywright-python所谓的不用编码就可以自动化,这个不太可能的,毕竟不管怎么录制脚本,参数化、关联、断言三件套总是要的,因此学好Python,才是做好自动化测试的基础。

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2021-10-26 07:56 , Processed in 0.057817 second(s), 26 queries .

    Powered by Discuz! X3.2

    © 2001-2021 Comsenz Inc.

    快速回复 返回顶部 返回列表