Flask-SQLALchemy单元测试问题

时间:2014-10-04 10:20:40

标签: python flask flask-sqlalchemy python-unittest

我通过模仿The Flask Mega-Tutorial来撰写网络应用。

因为我试图在我的代码中添加一些单元测试用例。我发现教程中的测试用例有很多重复的代码。

以下是代码段:

def test_avatar(self):
    u = User(nickname='john', email='john@example.com')
    avatar = u.avatar(128)
    expected = 'http://www.gravatar.com/avatar/d4c74594d841139328695756648b6bd6'
    ...

def test_make_unique_nickname(self):
    u = User(nickname='john', email='john@example.com')
    db.session.add(u)
    db.session.commit()
    ...

问题在于每次我想测试一个新案例时我都要重复这个过程:

u = User(nickname='john', email='john@example.com')
db.session.add(u)
db.session.commit()

所以,我把这个过程移开了,就像这样:

import unittest

from config import basedir
from app import app, db
from app.models import User

u = User(nickname='john', email='john@example.com')  # I put this out because some cases may want to use this stuff.

def _init_database():
    db.session.add(u)
    db.session.commit(u)

class TestCase(unittest.TestCase):
    def setUp(self):
        app.config['TESTING'] = True
        app.config['WTF_CSRF_ENABLED'] = False
        app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:')
        self.app = app.test_client()
        db.create_all()
        _init_database()  # init database every time

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

    def test_case_1(self):
        self.assertTrue(User.query.count() == 1)  # case 1

    def test_case_2(self):
        self.assertTrue(User.query.count() == 1)  # case 1

if __name__ == '__main__':
    unittest.main()

如您所见,两个测试用例是相同的。但是,只能通过一个案例。另一个将失败

但是如果我将u = User(nickname='john', email='john@example.com')移到_init_database()

def _init_database():
    u = User(nickname='john', email='john@example.com')
    db.session.add(u)
    db.session.commit(u)

现在一切都很好。

我真的不知道为什么!你能帮帮我吗?

1 个答案:

答案 0 :(得分:0)

User实例是由ORM控制的对象,因此将其作为全局变量不是一个好主意。该对象不仅包含您的数据,还包括数据库信息。通过使其成为全局,您首先在数据库中使用它进行第一次测试,然后在数据库上进行第二次测试。

更好的方法是为每个测试创建一个新的User实例,并使用setUp()方法返回它:

def _init_database():
    u = User(nickname='john', email='john@example.com')
    db.session.add(u)
    db.session.commit()
    return u

然后,您可以将此用户附加到测试用例并从测试中访问它。

相关问题