Как утверждать, что все утверждения провалились в python - PullRequest
0 голосов
/ 24 мая 2019

Я пытаюсь написать примеры того, как НЕ писать тесты в pytest.Для этого я хотел бы иметь возможность каким-либо образом модифицировать тестовые функции, чтобы они не выполнялись, если проходило какое-либо утверждение.Это легко с одним утверждением, используя декоратор:

def faulty_test(test_fn):
    def new_test_fn():
        try:
            test_fn()
        except AssertionError:
            pass
        else:
            raise AssertionError

    return new_test_fn

@faulty_test
def test_sth():
    assert 1 == 2

, но я хотел бы сделать это для функции с любым количеством утверждений.Тест должен провалиться, если какое-либо из утверждений прошло успешно.Это не должен быть декоратор

Ответы [ 4 ]

0 голосов
/ 24 мая 2019

Вероятно, вы должны обработать это в коде функции, используя _debug или другой (скрытый) аргумент. Тогда вы можете использовать декоратор на этом. Что бы я сделал:

def deco(inF):
    def wrapper(*args, **kwargs):
        kwargs['_debug'] = True
        output = inF(*args, **kwargs)
        #print(output)
        for i, _ in enumerate(zip(*output)):
            condition, msg = _
            # this will raise the first passed assert. Otherwise loop again to print all "passed" assertions, then raise
            if not condition:
                raise AssertionError('Condition {} succeded: {} is False'.format(1 + i, msg))
        return output
    return wrapper

@deco
def f(i, j , k, _debug=False):
    cond1, msg1 = i == 1, 'i is not 1'
    cond2, msg2 = j == 2, 'j is not 2'
    cond3, msg3 = k == 3, 'k is not 3'
    assert cond1 or _debug, msg1
    assert cond2 or _debug, msg2
    assert cond3 or _debug, msg3
    if _debug:
        return (cond1, cond2, cond3), (msg1, msg2, msg3) 
    return i + j + k

f(1,1,5)
>>AssertionError: Condition 2 succeded: j is not 2 is False
0 голосов
/ 24 мая 2019

Возможно, вам следует подумать об этом следующим образом: в момент исключения выполнение покидает блок try и входит в блок исключений.Вы не можете, по крайней мере, любым простым способом, который я могу придумать, повторно войти в блок try из блока исключений.

И, возможно, я неправильно понимаю вопрос, но вы не могли бы просто заменить свои утвержденияс обратным из этих утверждений?Если вы хотите утверждать, что вещь является ложной, вы можете:

assert not (1 == 2)

Если по какой-то причине вы сталкиваетесь с ситуацией, когда вы предполагаете, что данные функции по какой-то причине всегда будут давать сбойутверждений, и вы не можете изменить это, кажется, нет никакого способа обеспечить выполнение всех утверждений, поскольку план утверждений заключается в намеренном прерывании сразу при сбое.

0 голосов
/ 24 мая 2019

Если вы «нумеруете» утверждения, то обнаружение утверждения со значением больше 0 подразумевает предыдущие пройденные утверждения.

def faulty_test(test_fn):
    def new_test_fn():
        try:
            test_fn()
        except AssertionError as exc:
            if exc.args[0] > 0:
                # Assertions 0 through exc.args[0]-1 all passed
                raise AssertionError
        else:
            raise AssertionError

    return new_test_fn

@faulty_test
def test_sth():
    assert 1 == 2, 0
    assert 2 == 3, 1
    assert 3 == 4, 2
0 голосов
/ 24 мая 2019

Я думаю, это не обязательно должно быть несколько утверждений.Вы можете написать:

assert a == b or c == d or # so on

Любое условие True будет означать, что утверждение пройдет.

...