Python版Playwright无法正确存储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 = "")
问题分析
- 无效断言误导测试结果:第二个测试中
assert not accept_button是错误的,因为click()方法返回None,该断言只是验证变量值为None,并未真正检查Cookie弹窗是否消失、会话是否更新。 - 操作间缺少等待:点击Accept按钮后直接进行登录操作,可能此时Flask后端还未完成session设置,或页面状态未稳定,导致后续登录请求无法读取到Cookie同意状态。
- 超时时间不足: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
相关产品推荐
相关产品推荐

