我目前正在使用Pytest测试我的Flask应用程序,并遇到了一个关于POST请求和重定向的问题。让我更详细地解释一下。
用户想要注册我们的新网站,但必须确认他们在另一个网站上有账户。一旦他们确认了其他帐户的凭据,他们就会被带到注册页面。只有从确认页面进入才能访问注册页面,否则将被重定向回主页。
我想测试这个功能,并且可以成功地向确认页面发出POST请求。如果我不指定 follow_redirects=True
并打印响应数据,则会得到以下HTML:
Redirecting...
Redirecting...
You should be redirected automatically to target URL: /register?emp_id=1. If not click the link.
太好了!这正是我要找的!我想被重定向到注册页面。
现在当我确实指定了 follow_redirects=True
并打印出响应数据时,我期望返回注册页面的HTML。但是响应数据却返回了主页的HTML。
我进一步调查了问题所在。如我之前所提到的,唯一可以访问注册页面的方法是从确认页面进入。我在测试期间查看了视图中的 request.referrer
属性,它将返回 None
。我尝试在测试的POST请求中设置 Referrer
标头内容,但没有成功。
这是我正在使用的代码:
views.py
@app.route('/confirm', methods=['GET', 'POST'])
def confirm_bpm():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = BPMLoginForm()
if form.validate_on_submit():
bpm_user = BPMUser.query\
.filter(and_(BPMUser.group_name == form.group_name.data,
BPMUser.user_name == form.username.data,
BPMUser.password == encrypt(form.password.data)))\
.first()
if not bpm_user:
flash('BPM user account does not exist!')
url = url_for('confirm_bpm')
return redirect(url)
if bpm_user.user_level != 3:
flash('Only L3 Users can register through this portal.')
url = url_for('confirm_bpm')
return redirect(url)
url = url_for('register', emp_id=bpm_user.emp_id)
return redirect(url)
return render_template('login/confirm_bpm.html', form=form)
@app.route('/register', methods=['GET', 'POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('index'))
if request.method == 'GET' and\
request.referrer != request.url_root + 'confirm':
return redirect(url_for('index'))
emp_id = request.args.get('emp_id')
emp_id_exists = User.query.filter_by(emp_id=emp_id).first()
if emp_id_exists:
flash('User is already registered!')
return redirect(url_for('login'))
form = RegistrationForm()
if form.validate_on_submit():
new_user = User(login_type=form.login_type.data, login=form.login.data,
emp_id=emp_id)
new_user.set_password(form.password.data)
db.session.add(new_user)
db.session.commit()
flash('Registration successful!')
return redirect(url_for('login'))
return render_template('login/register.html', form=form)
TESTS
base.py
from config import TestConfig
from app import app, db
@pytest.fixture
def client():
"""
Initializes test requests for each individual test. The test request
keeps track of cookies.
"""
app.config.from_object(TestConfig)
client = app.test_client()
ctx = app.app_context()
ctx.push()
yield client
ctx.pop()
def confirm_bpm_login(client, group_name, username, password):
"""
POST to /confirm
"""
return client.post('/confirm', data=dict(
group_name=group_name,
username=username,
password=password,
submit=True
), follow_redirects=True)
test_auth.py
from app import db
from app.models import BPMCompany, BPMEmployee, User, BPMUser
from tests.base import client, db_data, login, confirm_bpm_login
def test_registration_page_from_confirm(client, db_data):
"""
Test registration page by HTTP GET request from "/confirm" url.
Should cause redirect to registration page.
!!! FAILING !!!
Reason: The POST to /confirm will redirect us to /register?emp_id=1,
but it will return the index.html because in the register view,
request.referrer does not recognize the POST is coming from /confirm_bpm
"""
bpm_user = BPMUser.query.filter_by(id=1).first()
rv = confirm_bpm_login(client, bpm_user.group_name,
bpm_user.user_name, 'jsmith01')
assert b'Register' in rv.data
< p> db_data
参数是在< strong> base.py 中的一个固定参数,它只是使用必要的数据填充数据库,以使注册流程正常工作。
我的目标是在不将确认和注册分成两个测试的情况下测试完整的注册流程。
Referer
错误,无法正常重定向。我之前提到在POST中设置Referer
头,但是听起来我把它放在了错误的HTTP操作上。感谢你澄清了这一点,Miguel。 - laskeym13