Playwright + Pytest 实现 Web UI 自动化测试
前言
平时工作一直用的 Cypress,但是 Cypress 真的太慢了,就想看看有什么替代品。Selenium 我一直不太喜欢,正好看到微软出的 Playwright 好像蛮有意思的。虽然 Playwright 的 JS 版本 的 Star 是 Python 版本的十倍之多,不过我个人还是更喜欢 Python 和 Pytest,就还是用 Python 版的 Playwright 搭配 Pytest 来食用了。(其实是 js 不太熟悉 XD)
主流的 UI 自动化 框架对比可以参考这篇文章 []
本项目风格和我之前写的 api-test比较相似,越小越简单越好。
项目地址
Github:
本项目参考了 & 的项目
分层
定位符、页面操作、业务逻辑三层:合并成了 page 类 测试用例层:test 类(基于 pytest) 数据层:yaml 文件 (config 数据 与 fixtures 数据) 结果层:HTML 报告(基于 pytest-html,感兴趣可以改成 allure),Log 日志(暂无)
* 图来自 陈晓伍 的 《Python Web自动化测试设计与实现》
test 类 page @pytest.fixture 来自 pytest-playwright env 是自定义的 @pytest.fixture,用来读取当前环境的配置信息 使用内置的 browser @pytest.fixture 来 生成一个 page @pytest.fixture 提升作用域,以达到共用同一浏览器的效果
page 类 想了好几种方式,如何来使用page对象。本来想试试继承,但好像不行。 最终还是作为类属性来使用了。
config 数据,管理 base_url 等通用信息 fixtures 数据,就是测试用例的测试数据了,只是我习惯 Cypress 的命名方式了。
fixtures 我定义了2种获取方式。 一种是test 类中获取当前要用的测试对象的 yaml 文件
# test 类 @pytest.fixture() def fixtures(self): yield Tools.get_fixtures("baidu_search") # ---- 用法 ----- # test 类 fixtures[kerwords]
一种是放在conftest.py中,作为@pytest.fixture 来用
# conftest.py @pytest.fixture(scope="class") def fixtures(): def _fixtures(filename: str): from common.tools import Tools return Tools.get_fixtures(filename) yield _fixtures # ---- 用法 ----- # test 类 fixtures(baidu_search)[kerwords]
其他
虚拟环境使用的 poetry
conftest.py 文件中,pytest 钩子和 pytest-html 钩子都有详尽的注解
报告 用的 pytest-html,我还蛮喜欢的。
新功能
视频录制
Playwright 内置的视频录制,传入一个 路径就可以了。 还学到了一个新钩子
@pytest.fixture(scope="session") def browser_context_args(browser_context_args, tmpdir_factory: pytest.TempdirFactory): return { **browser_context_args, "record_video_dir": os.path.join(OUTPUT_DIR, "videos") }
allure 报告
在 feature/allure 分支
已知问题
- config 数据 和 fixtures 数据如何整合,目前还在思考
- Tools.get_config()、Tools.get_fixtures() 等依赖 env 信息的操作,只能放在__init__ 或 实例方法中。因为引入文件时会自动执行文件。此时还没有 env 信息,所以会报错。
# 错误 class BaiduSearchPage: host = Tools.get_config("base_url") def __init__(self, page: Page): self.page = page # 正确 class BaiduSearchPage: def __init__(self, page: Page): self.page = page self.host = Tools.get_config("base_url")