Приспособление уровня класса Pytest запускается для каждого метода, если в этом приспособлении есть исключение - PullRequest
0 голосов
/ 18 января 2019

Я пишу несколько тестов, используя pytest, для которого требуется переменная окружения для запуска функции теста.Поэтому я создал прибор, который будет проверять, существует ли переменная окружения, или выходить иначе.Ниже приведен мой код.

import os
import sys

import pytest

from ..factorial import fact


@pytest.fixture(scope='class')
def pre(request):
    print('************setting up************')

    pwd = os.environ.get('PASSWD', None)
    if pwd is not None:
        request.cls.pwd = pwd
    else:
        sys.exit('This test requires your password, '
                 'please run export PASSWD=<yourPassword>')


@pytest.mark.usefixtures('pre')
class TestFactorial:
    def test_postive(self):
        assert fact(5) == 120

    def test_false(self):
        assert fact(6) == 720

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

collected 2 items                                                                                                                                                                                                  

test_factorial.py ************setting up************
..

============================================================================================= 2 passed in 0.01 seconds ===

Теперь, когда переменная окруженияне установлен, весь прибор запускается дважды.Ниже приведен вывод

collected 2 items                                                                                                                                                                                                  

test_factorial.py ************setting up************
E************setting up************
E

====================================================================================================== ERRORS ======================================================================================================
___________________________________________________________________________________ ERROR at setup of TestFactorial.test_postive ___________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_postive>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            request.cls.pwd = pwd
        else:
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:17: SystemExit
____________________________________________________________________________________ ERROR at setup of TestFactorial.test_false ____________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_false>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            request.cls.pwd = pwd
        else:
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:17: SystemExit

Я ожидал, что будет сгенерировано исключение, и программа закроется, и она даже не достигнет класса TestFactorial.Но это показывает, что прибор фактически запускался дважды один раз для каждого метода тестирования внутри класса.

Это ожидаемое поведение или я что-то упустил, чтобы понять, как на самом деле работают приборы?

Если это действительнотогда как я могу добиться такого поведения, чтобы, если переменная среды не установлена, тесты не запускались?

Редактировать 1

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

import os
import sys
from random import randint   # edit

import pytest

from ..factorial import fact


@pytest.fixture(scope='class')
def pre(request):
    print('************setting up************')

    pwd = os.environ.get('PASSWD', None)
    if pwd is not None:
        print(randint(1, 100))    # edit
        request.cls.pwd = randint(1, 100)
    else:
        print(randint(1, 100))    # edit
        sys.exit('This test requires your password, '
                 'please run export PASSWD=<yourPassword>')

@pytest.mark.usefixtures('pre')
class TestFactorial:
    def test_postive(self):
        assert fact(5) == 120

    def test_false(self):
        assert fact(6) == 720

Вывод, когда установлена ​​переменная окружения

pytest -sq test_factorial.py
************setting up************
67
..
2 passed in 0.01 seconds

Таким образом, он запускается только один раз для класса.

Вывод, когда переменная окружения не установлена ​​

pytest -sq test_factorial.py
************setting up************
69
E************setting up************
82
E
====================================================================================================== ERRORS ======================================================================================================
___________________________________________________________________________________ ERROR at setup of TestFactorial.test_postive ___________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_postive>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            print(randint(1, 100))
            request.cls.pwd = randint(1, 100)
        else:
            print(randint(1, 100))
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:20: SystemExit
____________________________________________________________________________________ ERROR at setup of TestFactorial.test_false ____________________________________________________________________________________

request = <SubRequest 'pre' for <Function test_false>>

    @pytest.fixture(scope='class')
    def pre(request):
        print('************setting up************')

        pwd = os.environ.get('PASSWD', None)
        if pwd is not None:
            print(randint(1, 100))
            request.cls.pwd = randint(1, 100)
        else:
            print(randint(1, 100))
>           sys.exit('This test requires your password, '
                     'please run export PASSWD=<yourPassword>')
E           SystemExit: This test requires your password, please run export PASSWD=<yourPassword>

test_factorial.py:20: SystemExit
2 error in 0.03 seconds

Обратите внимание, что случайные числа, напечатанные в каждом случае, различны, так что это показывает, что прибор фактически сработал дважды, один раз для каждого метода в классе.

Это очень странное поведение.Есть какие-нибудь подсказки?

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Мне удалось достичь желаемого результата с помощью pytest.skip внутри прибора. Таким образом, если прибор выдает какое-то исключение, тесты с использованием приборов будут пропущены.

0 голосов
/ 18 января 2019

pytest перехватывает исключение SystemExit, что разумно, если подумать: если вы тестируете функцию, которая вызывает sys.exit, вы не захотите, чтобы это завершило весь ваш набор тестов.

Используйте pytest.exit вместо sys.exit, что сигнализирует pytest о том, что вы действительно хотите завершить тестовый набор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...