Как запустить все тесты PyTest, даже если некоторые из них не работают?

Я ищу способ запускать все мои модульные тесты в PyTest, даже если некоторые из них терпят неудачу. Я знаю, что должен быть простой способ сделать это. Я проверил опции CLi и просмотрел этот сайт для похожих вопросов/ответов, но ничего не видел. Извините, если на это уже был дан ответ.

Например, рассмотрим следующий фрагмент кода, а вместе с ним и код PyTest:

def parrot(i):
    return i

def test_parrot():
    assert parrot(0) == 0
    assert parrot(1) == 1
    assert parrot(2) == 1
    assert parrot(2) == 2

По умолчанию выполнение останавливается при первом сбое:

$ python -m pytest fail_me.py 
=================== test session starts ===================
platform linux2 -- Python 2.7.10, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
rootdir: /home/npsrt/Documents/repo/codewars, inifile: 
collected 1 items 

fail_me.py F

=================== FAILURES ===================
___________________ test_parrot ___________________

    def test_parrot():
        assert parrot(0) == 0
        assert parrot(1) == 1
>       assert parrot(2) == 1
E       assert 2 == 1
E        +  where 2 = parrot(2)

fail_me.py:7: AssertionError
=================== 1 failed in 0.05 seconds ===================

Мне бы хотелось, чтобы код продолжал выполняться даже после того, как PyTest обнаруживает первый сбой.

Ответ 1

Все тесты прошли. Вы только написали один тест, и этот тест прошел!

Если вы хотите нефатальные утверждения, где тест будет продолжаться, если утверждение не выполняется (например, макросы Google Test EXPECT), попробуйте pytest-expect, который обеспечивает эту функциональность. Здесь пример их сайта дает:

def test_func(expect):
    expect('a' == 'b')
    expect(1 != 1)
    a = 1
    b = 2
    expect(a == b, 'a:%s b:%s' % (a,b))

Вы можете видеть, что ожидаемые отказы не останавливают тест, и все неудачные ожидания сообщаются:

$ python -m pytest test_expect.py
================ test session starts =================
platform darwin -- Python 2.7.9 -- py-1.4.26 -- pytest-2.7.0
rootdir: /Users/okken/example, inifile: 
plugins: expect
collected 1 items 

test_expect.py F

====================== FAILURES ======================
_____________________ test_func ______________________
>    expect('a' == 'b')
test_expect.py:2
--------
>    expect(1 != 1)
test_expect.py:3
--------
>    expect(a == b, 'a:%s b:%s' % (a,b))
a:1 b:2
test_expect.py:6
--------
Failed Expectations:3
============== 1 failed in 0.01 seconds ==============

Ответ 2

Как уже упоминалось, вы идеально пишете несколько тестов и имеете только одно утверждение в каждом (это не жесткий предел, а хорошая рекомендация).

Декоратор @pytest.mark.parametrize делает это легко:

import pytest

def parrot(i):
    return i

@pytest.mark.parametrize('inp, expected', [(0, 0), (1, 1), (2, 1), (2, 2)])
def test_parrot(inp, expected):
    assert parrot(inp) == expected

При запуске с -v:

parrot.py::test_parrot[0-0] PASSED
parrot.py::test_parrot[1-1] PASSED
parrot.py::test_parrot[2-1] FAILED
parrot.py::test_parrot[2-2] PASSED

=================================== FAILURES ===================================
_______________________________ test_parrot[2-1] _______________________________

inp = 2, expected = 1

    @pytest.mark.parametrize('inp, expected', [(0, 0), (1, 1), (2, 1), (2, 2)])
    def test_parrot(inp, expected):
>       assert parrot(inp) == expected
E       assert 2 == 1
E        +  where 2 = parrot(2)

parrot.py:8: AssertionError
====================== 1 failed, 3 passed in 0.01 seconds ======================

Ответ 3

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

Ответ 4

Я добился этого, добавив команду -v. Большое спасибо @the-compiler

Ответ 5

Плагин pytest pytest-check - это переписывание Pytest-Expect (которое было рекомендовано здесь ранее, но устарело). Это позволит вам сделать "мягкое" утверждение следующим образом:

Пример из репозитория GitHub:

import pytest_check as check

def test_example():
    a = 1
    b = 2
    c = [2, 4, 6]
    check.greater(a, b)
    check.less_equal(b, a)
    check.is_in(a, c, "Is 1 in the list")
    check.is_not_in(b, c, "make sure 2 isn't in list")