我目前正在使用 Pytest 测试我的 Flask 应用程序,但遇到了 POST 请求和重定向的问题。让我再解释一下。
用户想要注册我们的新站点,但必须确认他们拥有不同站点的帐户。一旦他们确认了另一个帐户的凭据,他们就会被带到注册页面。如果他们来自确认页面,他们只能点击注册页面,否则他们会被重定向回主页。
我想测试这个功能,并且可以成功地向确认页面发出 POST 请求。如果我不指定follow_redirects=True并打印响应数据,我会得到以下 HTML:
正在重定向...正在重定向...
您应该被自动重定向到目标 URL:/register?emp_id=1。如果没有点击链接。
伟大的!正是我要找的!我想被重定向到注册页面。
现在,当我指定follow_redirects=True并打印出响应数据时,我希望注册页面 HTML 能够返回。响应数据改为返回主页 HTML。
我进一步调查了问题出在哪里。正如我之前提到的,您可以点击注册页面的唯一方法是从确认页面。我request.referrer在测试期间查看了视图中的属性,它会返回None。我尝试Referrer在测试的 POST 请求中设置标头内容,但没有成功。
这是我正在使用的代码:
视图.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)
测试
基础.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
该db_data参数是base.py中的一个固定装置,它只是用注册流程工作所需的数据填充数据库。
我的目标是测试一个完整的注册流程,而不必将确认和注册分成两个测试。