Playwright中如何保持登录状态

 更新时间:2021年12月12日 10:23:12   作者:凌空摘星  
本文主要介绍了Playwright中如何保持登录状态,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

引言

在编写UI自动化测试用例的时候,通常会采用每个测试用例前打开新页面重新进行登录,以减少用例间的影响,比如一个测试用例执行失败会影响到下一个测试用例的执行,或者下一个用例的开始依赖于上一个用例的结束页面。但是这种方式会使得测试用例的执行时间大幅度上升,尤其是在测试用例划分的颗粒度比较小的时候;加入一个项目中有2000个测试用例,登录操作耗时2秒,那么光耗费在登录上面的时间就有4000秒,达到一个多小时了,严重影响测试执行效率,再假如项目中使用了验证码限制登录的情况,那么就更复杂了。所以,如果可以将登录状态保持住,开始测试用例的时候打开新页面,跳过登录直接进入到待测系统中,就可以大幅度提高测试执行效率。通常,每种UI自动化测试工具都会有类似的功能,这里以Playwright为例来介绍如何实现。

功能实现

在Playwright中提供了现成的方法,通过 context.storage_state(path='<文件路径>') ,可以将当前浏览器上下文的全部状态保存下来,在创建浏览器上下文时,添加 storage_state 参数即可读取保存的文件,从而完全恢复之前的浏览器状态。示例代码如下

# 首次登陆系统
from playwright.sync_api import sync_playwright

with sync_playwright() as playwright:
    browser = playwright.chromium.launch()
    context = browser.new_context()
    page = context.new_page()
  
  # 登陆系统
    page.goto('<login url>')
    page.fill('<username>', '<username selector>')
    page.fill('<password>', '<password selector>')
    page.click('<login button selector>')

  # 判断是否登陆成功
    assert 'Welcome' in page.title()
  
  # 保存状态文件
    context.storage_state(path='login_data.json')
# 使用已保存的状态文件跳过登录状态直接访问系统
with sync_playwright() as playwright:
    browser = playwright.chromium.launch()
  
  # 创建浏览器上下文时加载状态文件
    context = browser.new_context(storage_state='login_data.json')
    page = context.new_page()
  
  # 直接访问登录后的URL
    page.goto('<welcome url>')

  # 判断是否访问到登录后的页面
    assert 'Welcome' in page.title()

结合Pytest

通过以上代码验证了这种实现方式的可用性,还是很好用的。结合Pytest测试框架,可以通过fixture的形式提供一个已登录的page对象,可以直接在测试用例中使用,实现方式如下:

@pytest.fixture()
def logged_page():
    ss_file = 'login_data.json'
    with sync_playwright() as playwright:
        browser = playwright.chromium.launch()

    # 判断是否存在状态文件,有的话就加载
        if os.path.isfile(ss_file):
            context = browser.new_context(storage_state=ss_file)
        else:
            context = browser.new_context()
        page = context.new_page()

    # 直接跳转至登录后页面,前提是未登录用户访问待测系统会自动跳转至登录页面,如果你的系统逻辑不一样,需要修改
        page.goto('<welcome url>')

    # 通过title判断是否成功进入系统,如果没有需要进行登录,一般在第一次访问系统,或登录信息过期等原因会触发
        if 'Welcome' not in page.title():
            page.fill('<username>', '<username selector>')
            page.fill('<password>', '<password selector>')
            page.click('<login button selector>')
        yield page

    # 测试执行结束后保存状态文件,前提是测试用例中不能退出系统,安全起见加上异常处理
    try:
           context.storage_state(path=ss_file)
        except Exception as e:
            print(e)

结合Clent-Page Object模式

如前,结合Pytest已经可以实现一个很好用的fixture,在很多场景下已经够用了,不过我在项目中结合Clent-Page Object模式进行了另一种实现,核心代码如下:

