1

我正在制作一个简单的 Flask Web 应用程序来玩,我想使用鼻子测试。我被困在如何使用 Flask-SQLAlchemy 连接到我的测试文件中的内存测试数据库。当我运行我的测试时 - Flask 连接到我的主应用程序的数据库,更重要的是,每次测试后都无法清理它。这是我的测试代码:

import nose
from nose.tools import *
from pyquery import PyQuery as pq
from flask.ext.sqlalchemy import SQLAlchemy

from app import site, db

from app.models import Post


class TestApp(object):
    def setUp(self):
        site.config['TESTING'] = True
        site.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
        self.test_app = site.test_client()
        db.create_all()

    def tearDown(self):
        # db.session.remove()
        db.drop_all()

    def test_posts_index(self):
        db.session.add(Post('title', 'body'))
        db.session.add(Post('title2', 'body'))

        db.session.commit() # this writes to production db ie app.db file 
                            # instead of sqlite://
        rv = self.test_app.get('/posts')
        d = pq(rv.data)
        print len(d('h1'))
        assert len(d('h1')) == 2

这是我的app/__init__.py代码:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

from app import config

site = Flask(__name__)

site.config['SQLALCHEMY_DATABASE_URI'] = config.db_uri
db = SQLAlchemy(site)
site.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'


from app import db_setup
db_setup.create_db()

import controllers, models

函数中的 db_setup.create_db()app/__init__.py看起来就像这样:

from app import db
from app.models import Post
def create_db():
    db.create_all()
    db.session.commit()

我尝试在测试文件中实例化应用程序和数据库,但是我的模型不起作用,因为它们from app import db,其中 db 是生产数据库对象。我还在测试用例中撒了一些打印语句,比如print db它们打印出类似的东西<SQLAlchemy engine sqlite://>,但它仍然会写入生产数据库。

我非常感谢有关如何解决此问题的任何提示。谢谢!

4

3 回答 3

2

你为什么不使用一些关于环境的东西来确定应用程序是在测试模式还是实时模式下启动?

if 'testing' in os.environ:
    site.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://'
else:
    site.config['SQLALCHEMY_DATABASE_URI'] = config.db_uri

有很多方法可以给这只特殊的猫剥皮。如果您不喜欢if让代码块乱扔垃圾的想法,您可以根据应用程序是在测试模式还是实时模式下启动,从一个完全独立的模块中导入您的设置。

于 2013-10-31T08:46:10.177 回答
0

我能够找出问题所在,这与我在__init__.py文件中启动与数据库的连接有关,这是我不应该做的。

罪魁祸首是

from app import db_setup
db_setup.create_db()

代码。本质上,每次我做一个from app import db,我认为它app会被实例化,它调用db_setup.create_db(),它使用生产配置创建表。从那里开始,尽管尝试将烧瓶应用程序配置设置SQLALCHEMY_DATABASE_URI为内存数据库,但 db 对象将继续使用__init__.py文件中实例化的数据库。

我所要做的就是create_all()从当时我的意志运行的环境中调用。希望这可以帮助任何可能遇到类似情况的人。

于 2013-11-01T07:05:32.983 回答
0

我遇到了同样的问题,但我根本没有在我的init .py 文件中使用 db.create_all() 类型语句。

最后,我可以解决这个问题的唯一方法是使用

def setUp(self):
    with app.app_context():
                db.create_all() 
于 2016-07-28T10:09:17.677 回答