我正在使用Pytest测试我的Flask应用。我有3个文件
tests/
--conftest.py
--test_one.py
--test_two.py
如果我使用以下命令运行test_one.py
或 test_two.py
,它将正常运行。
python -m pytest tests/test_one.py
当我尝试使用以下命令运行所有测试时出现问题:
python -m pytest tests
我收到此错误:
AssertionError: View function mapping is overwriting an existing endpoint function: serve_static
我实际上并不为这个错误感到惊讶,因为init_app(app)
被调用了两次(每个文件一次),并且我从未拆解实际的app
。
我的问题是,是否有一种方法可以完全拆解flask应用程序并为每个单独的测试重建它??我正在寻找进行拆解的实际命令(即{{1} })
编辑:如果可以解决此问题(无需创建新的解决方案),我愿意设置Flask应用测试环境的其他方法。
编辑2:我发现了this个问题。这很相似,可以解决我的问题,但是涉及到函数内部的导入。我怀疑必须有更好的方法。
conftest.py
app.teardown()
app / __ init __。py
import os
import pytest
from app import app, init_app
from config import TestConfig
@pytest.fixture(scope='function')
def client():
app.config.from_object(TestConfig)
with app.test_client() as client:
with app.app_context():
init_app(app)
yield client
try:
os.remove('tests/testing.db')
except FileNotFoundError:
pass
答案 0 :(得分:2)
我会在每个继承TestCase的文件中创建一个类。这样,您可以在每次测试之前使用函数setup()
将您的testclient生成为实例变量。这样,您可以确保每个测试都具有相同的环境。
from unittest import TestCase
from app import app as application
class TestApplication(TestCase):
def setUp(self):
self.client = application.app.test_client()
def test_sth(self):
r = self.client.get('/approute2sth')
self.assertEqual(r.status_code, 200)
def test_sth_else(self):
r = self.client.get('/approute2sth_else')
self.assertEqual(r.status_code, 200)
答案 1 :(得分:0)
我正在考虑解决方案,但不涉及拆除flask应用程序。我不希望每个测试案例都拆掉它,因为这本身会导致每个测试案例的正常运行时间增加(除非flask应用程序初始化对于每个测试案例都是唯一的)
由于测试在pytest中并行运行,因此您可以执行以下操作
try:
app
except NameError:
app.config.from_object(TestConfig)
with app.test_client() as client:
with app.app_context():
init_app(app)
else:
print("App is already configured. Let us proceed with the test case")
您可以将其包装在单例类中,而不是也采用上述方法
答案 2 :(得分:0)
以下各项的某些组合可能有效。我认为,这是完成此操作的旧方法(尽管我自己从未这样做过)。我的印象是pytest
使用固定装置的概念来使直接teardown()
变得不必要。
#clear current db session
db.session.remove()
#drop all tables in db
db.drop_all()
#remove app_context
app.app_context.pop()
有关更多讨论,请参见this blog post on pytest。
答案 3 :(得分:0)
最终,我的问题是我如何创建app
。由于它是在__init__.py
中作为全局变量创建的,因此我无法为每个测试对其进行 remake 。我重构了__init__.py
(以及代码的其余部分),以使用create_app
函数,在其中可以一次又一次地创建相同的应用程序。以下代码最终起作用。
app / __ init __。py
def create_app(config)
app = Flask(__name__)
app.url_map._rules.clear()
from .models import db
app.config.from_object(config)
with app.app_context():
return app
def init_app(app):
...
conftest.py
import os
import pytest
from app import create_app, init_app
from config import TestConfig
@pytest.fixture(scope='function')
def client():
app = create_app()
app.config.from_object(TestConfig)
with app.test_client() as client:
with app.app_context():
from app.models import db
init_app(app, db)
yield client
try:
os.remove('tests/testing.db')
except FileNotFoundError:
pass