2014-10-04 73 views
1

我正在通過模仿The Flask Mega-Tutorial來編寫Web應用程序。Flask-SQLALchemy單元測試問題

正如我試圖添加一些單元測試用例到我的代碼。我發現教程中的測試用例有許多重複的代碼。

這裏是代碼段:

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

def test_make_unique_nickname(self): 
    u = User(nickname='john', email='[email protected]') 
    db.session.add(u) 
    db.session.commit() 
    ... 

的問題是,我想測試一個新的情況下,我每次都要重複這個過程:

u = User(nickname='john', email='[email protected]') 
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='[email protected]') # 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='[email protected]')_init_database()

def _init_database(): 
    u = User(nickname='john', email='[email protected]') 
    db.session.add(u) 
    db.session.commit(u) 

現在每一件事情是好的。

我真的不知道爲什麼!你可以幫幫我嗎?

回答

0

User實例是由ORM控制的對象,所以將其作爲全局變量並不是一個好主意。該對象不僅包含您的數據,還包含數據庫信息。通過使其成爲全局數據庫,您首先在數據庫中使用它進行第一次測試,然後在數據庫中使用它進行第二次測試。

一個更好的方法是創建一個新的User實例爲每個測試,並在setUp()方法返回它:

def _init_database(): 
    u = User(nickname='john', email='[email protected]') 
    db.session.add(u) 
    db.session.commit() 
    return u 

然後你就可以該用戶連接到你的測試用例,並從你的測試訪問它。

+0

你的意思是我不應該使用全局變量。但是,如果我想使用多個用戶呢?那麼,我必須像這樣返回(u1,u2,u3)'?我只能想辦法解決它。只需製作所有這些用戶對象變量。但是,每次我想要使用用戶時,都必須使用像這樣的'self.u1',這有點難看。 – 2014-10-06 13:11:51

+1

我並沒有試圖向你傳達如何糟糕的全局變量,不好意思,如果它似乎這樣。全局變量有時是有用的,但在這種情況下是有問題的,因爲用戶模型有點神奇,因爲它們存儲由SQLAlchemy控制的數據庫元數據。我會在'TestCase'類中使'_init_database()'函數成爲一個方法,並將所有用戶存儲爲對象變量。然後創建一個'_get_users()'方法,返回你的三個用戶,並在測試開始時將其稱爲'u1,u2,u3 = self._get_users()',這樣就不必使用'self'。 u1'。 – Miguel 2014-10-06 16:43:32