【问题标题】:Unit testing for ClassMethod of a model in Flask在 Flask 中对模型的 ClassMethod 进行单元测试
【发布时间】:2020-03-16 14:28:47
【问题描述】:

我有两个数据库:一个是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 数据库?

【问题讨论】:

  • 您展示的代码首先如何了解任何数据库?大概这是以某种方式融入Book

标签: python python-3.x flask flask-sqlalchemy


【解决方案1】:

您必须为您的测试功能提供上下文。最好的方法是使用工厂。如何做到这一点的一个很好的描述是:http://alanpryorjr.com/2019-05-20-flask-api-example/。如果你有一个应用程序和一个 db 夹具,你可以在你的测试函数中使用它:

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)

是的,唯一的区别是函数调用中的db。我不能说为什么你的其他测试有效。我最好的猜测是您的失败测试是在测试上下文被破坏后执行的。最好每次都明确说明您的应用上下文。

如果一切都失败了(并且您可以通过正确的数据库连接访问您的应用程序),您可以手动推送上下文:

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/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    • 2017-08-11
    • 2014-05-17
    相关资源
    最近更新 更多