使用pytest包来做程序测试。
$ pip install pytest
测试的应用可以使用官方的例子:
https://github.com/pallets/flask/tree/master/examples/tutorial
我们需要在程序根目录新建一个test文件夹,存放我们的测试文件。然后新建一个测试文件test_flaskr.py,命名格式最好是以test_开头,方便pytest框架自动检测。
先创建一个@pytest.fixture修饰的client函数,用来配置应用信息跟初始化数据库,每一个单独的测试都会调用这个pytest.fixture修饰的函数。
import os
import tempfile
import pytest
from flaskr import flaskr
@pytest.fixture
def client():
# db_fd
# tempfile 模块可以创建一个临时的数据库和初始化它。
db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp()
flaskr.app.config['TESTING'] = True
with flaskr.app.test_client() as client:
with flaskr.app.app_context():
flaskr.init_db()
yield client
os.close(db_fd)
os.unlink(flaskr.app.config['DATABASE'])
mkstemp()函数做了两件事情:返回一个低级文件句柄(file handle)和一个使用随机名称的数据库名。我们只需要使用db_fd围绕我们的测试,然后可以使用os.close()函数关闭文件。
测试函数要以test_开头。我们在test_flaskr.py文件添加一个访问"/"路径的测试:
def test_empty_db(client):
"""Start with a blank database."""
rv = client.get('/')
assert b'No entries here so far' in rv.data
client.get('/') 会发出一个GET请求,然后返回响应的数据,可以使用响应的data属性获取内容然后判断是否包含我们要测试的内容。
def login(client, username, password):
return client.post('/login', data=dict(
username=username,
password=password
), follow_redirects=True)
def logout(client):
return client.get('/logout', follow_redirects=True)
def test_login_logout(client):
"""Make sure login and logout works."""
rv = login(client, flaskr.app.config['USERNAME'], flaskr.app.config['PASSWORD'])
assert b'You were logged in' in rv.data
rv = logout(client)
assert b'You were logged out' in rv.data
rv = login(client, flaskr.app.config['USERNAME'] + 'x', flaskr.app.config['PASSWORD'])
assert b'Invalid username' in rv.data
rv = login(client, flaskr.app.config['USERNAME'], flaskr.app.config['PASSWORD'] + 'x')
assert b'Invalid password' in rv.data
因为登录跟退出页面可能会重定向,我们需要设置follow_redirects=True去跟踪页面跳转返回的结果。
def test_messages(client):
"""Test that messages work."""
login(client, flaskr.app.config['USERNAME'], flaskr.app.config['PASSWORD'])
rv = client.post('/add', data=dict(
title='<Hello>',
text='<strong>HTML</strong> allowed here'
), follow_redirects=True)
assert b'No entries here so far' not in rv.data
assert b'<Hello>' in rv.data
assert b'<strong>HTML</strong> allowed here' in rv.data
待续。。。