You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python版Playwright无法正确存储Cookie,登录测试失败求助

解决Playwright测试Flask应用登录时Cookie状态未正确存储的问题

问题描述

使用Playwright测试基于Python Flask开发的Web应用登录功能时,出现以下问题:

  • 页面存在Cookie授权弹窗,测试中已点击「Accept」按钮,弹窗消失,用户名和密码也正确输入,但点击登录后被重定向回登录页,提示必须先接受Cookie;手动操作登录正常。
  • 测试报错信息:
>       expect(page.get_by_text("Welcome, Harry. Select a timestable.")).to_be_visible()
E       AssertionError: Locator expected to be visible
E       Actual value: None 
E       Call log:
E       LocatorAssertions.to_be_visible with timeout 5000ms
E       waiting for get_by_text("Welcome, Harry. Select a timestable.")
  • 推测原因:Flask将Cookie同意状态存储在session cookie中,但Playwright测试环境下该Cookie未被正确传递到后续登录请求。

现有代码

Playwright测试代码

import re
from playwright.sync_api import Page, expect, sync_playwright

def test_homepage_has_correct_title(page: Page):
    page.goto("https://ttcoach.herokuapp.com/login")
    expect(page).to_have_title(re.compile("Times Table Coach"))

def test_accepting_cookies_hides_box(page: Page):
    page.goto("https://ttcoach.herokuapp.com/login")
    accept_button = page.get_by_role("button", name="Accept").click()
    # checking accept_button is None (doesn't exist)
    assert not accept_button

def test_logging_in(page: Page):
    page.goto("https://ttcoach.herokuapp.com/login")
    page.get_by_role("button", name="Accept").click()
    page.get_by_placeholder("Username").fill("Harry")
    page.get_by_placeholder("Password").fill("potter")
    page.get_by_role("button", name="Login").click()
    expect(page.get_by_text("Welcome, Harry. Select a timestable.")).to_be_visible()

Flask登录路由代码

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == 'POST':
        if request.form.get("accepted") == "yes":
            session["cookies"] = "yes"

        # checking if cookies are accepted
        if not "cookies" in session:
            return render_template("login.html", login_message = "You must accept the cookies to continue.", cookies = "")
        
        # saving user input
        username_entered = request.form.get("username")
        password_entered = request.form.get("password")

        # checking if user exists and password is correct
        user_retrieved = user_repository.get_one(database_connection.connect(), username_entered) 
        if user_retrieved == False or not bcrypt.checkpw(password_entered.encode('utf-8'), user_retrieved.password.encode('utf-8')):
            return render_template("login.html", login_message = "Incorrect username or password. Try again.", cookies = "yes")
        
        # logging in
        session["user"] = jsonpickle.encode(user_retrieved)
        return redirect("/select")
    
    elif request.method == 'GET':   
        # deleting user in case we were redirected here after logout
        if "user" in session:
            session.pop("user", default=None) 

        # checking if user has accepted cookies
        if "cookies" in session:
            return render_template("login.html", login_message = "Enter your login details.", cookies = "yes")
        else:
            return render_template("login.html", login_message = "Enter your login details.", cookies = "")

问题分析

  1. 无效断言误导测试结果:第二个测试中assert not accept_button是错误的,因为click()方法返回None,该断言只是验证变量值为None,并未真正检查Cookie弹窗是否消失、会话是否更新。
  2. 操作间缺少等待:点击Accept按钮后直接进行登录操作,可能此时Flask后端还未完成session设置,或页面状态未稳定,导致后续登录请求无法读取到Cookie同意状态。
  3. 超时时间不足:Heroku部署的应用可能存在响应延迟,默认5秒超时可能不足以等待目标页面加载完成。

解决方案

1. 修复无效断言,验证Cookie弹窗状态

修改第二个测试,使用Playwright的断言API正确验证弹窗消失:

def test_accepting_cookies_hides_box(page: Page):
    page.goto("https://ttcoach.herokuapp.com/login")
    accept_button = page.get_by_role("button", name="Accept")
    accept_button.click()
    # 正确验证按钮不再可见
    expect(accept_button).not_to_be_visible()

2. 优化登录测试,添加必要等待

在登录测试中,确保Accept操作完成、页面状态稳定后再执行登录步骤,并延长超时时间应对部署环境延迟:

def test_logging_in(page: Page):
    page.goto("https://ttcoach.herokuapp.com/login")
    
    # 点击Accept并等待弹窗消失,确认会话更新
    accept_button = page.get_by_role("button", name="Accept")
    accept_button.click()
    expect(accept_button).not_to_be_visible()
    
    # 等待用户名输入框可交互,确保页面状态稳定
    username_input = page.get_by_placeholder("Username")
    expect(username_input).to_be_enabled()
    
    # 执行登录操作
    username_input.fill("Harry")
    page.get_by_placeholder("Password").fill("potter")
    page.get_by_role("button", name="Login").click()
    
    # 延长超时时间,等待目标页面加载完成
    expect(page.get_by_text("Welcome, Harry. Select a timestable.")).to_be_visible(timeout=10000)

3. 可选:调试Cookie状态(排查用)

若问题仍存在,可在测试中添加Cookie打印步骤,确认session cookie是否被正确设置:

# 在点击Accept后添加以下代码
cookies = page.context.cookies()
for cookie in cookies:
    print(f"Cookie: {cookie['name']} = {cookie['value']}")

原理说明

  • Playwright的expect断言会自动等待目标元素达到预期状态,确保操作的原子性和稳定性。
  • 延长超时时间可以避免因部署环境延迟导致的断言失败。
  • 验证输入框可交互,确保页面已完成会话更新和渲染,避免后续操作提前执行。

内容的提问来源于stack exchange,提问作者jonasdiete

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:59:54