2017-06-12 9 views
0

フラスコで書かれたREST APIの単体テストをflask_sqlalchemy拡張で書いています。いくつかのモデルクラスがあるので、私はTestCaseサブクラスを作成して、テストデータベースの標準のsetUp/cleanUpを実行しました。すべてのテストクラスはこれを継承しています。 1つのクラスで複数のテストを実行すると、self.db.session.commit()(ユーザテーブルにエントリを追加しようとしています)で2番目のsetUp()が失敗するのは、self.db.create_all()が黙って失敗したためですテーブルを作成します。ここ は、テストパッケージの__init__.pyで、私のベーステストクラスである:flask_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 

誰もがここで間違っているものを私にしてください教えてください。

EDIT: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'に問題があることを述べたが、それが呼び出される方法を追加していない:あなたはmodels.pyからdbを使用していることを修正することができます。私はそれが 'create_app 'で呼び出されたと思います。私たちが見るためにあなたの質問にこの関数を追加できますか? – Fian

+0

上記の 'setUp()'メソッドで 'db.create_all()'が呼び出されますが、あなたの質問はメインパッケージの 'create_app()'をもう一度見てもらえました。あなたが推測したように、 'db.create_all()'も呼び出すことが判明しました。私は質問にそれを加えました。 – ProfCalculus

+0

...しかし、AFAIK 'create_all()'は冪等でなければなりません。 – ProfCalculus

答えて

0

create_all()は、モデルでモジュールをインポートすることで検出されるメタデータに適用されます。あなたのケースでは、モデルのメタデータはmodels.pyからdbにバインドされますが、chessleague/__init__.dbからcreate_app()create_all()を呼び出しています。これはSqlAlchemyとは異なるオブジェクトです。

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) そして、モジュールレベルで(右SQLACHEMY_DATABASE_URL含む)App.configファイルに create_app(config_name)

  • 負荷右設定をアプリケーションインスタンスを作成
  • モデルをインポートクラスとこのインポートはmodels.pyにモジュールレベルでシンボルdbを作成models.py

から(model_dbなど)db、FOLこれですべてが適切に設定され

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

:モデルクラスの定義によってlowedシンボル「db」はどこでもmodels.pyからインポートすることができ、私は私のテストsetUp()から首尾db.create_all()を呼び出すことができます。

@Fian、私はあなたのクレジットを与えることができるように答えとしてあなたのソリューションを投稿できますか?

関連する問題