【发布时间】:2017-06-14 18:10:50
【问题描述】:
我正在为 Flask 中使用 flask_sqlalchemy 扩展编写的 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
`
【问题讨论】:
-
您提到了
create_all的问题,但没有添加它是如何调用的。我想它是在“create_app”中调用的,你能把这个函数添加到你的问题中让我们看看吗? -
db.create_all()确实在上面的setUp()方法中被调用,但您的问题让我再次查看主包中的create_app()。事实证明,它也调用了db.create_all(),正如您所猜测的那样。我已将其添加到问题中。 -
... 但 AFAIK
create_all()应该是幂等的。 -
有一个错字。我一直对
create_app(不是create_all)功能感兴趣。如果您的models.py导入一个数据库,或在其内部创建实例,您应该尝试将create_app()中的行更改为from .models import User,Player,Game,Match,Team,Post, db as models_db和models_db.create_all(),这样您将使用models.py中的数据库创建表 -
你成功了!问题在于
app和db的初始化顺序。我从基础包中导入的db(并调用create_all())实际上并不是绑定到模型的那个。因此create_all()什么也没创造。
标签: python unit-testing flask flask-sqlalchemy