我正在为使用flask_sqlalchemy扩展名在Flask中编写的REST API编写单元测试。因为我有许多模型类,所以我编写了一个TestCase
子类来执行测试数据库的标准setUp / cleanUp。我的所有测试类都继承自此。单独运行时每个测试都会成功,但是当我在一个类中运行多个测试时,第二个setUp()在self.db.session.commit()
上失败(我试图在User表中添加一个条目),因为self.db.create_all()
(无声地)无法创建任何表。
这是我的基础测试类,位于测试包的__init__.py
中:
import unittest
from .test_client import TestClient
from .. import create_app
from pdb import set_trace as DBG
class ApiTest(unittest.TestCase):
default_username = 'fred'
default_password = 'bloggs'
db = None
def setUp(self):
try:
self.app = create_app('testing')
self.addCleanup(self.cleanUp)
self.ctx = self.app.app_context()
self.ctx.push()
from .. import db
self.db = db
self.db.session.commit()
self.db.drop_all(app=self.app)
from ..models import User, Player, Team, Match, Game
# self.app.logger.debug('drop_all())')
self.db.create_all(app=self.app)
# self.app.logger.debug('create_all())')
user = User(user_name=self.default_username)
user.password = self.default_password
self.db.session.add(u)
self.db.session.commit()
self.client = TestClient(self.app, user.generate_auth_token(), '')
except Exception, ex:
self.app.logger.error("Error during setUp: %s" % ex)
raise
def cleanUp(self):
try:
self.db.session.commit()
self.db.session.remove()
self.db.drop_all(app=self.app)
# self.app.logger.debug('drop_all())')
self.ctx.pop()
except Exception, ex:
self.app.logger.error("Error during cleanUp: %s" % ex)
raise
有人能告诉我这里有什么问题吗?
编辑:根据要求添加了create_app()
的代码。
# chessleague/__init__.py
import os
from flask import Flask, g
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from . import config
app = None
db = None # The database, initialised in create_app()
def create_app(config_name):
app = Flask(__name__)
app.config.update(config.get_config(config_name))
# if app.config['USE_TOKEN_AUTH']:
# from api.token import token as token_blueprint
# app.register_blueprint(token_blueprint, url_prefix='/auth')
import logging
from logging.handlers import SysLogHandler
syslog_handler = SysLogHandler()
syslog_handler.setLevel(logging.WARNING)
app.logger.addHandler(syslog_handler)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
global db
db = SQLAlchemy(app)
db.init_app(app)
from .models import User,Player,Game,Match,Team,Post
db.create_all()
from .api import api as api_blueprint
app.register_blueprint(api_blueprint, url_prefix='/chessleague')
return app
`
答案 0 :(得分:1)
create_all()
适用于通过导入带模型的模块发现的元数据。在你的情况下,模特'元数据绑定到db
的{{1}},但您从models.py
create_all()
调用chessleague/__init__.db
,这是SqlAlchemy的不同对象。您可以使用create_app()
中的db
来解决此问题:
models.py
答案 1 :(得分:0)
这是适用于我的初始化序列 - 欢迎评论!
我的测试班setUp()
从主应用包调用create_app(config_name)
。
主应用程序包(__init__.py
)在模块级别创建应用程序实例,即app=Flask(my_app_package_name)
然后我的功能
create_app(config_name)
db
(作为model_db
)
此导入在models.py中的模块级别创建符号db
,后跟模型类定义:
# models.py
from . import app
db = SQLAlchemy(app)
...
class User(db.Model)
...
etc
现在一切都设置正确:可以从models.py中的任何位置导入符号'db',我可以从我的测试db.create_all()
成功调用setUp()
。
@Fian,你可以发布你的解决方案作为答案,所以我可以给你信用吗?