我目前正在为烧瓶应用编写单元测试,这需要在测试期间保持打开会话。为此,我发现我可以使用test_request_context
。这工作正常,直到我需要发出多个请求。
我当前的测试涉及登录/注销系统,我需要确保在用户单击注销按钮时实际从会话中重置某些属性。
我的代码的一个粗略示例:
from unittest import TestCase
from flask import Flask, session
from mypackage import auth_blueprint
class FlaskTestCase(TestCase):
def setUp(self):
self.app = Flask(__name__)
self.app.secret_key = urandom(24)
self.app.register_blueprint(auth_blueprint) # The blueprint to test
self.client = self.app.test_client()
def test_login_logout():
with self.app.test_request_context("/auth/login", data={"username": "foo", "password": "bar"}, method="POST"):
assert session["logged_in"]
# How would I make A call to logout?
# self.client.post("/auth/logout") doesn't work
assert not session["logged_in"]
有谁知道如何在一次测试中进行多次通话并检查同一个会话?感谢您的帮助
答案 0 :(得分:1)
您应该能够为两个呼叫使用相同的上下文。我用flask_restful尝试了这个并且它有效。您可以阅读应用程序上下文以及它们的传递方式。此外,您可以尝试使用current_app上下文:
from flask import current_app
current_app.app_context()
我先试试这个:
from unittest import TestCase
from flask import Flask, session
from mypackage import auth_blueprint
class FlaskTestCase(TestCase):
def setUp(self):
self.app = Flask(__name__)
self.app.secret_key = urandom(24)
self.app.register_blueprint(auth_blueprint) # The blueprint to test
self.client = self.app.test_client()
self.app.app_context().push()
def test_login_logout():
with self.app.app_context():
self.client.post("/auth/login", data={"username": "foo", "password": "bar"})
assert session["logged_in"]
# How would I make A call to logout?
self.client.post("/auth/logout")
assert not session["logged_in"]
答案 1 :(得分:0)
您可以使用setUpClass和tearDownClass。首先,您需要定义一个在单独的测试文件中调用的全局TestCase。
我给出的示例是使用connexion。您可以通过更新setUpClass定义并仅将该应用程序定义为Flask应用程序来进行调整。
test_server.py
import unittest
import os
import connexion
import logbook
from config import db
from models import Book
# Logging configuration
log = logbook.Logger(__name__)
# Books Fixtures
BOOKS = [
{
'name': 'Book 1',
},
{
'name': 'Book 2',
},
{
'name': 'Book 3'
},
]
class TestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
basedir = os.path.abspath(os.path.dirname(__file__))
log.info("setUpClass")
# Setting UP the DB and the tests
cls.connex_app = connexion.App(__name__, specification_dir=basedir)
cls.connex_app.add_api('swagger.yml', validate_responses=True)
cls.connex_app.app.config['TESTING'] = True
cls.connex_app.app.config['WTF_CSRF_ENABLED'] = False
cls.connex_app.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'test.db')
# Delete DB if exists : not for production
if os.path.exists('test.db'):
os.remove('test.db')
db.create_all()
TestCase.add_sample_algorithm()
TestCase.add_sample_backtest()
cls.test_client = cls.connex_app.app.test_client()
@staticmethod
def add_sample_book():
# Iterate over the BOOKS Dictionary and populate the DB :
for book in BOOKS:
book_to_add = Book(name=book['name'])
log.info("## Book to add:" + str(book_to_add))
db.session.add(book_to_add)
db.session.commit()
@classmethod
def tearDownClass(cls):
log.info("tearDownClass ")
db.session.remove()
db.drop_all()
if os.path.exists('test.db'):
os.remove('test.db')
if __name__ == '__main__':
unittest.main()
然后,您可以在每个测试文件中调用测试服务器,该服务器将创建测试数据库,运行测试客户端,然后在完成一系列测试后将其拆解。以这种方式定义的setUpClass和tearDownClass可以避免出现问题(从多个测试文件调用测试服务器时出现蓝图(例如attributeError:蓝图之间发生名称冲突)。
from test_server import TestCase
class BookTest(TestCase):
@classmethod
def setUpClass(cls):
super(BookTest, cls).setUpClass()
# Additional initialization
@classmethod
def tearDownClass(cls):
super(BookTest, cls).tearDownClass()
def test_get_root(self):
resp = self.test_client.get('/')
self.assertEqual(404, resp.status_code)
def test_get_all_books(self):
resp = self.test_client.get('/api/books')
self.assertEqual(200, resp.status_code)
self.assertEqual(3, len(resp.json))
# Book 1 :
self.assertEqual(resp.json[0]['name'], "Book 1")
谢谢
阿尤布