Часто я пишу тестовый класс, который использует приспособление 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"
Конечно, просто используйте приспособление для автозагрузки. Вот соответствующее место в документации 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 у меня почему-то никогда не работает. Кажется, что методы тестирования получают новый экземпляр, а self
не имеет атрибутов в методе настройки. Просто для контекста я использую 2 pytext.mark...
в классе.
@ Ken4scholars лучше всего задать отдельный вопрос, включая минимальный воспроизводимый пример неудачной тестовой установки, которая у вас есть. Ты можешь это сделать?
@hofling, конечно. Пожалуйста, проверьте этот вопрос. Хотя это другая проблема, но есть описание этой проблемы. stackoverflow.com/questions/54192519/…
@hoefling, когда я устанавливаю для области видимости _request_google_page значение 'class' и область действия Google как "модуль", я вижу следующую ошибку внутри функции "def test_alive (self):" AttributeError: объект 'TestGoogle' не имеет атрибута '_response ' Любая идея?
@PrashantPathak Я добавил фрагмент с настроенными областями в конце ответа, проверьте это. Он будет работать, если вы скопируете его как есть.
@hoefling, спасибо, значит функция должна выходить за рамки класса.
@hoefling Можете ли вы также помочь мне понять одну концепцию? который мне трудно очистить. Таким образом, в приведенном выше коде def _request_google_page () ничего не возвращает, но мы можем использовать объект ответа в def test_alive (). Итак, как получить доступ к "request.cls._response" внутри методов тестирования класса, как последует вызов?
@PrashantPathak это часть сбора и подготовки тестов. request.cls
будет TestGoogle
, когда приспособление _request_google_page
оценивается в тестовой коллекции, поэтому после сбора TestGoogle
будет инициализирован TestGoogle._response
; после этого выполняется TestGoogle().test_alive()
и доступен self._response
. На самом деле это переменная класса.
@hoefling, Ооо, я вижу, что это «я» здесь не является переменной экземпляра, оно в основном указывает на переменную класса. Понятно сейчас. Спасибо за ваше разъяснение
Я столкнулся с другой проблемой ScopeMismatch: вы пытались получить доступ к приспособлению с областью видимости «функция» с помощью объекта запроса с областью видимости «класс», задействованных фабрик.
@Anuragjain означает, что вы расширили область действия цепочки вызовов фикстур, что недопустимо. Это не проблема кода в ответе; если вам нужна помощь, задайте новый вопрос с минимальный воспроизводимый пример.
Мне пришлось решить аналогичную проблему, и принятое решение не сработало для меня с приспособлением с привязкой к классу.
Я хотел вызвать прибор один раз для каждого тестового класса и повторно использовать значение в тестовых методах с помощью 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 Я не думаю, что есть, и я не могу придумать случая, когда это было бы необходимо, и cls
не работал бы
я действительно хочу именно такого поведения. установите значение self.variable в тесте и используйте его в следующих тестах
@JorritSmit звучит странно, чтобы установить значение в одном тесте, которое будет использоваться в других тестах. Тест не должен генерировать значения для других тестов.
Спасибо @hoefling Это то, что я хотел. Я никогда не разбирался в функциональности приспособлений autouse. Теперь я понимаю. Ваше здоровье.