Flask SQLAlchemy没有';不要让我在测试夹具中多次设置烧瓶应用程序
我正在编写一个用于其数据库后端的应用程序 Flask应用程序是使用名为Flask SQLAlchemy没有';不要让我在测试夹具中多次设置烧瓶应用程序,flask,flask-sqlalchemy,Flask,Flask Sqlalchemy,我正在编写一个用于其数据库后端的应用程序 Flask应用程序是使用名为create\u app的应用程序工厂创建的 from flask import Flask def create_app(config_filename = None): app = Flask(__name__) if config_filename is None: app.config.from_pyfile('config.py', silent=True) else:
create\u app
的应用程序工厂创建的
from flask import Flask
def create_app(config_filename = None):
app = Flask(__name__)
if config_filename is None:
app.config.from_pyfile('config.py', silent=True)
else:
app.config.from_mapping(config_filename)
from .model import db
db.init_app(app)
db.create_all(app=app)
return app
数据库模型由一个名为Document
的对象组成
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Document(db.Model):
id = db.Column(db.Integer, primary_key=True)
document_uri = db.Column(db.String, nullable=False, unique=True)
我用它来做单元测试。我创建了一个名为app\u with_documents
的pytest,它调用应用程序工厂来创建一个应用程序,并在测试运行之前将一些Document
对象添加到数据库中,然后在单元测试完成后清空数据库
import pytest
from model import Document, db
from myapplication import create_app
@pytest.fixture
def app():
config = {
'SQLALCHEMY_DATABASE_URI': f"sqlite:///:memory:",
'TESTING': True,
'SQLALCHEMY_TRACK_MODIFICATIONS': False
}
app = create_app(config)
yield app
with app.app_context():
db.drop_all()
@pytest.fixture
def app_with_documents(app):
with app.app_context():
document_1 = Document(document_uri='Document 1')
document_2 = Document(document_uri='Document 2')
document_3 = Document(document_uri='Document 3')
document_4 = Document(document_uri='Document 4')
db.session.add_all([document_1, document_2, document_3, document_4])
db.session.commit()
return app
我有多个使用这个夹具的单元测试
def test_unit_test_1(app_with_documents):
...
def test_unit_test_2(app_with_documents):
...
如果我运行一个单元测试,一切都会正常。如果我运行多个测试,后续的单元测试将在测试夹具设置中的db.session.commit()
行崩溃,并显示“无这样的表:文档”
我所期望的是,每个单元测试都会获得自己的全新的、完全相同的预填充数据库,这样所有测试都会成功
(这是数据库表的问题,而不是单元测试的问题。即使我的单元测试只包含pass
,我也会看到错误)
错误消息提到缺少表的事实使它看起来像是create\u app
中的db.create\u all(app=app)
在第一次单元测试运行后不会被调用。但是,我已经在调试器中验证了,正如预期的那样,每个单元测试都会调用一次此应用程序工厂函数
我对db.drop_all()的调用可能是清除数据库的错误方法。所以,我没有在内存中创建数据库,而是尝试在磁盘上创建一个数据库,然后作为测试夹具清理的一部分删除它。(这是烧瓶文档中的技术。)
这会产生相同的错误
- 这是烧瓶和/或SQLAlchemy中的错误吗
- 编写预先填充应用程序数据库的烧瓶测试装置的正确方法是什么
这是Flask 1.0.2、Flask SQLAlchemy 2.3.2和pytest 3.6.0,它们都是当前的最新版本。在我的
conftest.py
中,我在我的应用程序中导入了model.py
的内容
from model import Document, db
我使用Pycharm的pytest runner在Pycharm中运行单元测试。相反,如果我使用python-m pytest从命令行运行测试,我会看到以下错误
ModuleNotFoundError: No module named 'model'
ERROR: could not load /Users/wmcneill/src/FlaskRestPlus/test/conftest.py
通过在conftest.py
中完全限定导入路径,我可以从命令行运行测试
from myapplication.model import Document, db
当我这样做时,所有的单元测试都通过了。当我从Pycharm内部运行单元测试时,它们也通过了
因此,我似乎在单元测试中错误地编写了导入语句。然而,当我通过Pycharm运行这些单元测试时,没有看到关于导入的错误消息,而是启动了脚本,但随后出现了奇怪的SQL错误
我仍然没有弄明白为什么我会看到奇怪的SQL错误。大概是关于处理全局状态的方式的一些微妙之处。但是更改导入行解决了我的问题
ModuleNotFoundError: No module named 'model'
ERROR: could not load /Users/wmcneill/src/FlaskRestPlus/test/conftest.py
from myapplication.model import Document, db