Подтвердить что ты не робот

Как правильно настроить и разорвать мой класс pytest с помощью тестов?

Я использую selenium для сквозного тестирования и не могу понять, как использовать методы setup_class и teardown_class.

Мне нужно настроить браузер в методе setup_class, затем выполнить несколько тестов, определенных как методы класса, и, наконец, выйти из браузера в методе teardown_clas.

Но логически это кажется плохим решением, потому что на самом деле мои тесты будут работать не с классом, а с объектом. Я передаю параметр self внутри каждого метода тестирования, чтобы получить доступ к переменным объектов:

class TestClass:

    def setup_class(cls):
        pass

    def test_buttons(self, data):
        # self.$attribute can be used, but not cls.$attribute?  
        pass

    def test_buttons2(self, data):
        # self.$attribute can be used, but not cls.$attribute?
        pass

    def teardown_class(cls):
        pass

И даже кажется неправильным создавать экземпляр браузера для класса. Он должен создаваться для каждого объекта отдельно, верно?

Итак, мне нужно использовать методы __init__ и __del__ вместо setup_class и teardown_class?

4b9b3361

Ответ 1

В соответствии с Фиксация/выполнение кода разрыва использование addfinalizer является "историческим".

Как историческое примечание, другой способ написать код разрыва - это принять объект запроса в вашу функцию привязки и вызывать его request.addfinalizer один или несколько раз:

Нынешняя лучшая практика настройки и разгона заключается в использовании yield

import pytest

@pytest.fixture()
def resource():
    print("setup")
    yield "resource"
    print("teardown")

class TestResource(object):
    def test_that_depends_on_resource(self, resource):
        print("testing {}".format(resource))

Выполнение этого результата приводит к

$ py.test --capture=no pytest_yield.py
=== test session starts ===
platform darwin -- Python 2.7.10, pytest-3.0.2, py-1.4.31, pluggy-0.3.1
collected 1 items

pytest_yield.py setup
testing resource
.teardown


=== 1 passed in 0.01 seconds ===

Ответ 2

Когда вы пишете "тесты, определенные как методы класса", вы действительно имеете в виду методы класса (методы, которые получают его class в качестве первого параметра) или просто обычные методы (методы, которые получают экземпляр как первый параметр)?

Так как ваш пример использует self для методов тестирования, я предполагаю последний, поэтому вам просто нужно использовать setup_method вместо этого:

class Test:

    def setup_method(self, test_method):
        # configure self.attribute

    def teardown_method(self, test_method):
        # tear down self.attribute

    def test_buttons(self):
        # use self.attribute for test

Экземпляр метода тестирования передается в setup_method и teardown_method, но может быть проигнорирован, если ваш код установки/разрыва не должен знать контекст тестирования. Дополнительную информацию можно найти здесь.

Я также рекомендую вам ознакомиться с py.test приспособлениями, так как они являются более мощной концепцией.

Ответ 3

Как пояснил @Bruno, использование pytest-приборов - это еще одно решение, доступное как для тестовых классов, так и для простых тестовых функций. Здесь пример тестирования функций python2.7:

import pytest

@pytest.fixture(scope='function')
def some_resource(request):
    stuff_i_setup = ["I setup"]

    def some_teardown():
        stuff_i_setup[0] += " ... but now I'm torn down..."
        print stuff_i_setup[0]
    request.addfinalizer(some_teardown)

    return stuff_i_setup[0]

def test_1_that_needs_resource(some_resource):
    print some_resource + "... and now I'm testing things..."

Итак, запуск test_1... вызывает:

I setup... and now I'm testing things...
I setup ... but now I'm torn down...

Обратите внимание, что stuff_i_setup ссылается на прибор, позволяя этому объекту быть setup и torn down для теста, с которым он взаимодействует. Вы можете себе представить, что это может быть полезно для постоянного объекта, такого как гипотетическая база данных или какое-то соединение, которое должно быть очищено до того, как каждый тест будет запущен, чтобы изолировать их.

Ответ 4

Это может помочь http://docs.pytest.org/en/latest/xunit_setup.html

В моем наборе тестов я группирую свои тестовые случаи в классы. Для настройки и демонтажа, который мне нужен для всех тестовых случаев в этом классе, я использую методы классов setup_class(cls) и teardown_class(cls).

А для настройки и демонтажа, которые мне нужны для каждого тестового случая, я использую setup_method(method) и teardown_method(methods)

Пример:

lh = <got log handler from logger module>

class TestClass:
    @classmethod
    def setup_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    @classmethod
    def teardown_class(cls):
        lh.info("starting class: {} execution".format(cls.__name__))

    def setup_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def teardown_method(self, method):
        lh.info("starting execution of tc: {}".format(method.__name__))

    def test_tc1(self):
        <tc_content>
        assert 

    def test_tc2(self):
        <tc_content>
        assert

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

Вы можете добавить другие шаги по настройке и демонтажу, которые вы можете выполнить в соответствующих местах.

Надеюсь, это поможет!

Ответ 5

Ваш код должен работать так, как вы ожидаете, если вы добавите декораторы @classmethod.

@classmethod 
def setup_class(cls):
    "Runs once per class"

@classmethod 
def teardown_class(cls):
    "Runs at end of class"

См. http://pythontesting.net/framework/pytest/pytest-xunit-style-fixtures/