优化 Flask 客户端测试

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 63w+ 字,讲解图 2808+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2200+ 小伙伴加入学习 ,欢迎点击围观

在编写 Python 集成测试时,将诸如数据库访问之类的慢速代码放在 setUpClass 方法中很有用,这样它们只对整个 unittest.TestCase 执行一次。最近,在为 Flask API 编写集成测试时,我想为 TestCase 进行一次 API 调用,但有许多测试断言 JSON 响应的各个部分。这有点尴尬,因为 Flask 测试客户端 仅使用 TestCase 的实例进行实例化。

我最终在自定义基 TestCase 子类的全局变量中缓存了 API 响应。


 from functools import partial
from unittest import TestCase

_cached_api_responses = {}

class MyTestCase(TestCase):

def set_cached_json_data(self, cache_key, test_callable):
    """ We want to separate out tests for various keys in the json response 
        of an API call, but we only want to make an API once for performance
        reasons. Solution is to cache this between test calls, which is made
        more difficult due to test classes being re-instantiated between
        individual tests. Cache in a global. """
    global _cached_api_responses
    response_json = _cached_api_responses.get(cache_key)
    if not response_json:
        response = test_callable()
        response_json = response.json
        _cached_api_responses[cache_key] = response_json
    return response_json

class SpecificTestCase(MyTestCase):

@classmethod
def setUpClass(cls):
    # do a bunch of database record creation
    cls.db_object = ...

def setUp(self):
    # cache a flask API response 
    test_callable = partial(self.get, '/my-url')
    self.response_json = self.set_cached_json_data('my-url', test_callable)

def test_foo(self):
    foo = self.response_json['foo']
    self.assertEquals(len(foo), 1)

def test_bar(self):
    bar = self.response_json['foo']['bar']
    self.assertEquals(len(bar), 10)

使用 partial 只是为了更容易将任何测试客户端调用传递到缓存函数中。

它缓存 JSON 而不是 SQLAlchemy 数据库对象的集合这一事实很重要,如果您尝试这样做,您会发现 SQLAlchemy 会抛出有关对象不再与测试中的会话绑定的异常。

我目前在 NerdWallet 工作,这是一家位于旧金山的初创公司,致力于让生活中的所有财务决策变得清晰。我们正在 疯狂招聘 。在 Twitter 上联系我,我很想谈谈。

相关文章