Инструмент Pytest для класса через себя, а не как аргумент метода

Часто я пишу тестовый класс, который использует приспособление pytest в каждом методе. Вот пример. Я бы хотел избежать необходимости указывать имя прибора в подписи каждого метода. Это не СУХОЕ. Как это может быть сделано?

Я хотел бы получить доступ к приспособлению, указав приспособление как атрибут тестового класса. В этом примере я хотел бы видеть приспособление Google как атрибут TestGoogle. Это возможно?

from bs4 import BeautifulSoup
import pytest
import requests

@pytest.fixture()
def google():
    return requests.get("https://www.google.com")


class TestGoogle:
    def test_alive(self, google):
        assert google.status_code == 200

    def test_html_title(self, google):
        soup = BeautifulSoup(google.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
27
0
20 091
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Конечно, просто используйте приспособление для автозагрузки. Вот соответствующее место в документации pytest. В вашем примере изменение будет вводить дополнительный прибор (я назвал его _request_google_page):

from bs4 import BeautifulSoup
import pytest
import requests

@pytest.fixture()
def google():
    return requests.get("https://www.google.com")


class TestGoogle:

    @pytest.fixture(autouse=True)
    def _request_google_page(self, google):
        self._response = google

    def test_alive(self):
        assert self._response.status_code == 200

    def test_html_title(self):
        soup = BeautifulSoup(self._response.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"

Вы даже можете полностью отказаться от прибора google и перенести код на _request_google_page:

@pytest.fixture(autouse=True)
def _request_google_page(self):
    self._response = requests.get("https://www.google.com")

Обратите внимание, что по умолчанию _request_google_page будет вызываться один раз для каждого теста, поэтому каждый тест будет получать новый ответ. Если вы хотите, чтобы ответ был инициализирован один раз и повторно использовался во всех тестах в классе TestGoogle, отрегулируйте области прибора (scope='class' для _request_google_page и scope='module' или scope='session' для google). Пример:

from bs4 import BeautifulSoup
import pytest
import requests


@pytest.fixture(scope='module')
def google():
    return requests.get("https://www.google.com")


@pytest.fixture(autouse=True, scope='class')
def _request_google_page(request, google):
    request.cls._response = google


class TestGoogle:

    def test_alive(self):
        assert self._response.status_code == 200

    def test_html_title(self):
        soup = BeautifulSoup(self._response.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"

Спасибо @hoefling Это то, что я хотел. Я никогда не разбирался в функциональности приспособлений autouse. Теперь я понимаю. Ваше здоровье.

Donal Mee 03.05.2018 16:22

Рад, что смог вам помочь!

hoefling 04.05.2018 15:10

@hoefling у меня почему-то никогда не работает. Кажется, что методы тестирования получают новый экземпляр, а self не имеет атрибутов в методе настройки. Просто для контекста я использую 2 pytext.mark... в классе.

Ken4scholars 15.01.2019 04:25

@ Ken4scholars лучше всего задать отдельный вопрос, включая минимальный воспроизводимый пример неудачной тестовой установки, которая у вас есть. Ты можешь это сделать?

hoefling 15.01.2019 09:06

@hofling, конечно. Пожалуйста, проверьте этот вопрос. Хотя это другая проблема, но есть описание этой проблемы. stackoverflow.com/questions/54192519/…

Ken4scholars 15.01.2019 10:27

@hoefling, когда я устанавливаю для области видимости _request_google_page значение 'class' и область действия Google как "модуль", я вижу следующую ошибку внутри функции "def test_alive (self):" AttributeError: объект 'TestGoogle' не имеет атрибута '_response ' Любая идея?

Prashant Pathak 31.07.2020 18:42

@PrashantPathak Я добавил фрагмент с настроенными областями в конце ответа, проверьте это. Он будет работать, если вы скопируете его как есть.

hoefling 31.07.2020 19:55

@hoefling, спасибо, значит функция должна выходить за рамки класса.

Prashant Pathak 01.08.2020 16:59

@hoefling Можете ли вы также помочь мне понять одну концепцию? который мне трудно очистить. Таким образом, в приведенном выше коде def _request_google_page () ничего не возвращает, но мы можем использовать объект ответа в def test_alive (). Итак, как получить доступ к "request.cls._response" внутри методов тестирования класса, как последует вызов?

Prashant Pathak 01.08.2020 17:03

@PrashantPathak это часть сбора и подготовки тестов. request.cls будет TestGoogle, когда приспособление _request_google_page оценивается в тестовой коллекции, поэтому после сбора TestGoogle будет инициализирован TestGoogle._response; после этого выполняется TestGoogle().test_alive() и доступен self._response. На самом деле это переменная класса.

hoefling 02.08.2020 12:36

@hoefling, Ооо, я вижу, что это «я» здесь не является переменной экземпляра, оно в основном указывает на переменную класса. Понятно сейчас. Спасибо за ваше разъяснение

Prashant Pathak 05.08.2020 17:26

Я столкнулся с другой проблемой ScopeMismatch: вы пытались получить доступ к приспособлению с областью видимости «функция» с помощью объекта запроса с областью видимости «класс», задействованных фабрик.

Anurag jain 12.04.2021 20:37

@Anuragjain означает, что вы расширили область действия цепочки вызовов фикстур, что недопустимо. Это не проблема кода в ответе; если вам нужна помощь, задайте новый вопрос с минимальный воспроизводимый пример.

hoefling 12.04.2021 21:19

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

Я хотел вызвать прибор один раз для каждого тестового класса и повторно использовать значение в тестовых методах с помощью self. Это фактически то, что намеревалась сделать OP.

Вы можете использовать прибор request для доступа к классу, который его использует (request.cls), и назначить значение прибора в атрибуте класса. Затем вы можете получить доступ к этому атрибуту из self. Вот полный фрагмент:

from bs4 import BeautifulSoup
import pytest
import requests

@pytest.fixture(scope = "class")
def google(request):
    request.cls.google = requests.get("https://www.google.com")


@pytest.mark.usefixtures("google")
class TestGoogle:
    def test_alive(self):
        assert self.google.status_code == 200

    def test_html_title(self):
        soup = BeautifulSoup(self.google.content, "html.parser")
        assert soup.title.text.upper() == "GOOGLE"

Надеюсь, что это поможет кому-нибудь еще ответить на этот вопрос.

Однако нет возможности установить значение self.variable через это?

MohitC 04.02.2021 21:57

@MohitC Я не думаю, что есть, и я не могу придумать случая, когда это было бы необходимо, и cls не работал бы

makeiteasy 05.02.2021 11:03

я действительно хочу именно такого поведения. установите значение self.variable в тесте и используйте его в следующих тестах

Jorrit Smit 05.04.2021 13:14

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

Jan Sakalos 14.05.2021 19:38

Другие вопросы по теме