运行测试时,它可以成功连接到数据库,但是不会创建表。我认为当我使用flask-sqlalchemy时,也许有另一种创建表的方法,但是我找不到解决方法。
这是app.py
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__, template_folder='templates')
app.wsgi_app = ProxyFix(app.wsgi_app)
app.config.from_object(config_name)
app.register_blueprint(api)
db.init_app(app)
@app.route('/ping')
def health_check():
return jsonify(dict(ok='ok'))
@app.errorhandler(404)
def ignore_error(err):
return jsonify()
app.add_url_rule('/urls', view_func=Shorty.as_view('urls'))
return app
这是run.py
environment = environ['TINY_ENV']
config = config_by_name[environment]
app = create_app(config)
if __name__ == '__main__':
app.run()
这是config.py
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
"""
set Flask configuration vars
"""
# General config
DEBUG = True
TESTING = False
# Database
SECRET_KEY = os.environ.get('SECRET_KEY', 'my_precious_secret_key')
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root@localhost:3306/tiny'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SERVER_HOST = 'localhost'
SERVER_PORT = '5000'
class TestConfig(Config):
"""
config for test
"""
TESTING = True
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root@localhost:3306/test_tiny'
config_by_name = dict(
test=TestConfig,
local=Config
)
key = Config.SECRET_KEY
这是models.py
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class URLS(db.Model):
__tablename__ = 'urls'
id = db.Column(db.Integer, primary_key=True)
original_url = db.Column(db.String(400), nullable=False)
short_url = db.Column(db.String(200), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow()
这是测试配置设置。
db = SQLAlchemy()
@pytest.fixture(scope='session')
def app():
test_config = config_by_name['test']
app = create_app(test_config)
app.app_context().push()
return app
@pytest.fixture(scope='session')
def client(app):
return app.test_client()
@pytest.fixture(scope='session')
def init_db(app):
db.init_app(app)
db.create_all()
yield db
db.drop_all()
答案 0 :(得分:0)
以下可能是阻止您的代码多次运行和/或阻止您删除/创建表的问题。不管它能否解决您的问题,这都是人们可能不了解的,并且牢记在心非常重要。 :)
当您多次运行测试时,db.drop_all()
可能不会被调用(因为其中一个测试失败),因此,它可能无法在下次运行时创建表(因为它们已经存在)现有)。问题在于使用不带try: finally:
的上下文管理器。 (注意:每个使用yield
的灯具都是一个上下文管理器)。
from contextlib import contextmanager
def test_foo(db):
print('begin foo')
raise RuntimeError()
print('end foo')
@contextmanager
def get_db():
print('before')
yield 'DB object'
print('after')
此代码代表您的代码,但未使用pytest的功能。 Pytest正在或多或少地运行它
try:
with get_db(app) as db:
test_foo(db)
except Exception as e:
print('Test failed')
人们期望输出类似于:
before
begin_foo
after
Test failed
但我们只能得到
before
begin_foo
Test failed
当contextmanager处于活动状态(yield
已执行)时,我们的测试方法正在运行。如果在执行测试功能期间引发异常,则执行将停止,而不会在yield
语句之后运行任何代码。为防止这种情况,我们必须将fixture
/ contextmanager
包装在try: ... finally:
块中。不管发生了什么,finally总是被执行。
@contextmanager
def get_db():
print('before')
try:
yield 'DB object'
finally:
print('after')
yield
语句之后的代码现在按预期执行。
before
begin foo
after
Test failed
如果您想了解更多信息,请参见contextmanager docs中的相关部分:
在生成器产生的点上,嵌套在with语句中的块是 被执行。退出该块后,将恢复生成器。如果未处理 异常发生在块中,它在生成器内部重新升高 产生产量的地方。因此,您可以使用try ... except ... finally语句进行陷阱 错误(如果有),或确保进行一些清理。