Модульное тестирование для ClassMethod модели в Flask - PullRequest
0 голосов
/ 16 марта 2020

У меня есть две базы данных: одна master и для тестирования у меня есть другая база данных master_test

Чтобы получить общую цену из таблицы, которую я создал @classmethod в модели. Этот метод помогает мне получить сумму фильтрации цен по месяцам и годам. Вот метод класса:

@classmethod
def get_total_book_price(cls, id):

    query = Book.query.with_entities(
        func.sum(Book.price).label("price")
    ).filter(
        extract('year', Book.created_at) >= datetime.date.today().year,
        extract('month', Book.created_at) >= datetime.date.today().month
    ).filter(
        Book.id == id
    ).all()

    return query[0].price

Этот запрос работает хорошо. Но когда я запускаю это для теста, его база данных master не существует. Он должен найти базу данных master_test вместо базы данных master. Вот код теста:

def test_get_total_book_price(self):
    id = 1
    response = Book.get_total_book_price(id)
    if not response:
        self.assertEqual(response, False)
    self.assertEqual(response, True)

Он показывает ОШИБКУ:

 sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) FATAL:  database "master" 
 does not exist
 (Background on this error at: http://sqlalche.me/e/e3q8)
 ----------------------------------------------------------------------
 Ran 34 tests in 2.011s
 FAILED (errors=1)
 ERROR: Job failed: exit code 1

Некоторые другие тестовые примеры прекрасно работают с master_test. Но для этого теста, почему он ищет master базу данных?

1 Ответ

0 голосов
/ 18 марта 2020

Вы должны предоставить контекст для своей тестовой функции. Лучший способ сделать это с фабриками. Отличное описание, как это сделать: http://alanpryorjr.com/2019-05-20-flask-api-example/. Если у вас есть приложение и осветитель БД, вы можете просто использовать его в своей тестовой функции:

from test.fixtures import app, db

def test_get_total_book_price(self, db):
    id = 1
    response = Book.get_total_book_price(id)
    if not response:
        self.assertEqual(response, False)
    self.assertEqual(response, True)

Да, единственное отличие - дБ в вызове функции. Я не могу сказать, почему ваши другие тесты работают. Мое лучшее предположение состоит в том, что ваш неудачный тест выполняется после того, как контекст теста разрушен. Лучше будьте откровенны в отношении контекста вашего приложения каждый раз.

Если все остальное терпит неудачу (и у вас есть доступ к вашему приложению при правильном соединении с базой данных), вы могли бы вручную * * * * * * * * * * * * * 10 * *

from foo import app

def test_get_total_book_price(self, app):
    app.app_context().push()        
    id = 1
    response = Book.get_total_book_price(id)
    if not response:
        self.assertEqual(response, False)
    self.assertEqual(response, True)

Хочу подчеркнуть, что вы должны использовать фабрики для тестирования.

Ссылка: https://flask.palletsprojects.com/en/1.0.x/appcontext/

...