代码之家  ›  专栏  ›  技术社区  ›  damd

单元测试Django视图中如何避免组合爆炸

  •  2
  • damd  · 技术社区  · 6 年前

    我有一个相当复杂的Django(Rest框架)视图,它更新数据库中的一个对象。

    为了更新对象,需要满足一些条件(这些不是真实的条件,但它们是相似的):

    1. 用户名必须以 admin
    2. is_moon_phase_ok 需要返回 True

    when not logged in, return 401
    when not logged in, return {"fail": "login"}
    when not logged in, don't touch database
    when not logged in, don't check moon phase
    when username is not admin_*, return 401
    when username is not admin_*, return {"fail": "username"}
    when username is not admin_*, don't touch database
    when username is not admin_*, don't check moon phase
    when invalid data, return 400
    when invalid data, return {"fail": "data"}
    when invalid data, don't touch database
    when invalid data, don't check moon phase
    when logged in, return 200
    when logged in, return updated data
    when logged in, check moon phase
    when logged in, update database
    

    试想一下,如果需求发生了变化,而它们确实发生了变化,那么忽略测试用例、确保它们仍然适用、根据新需求更新它们等等会是多么痛苦。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Gabriel Muj    6 年前

    对我来说,这听起来很像参数化测试,pytest支持这一点,基本上你可以编写一个测试,并提供输入参数,以及预期的。 编写泛型测试可能会引入一些逻辑(正如您在我的示例中看到的),但在我看来,您可以接受这种逻辑

    @pytest.mark.parametrize('is_admin,expected_status_code,expected_error', [
        (True, 200, {}),
        (False, 401, {"fail": "login"})
    ])
    def test_sample(is_admin, expected_status_code, expected_data):
        # do your setup
        if is_admin:
            user =  create_super_user()
        else:
            user =  normal_user()
    
        # do your request
        response = client.get('something')
    
        # make assertion on response
        assert response.status_code == expected_status_code
        assert response.data == expected_data
    

    您还可以有多个参数层,例如:

    @pytest.mark.parametrize('is_admin', [
        True,
        False
    ])
    @pytest.mark.parametrize('some_condition,expected_status_code,expected_error', [
        (True, 200, {}),
        (False, 401, {"fail": "login"})
    ])
    

    这将执行对isu admin(True/False)和其他参数的每个组合的测试,不错吧?

    在此处查看文档 pytest parametrize tests

    如果不使用pytest,请检查执行类似操作的库 Parameterized testing with any Python test framework