#python #selenium #pytest
Вопрос:
Для моего тестирования селена с помощью pytest у меня есть следующая логика в conftest.py файл
import pytest
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.firefox import GeckoDriverManager
@pytest.fixture(params=["Chrome","Firefox"],scope='class')
def oneTimeSetup1(request):
if request.param == "Chrome":
driver = webdriver.Chrome(ChromeDriverManager().install())
if request.param == "Firefox":
driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())
driver.implicitly_wait(5)
driver.maximize_window()
driver.get("https://courses.letskodeit.com/practice")
if request.cls is not None:
request.cls.driver = driver
print("the velue of param is " request.param)
yield driver
driver.quit()
моя структура теста такова
dir tests
--conftest.py
--test_one.py
----TestClassOne
------test_one
------test_two
когда я соберу тест, я смогу увидеть ниже
<Package tests>
<Module test_one.py>
<Class TestClassOne>
<Function test_one[Chrome]>
<Function test_one[Firefox]>
<Function test_two[Chrome]>
<Function test_two[Firefox]>
Поскольку область действия приспособления oneTimeSetup1 является классом, я не уверен, почему каждая тестовая функция запускается с новым сеансом браузера.
Можем ли мы провести один сеанс браузера Chrome, который выполнит как my test_one и test_two, так и то же самое для firefox.
import pytest
from pages.page1 import Page1
@pytest.mark.usefixtures("oneTimeSetup1")
class TestClassOne():
@pytest.fixture(autouse=True)
def classObject(self):
self.page = Page1(self.driver)
@pytest.mark.run(order=1)
def test_one(self):
self.page.methodA()
print("This is Test One")
@pytest.mark.run(order=2)
def test_two(self):
self.page.methodC()
print("This is Test Two")
Комментарии:
1. Да, я вижу, что браузер вызывается в общей сложности 4 раза. Разве он не должен позвонить дважды? Один раз с браузером = Chrome amp; браузер = Firefox??
2. Я добавляю печать(«значение параметра равно» request.param) в oneTimeSetup1. Я прикрепил скриншот CLI. Для каждой из тестовых функций вызывается новый сеанс браузера.
3. Хорошо, теперь я могу воспроизвести проблему — это связано с
pytest-ordering
(я не установил ее при первой попытке). Кажется, это нарушает рамки. Поскольку мне посчастливилось сохранитьpytest-order
преемникаpytest-ordering
(который больше не поддерживается), я напишу для этого ошибку. Попробуйте пока удалитьrun
метки и проверьте, происходит ли это по-прежнему.4. Спасибо, работает как заклинание после удаления @pytest.mark.run. Есть ли какой-либо другой способ сохранить порядок тестов? Я надеюсь, что они исправят эту проблему в следующем выпуске pytest-заказа.
5. Проблема здесь в параметризованных тестах — упорядочение тестов приведет к объединению параметризованных тестов, в то время как область действия класса будет делать обратное. Я подумаю об этом… Как я уже писал, я утверждаю
pytest-order
, что «они» были бы мной в этом случае. Я посмотрю, что я могу сделать, хотя мне пока немного неясно, потому что параметризация и упорядочение в области классов здесь несколько противоречат друг другу.
Ответ №1:
Как упоминалось в комментариях, проблема связана с заказом через pytest-ordering
плагин. На самом деле это ожидаемое поведение (а не ошибка, как я писал изначально), потому что тесты четко упорядочены, и этот порядок выполняется после любого первоначального заказа из-за использования прибора.
Есть возможность изменить это поведение, если использовать pytest-порядок (вилку pytest-порядка, которая больше не поддерживается) с опцией —снисходительный-порядок. Это изменяет последовательность заказа, так что тесты сначала упорядочиваются плагином, а затем устройством. Обратите внимание, что в этом случае вам нужно изменить маркер заказа с run
на order
:
...
@pytest.mark.run(order=2)
def test_one(self):
self.page.methodA()
print("This is Test One")
@pytest.mark.order(1)
def test_two(self):
self.page.methodC()
print("This is Test Two")
(Я изменил заказ, чтобы показать, что заказ имеет какое-либо действие). Если запустить это без опции, вы получите (как видно из исходного вопроса):
$ python -m pytest --collect-only
<Package tests>
<Module test_one.py>
<Class TestClassOne>
<Function test_two[Chrome]>
<Function test_two[Firefox]>
<Function test_one[Chrome]>
<Function test_one[Firefox]>
С помощью этой --indulgent-ordering
опции вы получаете вместо:
$ python -m pytest --collect-only --indulgent-ordering
<Package tests>
<Module test_one.py>
<Class TestClassOne>
<Function test_two[Chrome]>
<Function test_one[Chrome]>
<Function test_two[Firefox]>
<Function test_one[Firefox]>
что позволяет приспособлению правильно работать как приспособление с привязкой к классу.
Как обычно, вы можете добавить эту опцию в свой pytest.ini
, если хотите, чтобы она была эффективной для всех тестов:
[pytest]
addopts = --indulgent-ordering
Отказ от ответственности:
Я автор pytest-order
книги .