2017-06-12 15 views
0

我正在爲使用flask_sqlalchemy擴展名寫入Flask的REST API編寫單元測試。因爲我有很多模型類,我寫了一個TestCase子類來完成測試數據庫的標準setUp/cleanUp。我所有的測試類都從此繼承。每個測試單獨運行都會成功,但是當我在一個類中運行多個測試時,第二個setUp()在self.db.session.commit()(我試圖向用戶表中添加一個條目)上失敗,因爲self.db.create_all()(無提示)失敗創建任何表格。 這裏是我的基礎測試類,在測試封裝的__init__.pyflask_sqlalchemy create_all()在單元測試中無提示失敗

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

你提到用'create_all'一個問題,但還沒有添加它是如何調用。我想這是在'create_app'中調用的,你可以在你的問題中添加這個函數供我們看看嗎? – Fian

+0

'db.create_all()'在上面的'setUp()'方法中被調用,但是你的問題讓我再次看到主包中的'create_app()'。事實證明,它也調用'db.create_all()',正如你猜測的那樣。我已將它添加到問題中。 – ProfCalculus

+0

...但AFAIK'create_all()'應該是冪等的。 – ProfCalculus

回答

0

create_all()適用於元數據,這是通過導入帶模型的模塊發現的。在你的情況下,模型的元數據綁定到從models.pydb,但你打電話給create_all()chessleague/__init__.dbcreate_app()函數,這是SqlAlchemy的不同對象。您可以修復使用dbmodels.py

from .models import User,Player,Game,Match,Team,Post, db as models_db 
models_db.create_all() 
0

這裏是爲我工作的初始化序列 - 評論歡迎!

我的測試類setUp()從主應用程序包中調用create_app(config_name)。 主要的應用程序包(__init__.py)在模塊級創建應用程序實例,即app=Flask(my_app_package_name) 然後我的函數 create_app(config_name)

  • 負載權配置到的app.config(包括右SQLACHEMY_DATABASE_URL)
  • 導入模型從models.py

此導入在models.py模塊級別創建符號db,FOL類和db(如model_db)通過模型類定義lowed:

# models.py 
    from . import app 
    db = SQLAlchemy(app) 
    ... 
    class User(db.Model) 
    ... 
    etc 

現在一切都設置正確:符號「DB」,可以從任何地方models.py進口的,我可以從我的測試setUp()成功調用db.create_all()

@Fian,你可以發佈你的解答作爲答案,所以我可以給你信用?