尝试 Playwright 进行网站自动化测试

文章目录

    为何要对网站进行自动化测试?

    最近在开发公司内部使用的人事系统,发现手动测试非常麻烦。每次改动代码后,都需要手动打开浏览器,点击各种按钮,填写各种表单,确认功能是否正常。这个过程既耗时,又容易出错。

    同时,我自己的网站也有类似的需求。写了一堆功能,每次上线都心惊胆战,生怕修改了一处代码,导致其他功能出错。而自动化测试可以大大降低这种焦虑感。尤其,现在好多功能都是用 AI 来实现的,我经常性的不看 AI 的具体实现代码,而是看它的输出结果是否符合预期。这种情况下,自动化测试就显得尤为重要。

    我看现在好多人推荐使用 Playwright,而且是微软出品的,感觉应该还不错。于是决定尝试一下。

    Python 还是 TypeScript?

    从 Playwright 官网的文档看,官方支持了多种语言,包括 JavaScript/TypeScript (Node.js)、Python、Java、C#(.NET)。看起来默认主推的是 TypeScript。

    Playwright 支持的语言

    但是,我感觉后续如果要集成 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 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式