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

时间:2018-10-23 06:52:17

标签: python pytest

我有以下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 个答案:

答案 0 :(得分:1)

如果要检查所有False,则需要:

not any(...)

测试代码:

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

结果:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError

答案 1 :(得分:1)

尽管答案确实可以帮助您了解如何测试仅包含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 ===========================

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

答案 2 :(得分:-1)

使用以下检查

   list1 = [False, True, False] 
   bool(False in list1)

答案 3 :(得分:-1)

您的断言中不需要not

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

all()对所有元素执行AND操作,而any()执行OR操作。更多详细信息:https://stackoverflow.com/a/19389957/