我目前正在为一个flask应用程序编写单元测试,该应用程序需要在测试期间保持打开的会话。为此,我发现我可以使用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"]
有人知道我如何在一次测试中进行多个调用并检查相同的会话吗?提前感谢你的帮助
发布于 2017-08-24 04:04:29
您应该能够对两个调用使用相同的上下文。我已经在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"]
发布于 2019-10-14 10:45:34
您可以使用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")
谢谢,
阿尤布
https://stackoverflow.com/questions/45821222
复制