代码之家  ›  专栏  ›  技术社区  ›  Subhayan Bhattacharya

如何使用pytest检查函数返回的假值

  •  1
  • Subhayan Bhattacharya  · 技术社区  · 6 年前

    我有下面的python函数代码:

    class ValidateHotelStars(AbsValidator):
        @staticmethod
        def validate(stars):
            try:
                star = int(stars)
                if star < 0 or star > 5:
                    return False
                else:
                    return True
            except ValueError:
                return False
    

    现在我试图使用pytest为这个函数编写一个单元测试:

    def test_star_value_less_than_zero():
        invalid_stars = [-5, 4, "Five"]
        assert not all(list(map(ValidateHotelStars.validate, invalid_stars)))
    

    现在通过以下输出:

    (venv) C:\Users\SUSUBHAT.ORADEV\PycharmProjects\hoteldatareader>python -m pytest
    ============================= test session starts =============================
    platform win32 -- Python 3.6.5, pytest-3.9.1, py-1.7.0, pluggy-0.8.0
    rootdir: C:\Users\SUSUBHAT.ORADEV\PycharmProjects\hoteldatareader, inifile:
    collected 1 item
    
    hoteldatareader\tests\test_validators.py .                               [100%]
    
    ========================== 1 passed in 0.31 seconds ===========================
    

    从python repl运行时,理想情况下应该会失败:

    >>> from hoteldatareader.fieldvalidators.validate_hotel_stars import ValidateHotelStars
    >>> invalid_stars = [-5, 4, "Five"]
    >>> list(map(ValidateHotelStars.validate, invalid_stars))
    [False, True, False]
    

    所以不是所有的都是假的。

    我认为我的测试语法不正确。

    有人能在这里纠正我吗?

    非常感谢

    4 回复  |  直到 6 年前
        1
  •  1
  •   Stephen Rauch Afsar Ali    6 年前

    如果要检查所有错误,则需要:

    not any(...)
    

    测试代码:

    assert not any([False, True, False])
    

    结果:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AssertionError
    
        2
  •  1
  •   hoefling    6 年前

    虽然答案确实提供了一个关于如何测试只包含 True 价值观,它们都忽略了重要的东西:

    基本上,你在一个里面做三个测试。这种方法有很多缺点-如果 ValidateHotelStars.validate 在星列表中间引发未处理的异常?测试将失败,剩下的星星将不会被检查。假设 assert not any(...) 失败-你能说哪一个明星论点是失败的原因吗?你得到的只是 AssertionError: False is not true ,但不让您了解错误的确切来源。

    因为你已经使用 pytest ,为什么不使用它的强大功能之一?参数化测试:

    import pytest
    
    @pytest.mark.parametrize('invalid_star', [-5, 4, "Five"])
    def test_invalid_star_is_not_validated(invalid_star):
        assert not ValidateHotelStars.validate(invalid_star)
    

    运行测试将产生:

    $ pytest -v
    ================================== test session starts ===================================
    platform darwin -- Python 3.6.6, pytest-3.9.1, py-1.5.4, pluggy-0.7.1
    cachedir: .pytest_cache
    rootdir: /Users/hoefling/projects/private/stackoverflow, inifile:
    collected 3 items
    
    test_spam.py::test_invalid_star_is_not_validated[-5] PASSED                        [ 33%]
    test_spam.py::test_invalid_star_is_not_validated[4] FAILED                         [ 66%]
    test_spam.py::test_invalid_star_is_not_validated[Five] PASSED                      [100%]
    
    ======================================== FAILURES ========================================
    _________________________ test_invalid_star_is_not_validated[4] __________________________
    
    invalid_star = 4
    
        @pytest.mark.parametrize('invalid_star', [-5, 4, "Five"])
        def test_invalid_star_is_not_validated(invalid_star):
    >       assert not ValidateHotelStars.validate(invalid_star)
    E       assert not True
    E        +  where True = <function ValidateHotelStars.validate at 0x1057936a8>(4)
    E        +    where <function ValidateHotelStars.validate at 0x1057936a8> = ValidateHotelStars.validate
    
    test_spam.py:19: AssertionError
    =========================== 1 failed, 2 passed in 0.12 seconds ===========================
    

    我只需要写一个测试,但是由于参数化, 脓包 将运行三次,每次使用不同的 invalid_star 争论。现在,尽管 4 测试失败,它仍将继续执行 "Five" . 在测试运行完成后,您可以立即看到哪些确切参数未通过哪些测试。通过在单个测试中循环参数列表,您将无法获得此级别的详细信息。

        3
  •  -1
  •   nikhilesh_koshti    6 年前

    使用以下检查

       list1 = [False, True, False] 
       bool(False in list1)
    
        4
  •  -1
  •   SilentGuy    6 年前

    你不需要 not 在你的断言中:

    def test_star_value_less_than_zero():
    invalid_stars = [-5, 4, "Five"]
    assert all(list(map(ValidateHotelStars.validate, invalid_stars)))
    

    all() 对所有元素执行和操作 any() 执行或操作。更多细节: https://stackoverflow.com/a/19389957/