Как вызвать setup один раз для всех тестов и разборки после того, как все закончено

У меня есть куча тестов, написанных с использованием pytest. Есть все в каталоге dir. Например:

dir/test_base.py
dir/test_something.py
dir/test_something2.py
...

Упрощенная версия кода в них выглядит следующим образом:

test_base.py

import pytest

class TestBase:
   def setup_module(module):
      assert False

   def teardown_module(module):
      assert False

test_something.py

import pytest
from test_base import TestBase

class TestSomething(TestBase):
   def test_dummy():
       pass

test_something2.py

import pytest
from test_base import TestBase

class TestSomethingElse(TestBase):
   def test_dummy2():
       pass

Все мои файлы test_something*.py расширяют базовый класс в test_base.py. Теперь я написал методы setup_module(module) и teardown_module(module) в test_base.py. Я ожидал, что setup_module будет вызван один раз для всех тестов, и teardown_module() будет вызван в конце, когда все тесты будут завершены.

Но функции, кажется, не вызывают? Нужны ли декораторы для этого?

Ответ 1

Поместите setup_module и teardown_module вне класса на уровне модуля. Затем добавьте свой класс в свои тесты.

def setup_module(module):
    """..."""

def teardown_module(module):
    """..."""

class TestSomething:

    def test_dummy(self):
        """do some tests"""

Для получения дополнительной информации см. в этой статье.

Ответ 2

Требование OP состояло в том, чтобы каждая настройка и демонтаж выполнялись только один раз, а не один раз на модуль. Это можно сделать с помощью комбинации файла conftest.py, @pytest.fixture(scope="session") и передачи имени прибора в каждую тестовую функцию.

Они описаны в документации по приборам Pytest

Вот пример:

conftest.py

import pytest

@pytest.fixture(scope="session")
    def my_setup(request):
        print '\nDoing setup'
        def fin():
            print ("\nDoing teardown")
        request.addfinalizer(fin)

test_something.py

def test_dummy(my_setup):
    print '\ntest_dummy'

test_something2.py

def test_dummy2(my_setup):
    print '\ntest_dummy2'

def test_dummy3(my_setup):
    print '\ntest_dummy3'

Вывод при запуске py.test -s:

collected 3 items 

test_something.py 
Doing setup

test_dummy
.
test_something2.py 
test_dummy2
.
test_dummy3
.
Doing teardown

Имя conftest.py имеет значение: вы не можете дать этому файлу другое имя и ожидать, что Pytest найдет его в качестве источника данных.

Установка scope="session" важна. В противном случае настройка и демонтаж будут повторяться для каждого тестового модуля.

Если вы предпочитаете не передавать имя прибора my_setup в качестве аргумента каждой тестовой функции, вы можете поместить тестовые функции в класс и применить декоратор pytest.mark.usefixtures к классу.

Ответ 3

setup_module/teardown_module вызывают для модуля, где определены возможные (производные) тесты. Это также позволяет настроить настройку. Если у вас есть только один setup_module, вы можете поместить его в test_base.py и импортировать его из других мест. НТН.

Ответ 4

Прежде всего, это хорошая практика, чтобы поместить все тесты в модуль под названием "тесты":

<product>
   ...
   tests/
      __init__.py
      test_something.py

Во-вторых, я думаю, вы должны использовать методы setup_class/teardown_class в базовом классе:

import unittest
class MyBase(unittest.TestCase):

   @classmethod
   def setup_class(cls):
       ...

   @classmethod
   def teardown_class(cls):
       ...

Дополнительная информация: http://pytest.org/latest/xunit_setup.html