class Client(ABC):
    playwright = None
    browser = None

    def __init__(self, url: str, *, storage_state_name: str = None):
        self.url = url
        self.context = None
        self.main_page = None
        self.storage_state_file_path = None
        if storage_state_name is not None:
            self.storage_state_file_path = os.path.join('storage_state', f'{storage_state_name}.json')

    @abstractmethod
    def register_page(self):
        pass

    @abstractmethod
    def login(self, **kwargs):
        pass

    @abstractmethod
    def is_logged(self):
        pass

    def start(self) -> None:
        Client.playwright = sync_playwright().start()
        Client.browser = Client.playwright.chromium.launch(**BROWSER_CONFIG)
        if self.storage_state_file_path is not None and os.path.isfile(self.storage_state_file_path):
            self.context = Client.browser.new_context(**CONTEXT_CONFIG, storage_state=self.storage_state_file_path)
        else:
            self.context = Client.browser.new_context(**CONTEXT_CONFIG)
        self.main_page = self.context.new_page()
        self.main_page.goto(self.url)

        self.register_page()

    def close(self) -> None:
        if self.storage_state_file_path is not None:
            if not os.path.exists('storage_state'):
                os.mkdir('storage_state')
            self.context.storage_state(path=self.storage_state_file_path)
        self.main_page.close()
        self.context.close()

def logged_user(client, url, *, scope = 'function', storage_state_name = None, **kwargs):
    @pytest.fixture(scope=scope)
    def user_fixture():
        user = client(url, storage_state_name=storage_state_name)
        user.start()
        logger.info(f'用户登录: {kwargs}')
        if not user.is_logged():
            user.login(**kwargs)
        yield user
        user.close()

继承Client类,使用 logger_user 函数来生成不同终端用户的fixture,以实现继承Pytest。

到此这篇关于Playwright中如何保持登录状态的文章就介绍到这了,更多相关Playwright保持登录状态内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python 根据网易云歌曲的ID 直接下载歌曲的实例

    python 根据网易云歌曲的ID 直接下载歌曲的实例

    今天小编就为大家分享一篇python 根据网易云歌曲的ID 直接下载歌曲的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-08-08
  • 详解Python如何与 java高效的交互

    详解Python如何与 java高效的交互

    这篇文章主要为大家介绍了详解Python如何与java高效的交互的方法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • python必备库Matplotlib画图神器

    python必备库Matplotlib画图神器

    这篇文章主要介绍了python必备库Matplotlib画图神器,Matplotlib 是 Python 中最受欢迎的数据可视化软件包之一,支持跨平台运行,它是 Python 常用的 2D 绘图库,同时它也提供了一部分 3D 绘图接口,更多详细内容,需要的小伙伴可以参考一下下面文章具体内容
    2022-03-03
  • Python脚本实现网卡流量监控

    Python脚本实现网卡流量监控

    这篇文章主要介绍了Python脚本实现网卡流量监控,本文直接给出实现代码,需要的朋友可以参考下
    2015-02-02
  • python绘制无向图度分布曲线示例

    python绘制无向图度分布曲线示例

    今天小编就为大家分享一篇python绘制无向图度分布曲线示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • 跟老齐学Python之赋值,简单也不简单

    跟老齐学Python之赋值,简单也不简单

    在《初识永远强大的函数》一文中,有一节专门讨论“取名字的学问”,就是有关变量名称的问题,本温故而知新的原则,这里要复习一下
    2014-09-09
  • Python函数默认参数常见问题及解决方案

    Python函数默认参数常见问题及解决方案

    这篇文章主要介绍了Python函数默认参数常见问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Python+wxPython实现一个简单的音乐播放器

    Python+wxPython实现一个简单的音乐播放器

    这篇文章主要为大家详细介绍了如何使用Python编程语言和wxPython模块创建一个简单的音乐播放器,文中的示例代码讲解详细,感兴趣的可以了解下
    2023-09-09
  • Pytorch中实现只导入部分模型参数的方式

    Pytorch中实现只导入部分模型参数的方式

    今天小编就为大家分享一篇Pytorch中实现只导入部分模型参数的方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-01-01
  • Java 超详细讲解核心类Spring JdbcTemplate

    Java 超详细讲解核心类Spring JdbcTemplate

    JdbcTemplate JdbcTemplate是Spring JDBC核心包(core)中的核心类,它可以通过配置文件、注解、Java 配置类等形式获取数据库的相关信息,实现了对JDBC开发过程中的驱动加载、连接的开启和关闭、SQL语句的创建与执行、异常处理、事务处理、数据类型转换等操作的封装
    2022-04-04

最新评论