Тестовый пример параметризации Pytest совместно использует переменную класса - PullRequest
0 голосов
/ 24 января 2019

Я недавно начал использовать pytest и написал следующий класс.

import pytest
import yaml
import random

testcases = list()
class TestSample(object):
    test_yml_file = "/tmp/test_inputs.yml"

    yamlTestList = list()
    with open(test_yml_file, 'r') as testYamlFile:
        yamlTestList = yaml.load(testYamlFile)

    global testcases
    testcases = []

    for d in yamlTestList['testcases']:
        temp = dict()
        for k,v in d.items():
            temp[k] = v
        testcases.append((temp['testcase'],temp))

    last_value = 2

    @classmethod
    def setup_class(self):
        test_sample = TestSample()

    @pytest.mark.debug
    @pytest.mark.parametrize(('testname', 'testInput'), testcases)
    def test_run(self,testname,testInput):
        if last_value >= 10:
            last_value += random.randint(1,10)

Текущая проблема - Для каждого теста параметризации last_value всегда равно 2. Как мы можем использовать значение переменной 'last_value', измененной в предыдущем тестовом примере на текущий тест?

1 Ответ

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

Ответ:

Вам нужно будет создать экземпляр переменной lastvalue во внешней области видимости, из которой можно вызывать параметризованную функцию, а не в самом тестовом классе.Это из-за того, как параметризация работает с pytest.Каждый вызов функции с каждым отдельным набором параметров существует в отдельной области видимости, поэтому в своем коде вы в основном сбрасываете переменную lastvalue на 2 каждый раз перед вызовом функции.

Решение 1:

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


last_value = 0


class TestSample(object):
    testcases = [("name1", 1), ("name2", 2), ("name3", 3), ("name4", 4)]

    @pytest.mark.parametrize(('testname', 'testInput'), testcases)
    def test_run(self, testname, testInput):
        global last_value
        if last_value >= 10:
            last_value += random.randint(1, 10)
        else:
            last_value += 5

        print(last_value)

Обратите внимание, что я добавил в функцию условие else, чтобы проверить это.Даже если бы параметризация работала аналогично циклу внутри одного экземпляра класса, переменная lastvalue никогда бы не изменилась в вашем примере кода, поскольку предложение if last_value >= 10 никогда не имеет шансов встретиться и, следовательно, приращение lastvalue никогда не будетна самом деле происходит.

Лучшее решение:

Вместо использования глобалов, я бы рекомендовал использовать приспособление pytest с областью видимости "class".Вы можете прочитать о приспособлениях и областях действия приспособлений в документации по pytest здесь.

@pytest.fixture(name="sample_manager", scope="class")
def sample_manager_fixture():
    class SampleManager:
        def __init__(self):
            self.last_value = 0

    return SampleManager()


class TestSample:
    testcases = [("name1", 1), ("name2", 2), ("name3", 3), ("name4", 4)]

    def test_order(self, sample_manager):
        print(sample_manager.last_value)

    @pytest.mark.parametrize(('testname', 'testInput'), testcases)
    def test_run(self, testname, testInput, sample_manager):
        if sample_manager.last_value >= 10:
            sample_manager.last_value += random.randint(1, 10)
        else:
            sample_manager.last_value += 5

        print(sample_manager.last_value)

Функция приспособления sample_manager_fixture() возвращает экземпляр класса SampleManager, когда он передается в тестовую функцию,Pytest обрабатывает все это за кулисами, поэтому все, что вам нужно сделать, это включить имя прибора (объявленное явно в моем случае) в качестве параметра.Область действия прибора определяет «продолжительность жизни» каждого конкретного экземпляра объекта, возвращаемого из прибора.Таким образом, установка области видимости «class» для фиксатора уведомляет pytest о том, что вы хотите, чтобы все тестовые функции в определенном классе совместно использовали один и тот же экземпляр объекта, возвращенного из фиксатора.Вы можете вернуть любой объект с любой структурой из нужных вам осветителей, чтобы они были действительно мощным инструментом для управления данными в ваших тестах.

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