为何要对网站进行自动化测试?
最近在开发公司内部使用的人事系统,发现手动测试非常麻烦。每次改动代码后,都需要手动打开浏览器,点击各种按钮,填写各种表单,确认功能是否正常。这个过程既耗时,又容易出错。
同时,我自己的网站也有类似的需求。写了一堆功能,每次上线都心惊胆战,生怕修改了一处代码,导致其他功能出错。而自动化测试可以大大降低这种焦虑感。尤其,现在好多功能都是用 AI 来实现的,我经常性的不看 AI 的具体实现代码,而是看它的输出结果是否符合预期。这种情况下,自动化测试就显得尤为重要。
我看现在好多人推荐使用 Playwright,而且是微软出品的,感觉应该还不错。于是决定尝试一下。
Python 还是 TypeScript?
从 Playwright 官网的文档看,官方支持了多种语言,包括 JavaScript/TypeScript (Node.js)、Python、Java、C#(.NET)。看起来默认主推的是 TypeScript。
但是,我感觉后续如果要集成 AI 接口之类,还是 Python 更方便一些,所以我选择了 Python 版本的 Playwright。其次,我对 Node.js 和 TypeScript 都厌恶至极,所以也不想用这个生态。十一期间,听了一个 Ruby on Rails 作者的播客,发现其也对 TypeScript 充满厌恶,看来这种情绪还是挺普遍的。我宁愿直接用 JavaScript,也不想用 TypeScript。好了,抱怨到此为止,继续正题。
我对比了一下 Python 和 TypeScript 版本的 Playwright 文档,发现 API 基本一致,差别不大。功能也没有分别。所以,选择 Python 版本的 Playwright 没有任何问题。
安装参考
https://playwright.dev/python/docs/intro
安装非常简单,就两行命令:
pip install pytest-playwright
playwright install
注意,如果是 Windows 上,建议不要使用 WSL1 下安装,毕竟没法运行肉眼可见的浏览器。(感觉有时候调试,还是用可见的直观一些)。 还是用 PowerShell 安装比较好。
测试代码
以测试我自己的博客网站为例。
需要新建一个以 test_
开头的 Python 文件,比如 test_blog.py
。
注意,不要用 main.py 之类的名字,否则 pytest 无法识别。
pytest 只执行以 test_ 开头的 python 文件。
测试代码如下:
import re
from playwright.sync_api import Page, expect
# 打开首页,确认标题正确
def test_has_title(page: Page):
page.goto("https://www.sunzhongwei.com/")
# Expect a title "to contain" a substring.
expect(page).to_have_title(re.compile("大象笔记"))
# 点击关于我链接,确认跳转正确
def test_get_started_link(page: Page):
page.goto("https://www.sunzhongwei.com/")
# Click the about me link.
page.get_by_role("link", name="关于我").click()
# Expects page to have a heading with the name of About Me.
expect(page.get_by_role("heading", name="自建博客")).to_be_visible()
执行测试成功
> pytest
==== test session starts ====
platform win32 -- Python 3.11.9, pytest-8.4.2, pluggy-1.6.0
rootdir: D:\work\nonews
plugins: anyio-3.7.1, base-url-2.1.0, playwright-0.7.1
collected 2 items
test_blog.py ..
==== 2 passed in 7.97s ====
除了初始化慢点,需要几秒钟,后续的测试都很快。
执行测试失败
如果执行失败,会看到具体的错误信息:
page = <Page url='https://www.sunzhongwei.com/'>
def test_has_title(page: Page):
page.goto("https://www.sunzhongwei.com/")
# Expect a title "to contain" a substring.
> expect(page).to_have_title(re.compile("Playwright"))
E AssertionError: Page title expected to be 're.compile('Playwright')'
E Actual value: 大象笔记 - Notes of Elephant Leg
E Call log:
E - Expect "to_have_title" with timeout 5000ms
E 9 × unexpected value "大象笔记 - Notes of Elephant Leg"
test_blog.py:8: AssertionError
对于点击操作,如果不符合预期,会看到:
Expect "to_be_visible" with timeout 5000ms
非常的人性化,会自动等待元素出现,直到超时为止。
请求头
在服务器 Nginx 日志中,看了一下请求头:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit /537.36 (KHTML, like Gecko) HeadlessChrome/140.0.7339.16 Safari/537.36
这个 Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。相比于现代浏览器,Headless Chrome 更加方便测试 web 应用,获得网站的截图,做爬虫抓取信息等。
总结
代码简单易懂,安装也方便。下一步试试用这个写个爬虫,抓取一些网页数据。
关于作者 🌱
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式