Тестовая колба sql alchemy
У меня есть рабочее веб-приложение на Flask с SqlAlchemy для модерации новостей, у него есть некоторые методы api для обработки запросов модерации, таких как одобрение, запрет выбранных новостей, их список и т.д. Я хочу написать модульные тесты для этого методы, и я заставил их работать, но я не понимаю, как реализовать выполнение всех запросов, которые я делаю из тестовых случаев, в одном сеансе db, чтобы я мог удалить все изменения в базе данных. Или есть еще один очиститель или правильный способ сделать это?
Я выяснил, что, возможно, все, что мне нужно, это "scoped_session" в SqlAlchemy, но все мои попытки выполнить его не сработали. Если это правильный путь, пожалуйста, скажите мне, где использовать эти строки кода (в настройках или в методе set_up тестового примера).
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
session_factory = sessionmaker()
Session = scoped_session(session_factory)
Ответы
Ответ 1
Я предлагаю вам использовать расширение Flask-Testing. Это одобренное расширение, которое позволяет выполнять тестирование устройства по вашему желанию. Он также имеет специальный раздел для SQLAlchemy.
Тестирование с помощью SQLAlchemy
Это касается нескольких пунктов, если вы используете Flask-Testing с SQLAlchemy. Предполагается, что вы используете расширение Flask-SQLAlchemy, но если нет, то примеры не должны быть слишком сложными для адаптации к вашей конкретной настройке.
Во-первых, убедитесь, что вы установили URI базы данных в нечто иное, чем ваша производственная база данных! Во-вторых, обычно рекомендуется создавать и отбрасывать таблицы с каждым тестовым прогоном, чтобы обеспечить чистые тесты: "
from flask.ext.testing import TestCase
from myapp import create_app, db
class MyTest(TestCase):
SQLALCHEMY_DATABASE_URI = "sqlite://"
TESTING = True
def create_app(self):
# pass in test configuration
return create_app(self)
def setUp(self):
db.create_all()
def tearDown(self):
db.session.remove()
db.drop_all()
Ответ 2
Так я недавно тестировал модульные тесты. Я предполагаю, что вы используете SQLAlchemy, что используете классы моделей. Я также предполагаю, что все ваши таблицы определены как классы модели SQLAlchemy.
from flask import Flask
import unittest
from app import db
from app.models import Log
from constants import test_logs
class appDBTests(unittest.TestCase):
def setUp(self):
"""
Creates a new database for the unit test to use
"""
self.app = Flask(__name__)
db.init_app(self.app)
with self.app.app_context():
db.create_all()
self.populate_db() # Your function that adds test data.
def tearDown(self):
"""
Ensures that the database is emptied for next unit test
"""
self.app = Flask(__name__)
db.init_app(self.app)
with self.app.app_context():
db.drop_all()
Поскольку вы используете тот же БД, который настроен как приложение, это позволяет вам создавать и уничтожать тестовую базу данных с каждым запущенным unit test.
Ответ 3
Что касается ответа codegeek, использующего Flask-Testing, мне трудно понять, что делает createapp()
. Flask-SqlAlchemy Введение в контексты предоставило мне некоторый указатель на то, как динамически связывать объект SQLAlchemy с вашим приложением. В этом случае привязка к тестовому приложению.
В основном:
- Создайте объект sqlalchemy в колбе, но не передайте объект приложения
- В функции create_app создайте тестовое приложение и динамически привяжите SQLAlchemy.
myapp.py:
# don't pass in the app object yet
db = SQLAlchemy()
def create_test_app():
app = Flask(__name__)
app.config['TESTING'] = True
app.config["SQLALCHEMY_DATABASE_URI"] = "xxxxxxtestdatabasexxx"
# Dynamically bind SQLAlchemy to application
db.init_app(app)
app.app_context().push() # this does the binding
return app
# you can create another app context here, say for production
def create_production_app():
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "xxxxxxproductionxxxx"
# Dynamically bind SQLAlchemy to application
db.init_app(app)
app.app_context().push()
return app
Затем вы можете следовать решению codegeek, как описано в документации по фляжке.
from flask.ext.testing import TestCase
from myapp import create_app, db
class MyTest(TestCase):
# I removed some config passing here
def create_app(self):
return create_test_app()
def setUp(self):
db.create_all()
def tearDown(self):
db.session.remove()
db.drop_all()
Самое приятное в этом решении заключается в том, что вы можете создавать разные приложения и динамически связывать объект SQLAlchemy с помощью функции. Каждое приложение может использоваться в разных целях. Например, один для производства и один для модульного теста. В случае для производства вы можете вызвать create_production_application() в своем приложении фляги верхнего уровня.