ETJava Beta | Java    注册   登录
  • 搜索:
  • 【Playwright+Python】系列教程(八)鉴权Authentication的使用

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/longronglang/p/18349921
    如有侵权 请联系我们删除  (页面底部联系我们)  

    写在前面

    还是有些絮叨的感觉,官方翻译和某些博主写那个玩楞,基本都是软件直接翻译后的产物。

    读起来生硬不说,甚至有的时候不到是什么意思,真的是实在不敢恭维。

    到底是什么意思?

    就是你已经登陆过一次,在Session、Cookie未失效的情况下,登录过一次后,下次就不用再走一遍登录的过程,从而缩短了脚本执行时间,提高了测试效率。

    我说清楚了吗?

    明白了,谢谢!

    自己能办到的事,不求别人,哈哈哈!

    鉴权Authentication的使用

    1、核心概念

    这是官方给的必要配置,我来直接贴下吧,如下:

    mkdir -p playwright/.auth
    echo $'\nplaywright/.auth' >> .gitignore
    

    说明:恕我直言,加不加都行,并不影响什么,可忽略!

    2、核心思想

    每次运行脚本前,都需要跑一次登录的过程。

    按照我们之前的习惯,肯定也要将登录抽离,放到公共方法里是吧,但我们这里要做的就是一个加强。

    什么意思呢,就是登录一次,下次就不登录直接执行测试了。

    3、实战场景举栗

    场景:现在我要登录墨滴,然后点击写文章。

    核心:重复使用已登录状态

    3.1、使用cookies存储

    Playwright 允许在测试中重用已登录状态,通过 browserContext.storageState() 方法提取 cookies 和本地存储的认证状态,以便在多个测试中避免重复登录。
    示例代码:

    # -*- coding: utf-8 -*-
    # @Time    : 2024/08/08 20:03
    # @Author  : longrong.lang
    # @FileName: test_authentication.py
    # @Software: PyCharm
    # @Cnblogs :https://www.cnblogs.com/longronglang
    # @Motto:你只管努力,剩下的交给天意.
    import pytest
    from playwright.sync_api import expect, Page
    
    # 创建一个全局变量来保存存储状态
    storage = None
    
    
    def test_login(page: Page):
        global storage
        page.goto("https://www.mdnice.com/")
        page.get_by_text("登录 / 注册").click()
        page.get_by_text("邮箱登录 >").click()
        # Interact with login form
        page.get_by_placeholder("邮箱地址,比如:example@exapmle.com").fill("username@qq.com")
        page.get_by_placeholder("请输入密码").fill("password")
        page.get_by_text("我要登录啦!").click()
        page.wait_for_timeout(1000)
        # 断言页面标题是百度一下,你就知道
        expect(page.get_by_text('社区日更文章领福利')).to_have_text("社区日更文章领福利")
        # Save storage state into the file.
        storage = page.context.storage_state(path="state.json")
    
    
    # 在其他测试中,创建新的上下文并使用之前保存的存储状态
    def test_write_article(page: Page) -> None:
        global storage
        """
        方法1
        创建新的上下文,使用之前存储的状态文件state.json
        new_context = page.context.browser.new_context(storage_state=storage)
        new_page = new_context.new_page()
        """
    
        """
        方法2
        直接新建一个页面,使用之前存储的状态文件state.json
        """
        new_page = page.context.browser.new_page(storage_state=storage)
        new_page.goto("https://www.mdnice.com/")
        new_page.get_by_text("写文章").click()
    
    
    if __name__ == '__main__':
        pytest.main(['-vs', 'test_authentication.py'])
    
    

    效果:
    image.png
    这两种方式上,虽然用例可以执行成功,但是新开了好几个浏览器窗口

    3.2、使用Session存储

    Cookies 和本地存储的身份验证状态可以跨浏览器使用,但 Session 存储无法持久化,Playwright 不提供相应的 API,需手动实现保存和加载。

    示例代码:

    # -*- coding: utf-8 -*-
    # @Time    : 2024/08/08 21:30
    # @Author  : longrong.lang
    # @FileName: test_session storage.py
    # @Software: PyCharm
    # @Cnblogs :https://www.cnblogs.com/longronglang
    # @Motto:你只管努力,剩下的交给天意.
    # contest.py
    import os
    
    import pytest
    from playwright.sync_api import Page
    
    
    # 定义全局登录
    @pytest.fixture(scope="function", autouse=True)
    def page(page: Page):
        page.goto("https://www.mdnice.com/")
        page.get_by_text("登录 / 注册").click()
        page.get_by_text("邮箱登录 >").click()
        # Interact with login form
        page.get_by_placeholder("邮箱地址,比如:example@exapmle.com").fill("username@qq.com")
        page.get_by_placeholder("请输入密码").fill("password")
        page.get_by_text("我要登录啦!").click()
        page.wait_for_timeout(1000)
        # 断言页面标题是百度一下,你就知道
        expect(page.get_by_text('社区日更文章领福利')).to_have_text("社区日更文章领福利")
        # 获取当前页面的会话存储
        session_storage = page.evaluate("() => JSON.stringify(sessionStorage)")
        # 将会话存储存储为环境变量
        os.environ["SESSION_STORAGE"] = session_storage
        session_storage = os.environ["SESSION_STORAGE"]
        new_context = page.context
        new_context.add_init_script("""(storage => {
          if (window.location.hostname === 'example.com') {
            const entries = JSON.parse(storage)
            for (const [key, value] of Object.entries(entries)) {
              window.sessionStorage.setItem(key, value)
            }
          }
        })('""" + session_storage + "')")
        new_page = new_context.new_page()
        yield new_page
    
    
    # test_demo.py
    from playwright.sync_api import Page, expect
    
    
    def test_write_article(page: Page) -> None:
        page.goto("https://www.mdnice.com/")
        page.get_by_text("写文章").click()
        page.wait_for_timeout(1000)
    
    
    if __name__ == '__main__':
        pytest.main(['-vs', 'test_authentication.py'])
    
    

    效果:
    image.png
    这样写,比较优雅,至少不会同时打开多个浏览器,但还是多了一个tab,整体问题不大。

    写在最后

    前天看过一个博主写的文章,真的震撼到我了,超级细致,而且代入感很强。

    顿时让我感觉到,好的技术文章,也是有灵魂的。

    那么问题来了,要是你来写技术文章?

    你该怎么写呢?