Вступление

Привет, сообщество.

Я хотел бы поделиться с Вами своим объяснением того, как понять фикстуры и как начать использовать их в своих проектах, тем самым начать радоваться жизни)

Вероятно, даже продвинутый QA Automation найдет что-то новое, но моя цель объяснить на пальцах эту тему начинающим, ибо именно в ней зачастую происходят затыки.

Файл conftest.py

Это специальный pytest файл, в который он заглядывает еще перед тем как запустить тесты. Поэтому в основном он используется для создания фикстур внутри нашего проекта.

Данный файл обычно находиться в корне проекта, возьмем к примеру базовую структуру PageObject:

Базовый PageObject
Базовый PageObject

Что такое фикстура

Фикстура - это объект, который можно рассматривать, как набор условий необходимых тесту для выполнения, например, зачастую фикстуры создаются, чтобы генерировать какие-то данные еще до теста и возвращать их для использования в тесте или перед тестом, вот несколько примеров:

  • Создавать подключение к базе данных перед тестом и отключаться от нее после завершения теста

  • Инициализировать драйвер-браузера и закрывать сессию после завершения теста

  • Авторизовываться перед запуском теста и не тратить время на логин

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

В целом, фикстуры ну прям очень напоминают декораторы, так как условно они оборачивают ваш тест и делают что-то до и иногда после выполнения теста.

Использование фикстур через return и ее передача в тест в качестве аргумента

Начнем с простого примера:

def connect_to_database():
    connection = "Соединение с базой данных установлено"
    return connection

Как Вы можете видеть, у нас есть максимально простая функция, она возвращает образно, подключение к базе данных.

Что, если мы хотим использовать ее, как обертку для теста, т.е подключаться к базе данных еще перед тестом, а уже в тесте использовать эти данные?

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

В этом нам поможет фикстурирование, т.е превращение нашей функции в фикстуру.

Для того, чтобы функцию зарегистрировать как фикстуру, в pytest есть специальный маркер (декоратор) @pytest.fixture, его нужно прописать над нужной функцией.

Напомню все общие фикстуры мы пишем в файле conftest.py, они будут видны всем тестовым классам по умолчанию.

import pytest


@pytest.fixture # Таким образом функция будет восприниматься, как фикстура
def connect_to_database():
    connection = "Соединение с базой данных установлено"
    return connection

conftest.py

Но как это использовать? Есть несколько путей, мы начнем с самого простого, а именно будем прокидывать фикстуру в качестве аргумента внутрь нашего теста (тестового метода).

import pytest


@pytest.fixture # Таким образом функция будет восприниматься, как фикстура
def connect_to_database():
    connection = "Соединение с базой данных установлено"
    return connection

conftest.py

import pytest


class TestExample:

    def test_1(self, connect_to_database): # Прокидываем фикстуру в тест и она выполнится перед тестом
          print(connect_to_database) # Используем фикстуру, она вернет нам текст с подключением к БД

test_example.py

В итоге перед запуском теста, в консоли мы увидим то самое сообщение "Соединение с базой данных установлено", что будет означать выполнение подключения к БД или любого другого кода перед тестом.

Как вы могли заметить, никаких импортов нет, тестовые файлы автоматически находят фикстуру находящуюся в conftest.py без каких-либо импортов, достаточно пробросить фикстуру в качестве аргумента в тестовый метод.

Но что, если фикстура возвращает несколько значений, например, сгенерированный логин и пароль, то как их использовать в тесте?

import pytest
import time


@pytest.fixture
def generate_data():
    login = f"autotest_{time.time()}@hyper.org" # Генерирует логин
    password = "512" # Назначает пароль
    return login, password # Возвращает логин и пароль

conftest.py

Исходя из того, как работает python, мы знаем, что он в данном случае вернется кортеж данных:

("autotest_12399412@hyper.org", "512") # логин, пароль

Соответсвенно, чтобы передать данные в тест, нужно так же передать фикстуру в качестве аргумента и через нее обращаться к элементам кортежа по индексу:

import pytest


class TestExample:
  
	def test_1(self, generate_data): # Прокидываем фикстуру в тест и она выполнится перед тестом
        login = generate_data[0] # Записываем в переменную сгенерированный логин
        password = generate_data[1] # Записываем в переменную полученный логин
        ...

test_example.py

Все это классно, но не совсем удобно, потому что, чтобы узнать к чему мы обращаемся, нужно идти в саму фикстуру, так как из строчки generate_data[0] ничего не будет понятно.

Выход следующий, можно возвращать значения в виде словаря и обращаться к элементам по ключу:

import pytest
import time


@pytest.fixture
def generate_data():
    login = f"autotest_{time.time()}@hyper.org" # Генерирует логин
    password = "512" # Назначает пароль
    return {"login":login, "password": password} # Возвращает логин и пароль

conftest.py

import pytest


class TestExample:

    def test_1(self, generate_data): # Прокидываем фикстуру в тест и она выполнится перед тестом
        login = generate_data["login"] # Записываем в переменную сгенерированный логин
        password = generate_data["password"] # Записываем в переменную полученный логин
        ...

test_example.py

Вот теперь стало намного понятнее)

Использование фикстур через request.cls и ее вызов с помощью маркера (декоратора)

Следующий способ использования фикстур - это request.cls

Постараюсь объяснить максимально простым языком, для этого возьмем тот же пример с генерацией логина и пароля:

  1. В качестве аргумента внутрь нашей фикстуры прокидываем request

  2. Назначим переменную с помощью request.cls.имя_переменной

import pytest
import time


@pytest.fixture
def generate_data(request):
    request.cls.login = f"autotest_{time.time()}@hyper.org" # Генерирует логин
    request.cls.password = "512" # Назначает пароль

conftest.py

Суть в том, что, когда вы объявляете переменную через request.cls.имя_переменной, в тестовом классе автоматически будет создаваться такой атрибут. Это то же самое, что если бы вы напрямую объявили их в init тестового класса:

import pytest


class TestExample:
    # Данный кусок кода = requst.cls.login и request.cls.password в фикстуре
	def __init__(self):
        self.login = f"autotest_{time.time()}@hyper.org"
        self.password = "512"
  • request - создать

  • cls - внутри класса

  • имя_переменной - атрибут класса

создать.внутри_класса.имя_переменной = request.cls.login

В случае использования request.cls, оператор return прописывать не нужно, но всегда нужно передавать в фикстуру request.

Теперь переходим к этапу использования. В случае, если вы используете вышеописанный метод, то не нужно прокидывать фикстуру в тест в качестве аргумента, тут все интереснее, мы будем использовать специальный pytest-маркер (декоратор):

  • @pytest.mark.usefixtures(”имя фикстуры”) - маркер (декоратор) для вызова фикстуры

Маркер (декоратор) прописывается либо над нужным тестом, в случае, если вы хотите генерировать данные из фикстуры только для одного теста, или над классом, если хотите генерировать новые данные для каждого теста.

import pytest
import time


@pytest.fixture
def generate_data(request):
    request.cls.login = f"autotest_{time.time()}@hyper.org" # Генерирует логин
    request.cls.password = "512" # Назначает пароль

conftest.py

import pytest

@pytest.mark.usefixtures("generate_data") # Вызываем фикстуру над классом
class TestExample:

    def test_1(self):
        print(self.login) # Сюда передастся логин
        print(self.password) # А сюда пароль

test_example.py

Если вы вызвали фикстуру через маркер (декоратор) и использовали request.cls для создания данных в фикстуре, то логин и пароль будут доступны через self параметр напрямую!

Надеюсь разобрались) Теперь по аналогии сделаем фикстуру для инициализации драйвера:

import pytest
import time

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service


@pytest.fixture
def get_driver(request):
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service)
    request.cls.driver = driver

conftest.py

Теперь, вызвав с помощью маркера (декоратора) фикстуру непосредственно в тесте, вы можете спокойно обращаться к драйверу и его методам через self.driver.

import pytest


@pytest.mark.usefixtures("get_driver") # Вызываем фикстуру над тестом
class TestExample:
  
	def test_1(self):
	    self.driver.get("https://yandex.ru") # Работаем с полученным обьектом драйвера

test_example.py

Автоматическое использование фикстур

Тут все просто, у фикстуры есть параметр:

  • autouse - данный параметр принимает в качестве значения True или False

В случае, если выставить autouse=True, фикстура будет вызываться абсолютно для каждого теста в проекте автоматически, без явного ее вызова где-либо.

import pytest
import time

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service


@pytest.fixture(autouse=True) # Пока не обращаем внимания на эту строку
def get_driver(request):
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service)
    request.cls.driver = driver

conftest.py

import pytest


class TestExample:

    def test_1(self):
        self.driver.get("https://vk.com") # И никаких явных вызовов фикстуры

test_example.py

Соответсвенно, чтобы избежать проблем и конфликтов между разными фикстурами, я рекомендую использовать этот атрибут исключительно для инициализации драйвера.

Пред- и постусловия в фикстурах

Для того, чтобы фикстура делала что-то перед тестом, например, инициализация драйвера, и после теста, например, закрытие браузера, существует специальная функция:

  • yield - это разделитель в контексте автоматизации, все, что написано над ним, будет исполнено до теста, все, что ниже - после теста.

import pytest
import time

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service


@pytest.fixture(autouse=True)
def get_driver(request):
    service = Service(ChromeDriverManager().install())
    driver = webdriver.Chrome(service=service)
    request.cls.driver = driver
    yield
    driver.quit()

conftest.py

Если мы вспомним как создается стандартный декоратор, то увидим, что он принимает в себя функцию. И все что над ней - это предусловия, а то, что после - это постусловия.

def decorator(test): # Принимает в себя функцию
    def wrapper():
        print("Перед тестом") # Предусловия
        test() # Функция которую декарируем
        print("После теста") # Постусловия
    return wrapper
  
@decorator # Применяем декоратор
def hello():
    print("Привет")

example.py

Соответственно, принцип работы фикстур +- аналогичнен, во время запуска тестов, в фикстуру вместо yield подставляется наш тест.

Область видимости фикстур

Область видимости определяет, как применяется фикстура, для всего набора тестов (для тестового класса) единожды или для каждого теста (тестового метода) отдельно.

За область видимости отвечает параметр фикстуры:

  • scope - определяет область применения фикстуры

В целом, для 99% случаев, достаточно знать лишь 2 области видимости:

  1. scope=”class” - фикстура будет вызвана один раз для всех тестов внутри тестового класса

    • Пример 1: Возьмем фикстуру инициализации драйвера

      import pytest
      import time
      
      from selenium import webdriver
      from webdriver_manager.chrome import ChromeDriverManager
      from selenium.webdriver.chrome.service import Service
      
      
      @pytest.fixture(autouse=True, scope="class")
      def get_driver(request):
          service = Service(ChromeDriverManager().install())
          driver = webdriver.Chrome(service=service)
          request.cls.driver = driver
          yield
          driver.quit()

      conftest.py

      И для примера сделаем 2 теста

      import pytest
      
      
      class TestExample:
        
      	def test_1(self):
          self.driver.get("https://vk.com")
      	
      	def test_2(self):
          self.driver.get("https://ya.ru")

      test_example.py

      В таком случае, экземпляр драйвера будет создан один раз для всех тестов, так же все тесты будут проходить в одном окне браузера, т.е в рамках одной сессии. Браузер закроется только тогда, когда пройдут все тесты, а это уже, как минимум, не позволит нам в будущем запускать тесты параллельно, ибо они будут друг друга перебивать.

    • Пример 2: Генерация логина

      import pytest
      import time
      
      
      @pytest.fixture(scope="class")
      def generate_login(request):
          request.cls.login = f"autotest_{time.time()@hyperr.org" # Генерирует логин

      conftest.py

      При использовании фикстуры описанной выше, логин сгенерируется один раз и будет одинаковым для всех тестов внутри класса.

      import pytest
      
      
      @pytest.mark.usefixtures("generate_login") # Вызов фикстуры генерации логина
      class TestExample:
        
      	def test_1(self):
              print(self.login)
      	
      	def test_2(self):
              print(self.login)

      test_example.py

      В результате, мы получим один и тот же логин в каждом тесте. Это может помочь в зависимых тестах, но тем не менее, атомарность - залог качественных тестов. Тут мы и подходим ко второй области видимости.

  2. scope=function” - фикстура будет вызываться для каждого теста по отдельности, атомарно.

    Это означает, что в случае использования фикстуры с драйвером, для каждого теста будет создаваться новый экземпляр драйвера, соотвественно будет открываться новая сессия браузера, а при генерации данных, для каждого теста будут генерироваться новые данные.

    • Пример 1: Возьмем фикстуру инициализации драйвера

      import pytest
      import time
      
      from selenium import webdriver
      from webdriver_manager.chrome import ChromeDriverManager
      from selenium.webdriver.chrome.service import Service
      
      
      @pytest.fixture(autouse=True, scope="function")
      def get_driver(request):
          service = Service(ChromeDriverManager().install())
          driver = webdriver.Chrome(service=service)
          request.cls.driver = driver
          yield
          driver.quit()

      conftest.py

      И для примера сделаем 2 теста

      import pytest
      
      
      class TestExample:
        
      	def test_1(self):
              self.driver.get("https://vk.com")
      	
      	def test_2(self):
              self.driver.get("https://ya.ru")

      test_example.py

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

    • Пример 2: Генерация логина

      import pytest
      import time
      
      
      @pytest.fixture(scope="function")
      def generate_login(request):
          request.cls.login = f"autotest_{time.time()}@hyper.org" # Генерирует логин
      

      conftest.py

      При использовании фикстуры, будет генирироваться новый логин для каждого теста

      import pytest
      
      
      @pytest.mark.usefixtures("generate_login") # Вызов фикстуры генерации логина
      class TestExample:
      	
          def test_1(self):
              print(self.login)
      	
      	def test_2(self):
              print(self.login)

      test_example.py

      В результате, мы получим полностью разные данные в каждом новом тесте.

Заключение

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

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

Мой Telegram: https://t.me/qa4_channel

Комментарии (38)


  1. teror4uks
    00.00.0000 00:00
    +5

    Да вроде бы оригинальная документация на оф сайте и так объясняет все что нужно.

    Ещё не понял зачем в классы объединять тесты?

    Эта магия с созданием атрибутов через request фикстуру выглядит не дружелюбно к чтению. Нужно ещё догадаться откуда оно там пришло, не проще ли передать в нужный тест фикстуру login, как параметр функции? Так бонусом ещё и легко указать тип для значения фикстуры что важно, так как в современном питоне принято использовать аннотации типов.


    1. manikosto Автор
      00.00.0000 00:00
      -3

      Обьясняет, да, только так, что любой новичок впадет в шок)

      Вопрос 1 - Тесты обьединяются в тестовый класс (это тестовый сьют для pytest) + как сказано в начале статьи, используется паттерн PageObject

      Вопрос 2 - Как написано в статье, магия с request это один из вариантов использования, о котором необходимо знать, к примеру для того, чтобы не прокидывать драйвер во все тесты в качестве аргумента

      Вопрос 3 - Касательно к примера с тестовыми данными, да, несомненно проще прокидывать фикстуру в качестве аргумента в тест

      Вопрос 4 - Про аннотации типов согласен, но их даже многие крутые разрабы не используют, а для новичков это лишние сбивающие с толку каракули в коде, а моя задача ясно изложить суть фикстур)

      Спасибо большое за комментарий)


      1. teror4uks
        00.00.0000 00:00
        +1

        Тесты обьединяются в тестовый класс (это тестовый сьют для pytest) + как сказано в начале статьи, используется паттерн PageObject

        Я вижу что они в классы объединены, я не понял зачем, так как пайтест парадигма как раз в том и заключается что ты пишешь атомарные тесты, там нет наследований как в юнит тестах всё постороенно на функциях и декораторах.

        Ваш ответ

        Как написано в статье, магия с request это один из вариантов использования, о котором необходимо знать, к примеру для того, чтобы не прокидывать драйвер во все тесты в качестве аргумента

        Противоречит следующему

        Касательно к примера с тестовыми данными, да, несомненно проще прокидывать фикстуру в качестве аргумента в тест

        Не вижу ничего плохого прописывать в каждый тест аргумент функции.

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

        Эм что это за крутые разрабы которые в современном питоне не используют типы? Может они и тесты не пишут? А то знаете какие то портянки кода не нужные.... Без типов и их статической проверки, если он сложнее одного файла, ваш код превращается в мишуру, которую приходится разгадывать в рантайме.


        1. manikosto Автор
          00.00.0000 00:00
          -4

          1. Если вы разработчик и не знакомы с направлением QA, и работали только с unit тестами, то статья не для Вас, она для QA! Но в целом почитайте про PageObjectModel (паттерн для автоматизации тестирования) это сфера QA. Тесты и так атомарные, там нет никаких наследований в коде.

          2. Зачем прописывать каждый раз драйвер?) Вам что крутой автоматизатор, что ChatGPT абсолютно такую же инициализацию драйвера через фикстуру сделает, как меня в примере)

          3. И снова, я убрал все лишнее чтобы сконцентрировать внимание QA Automation инженеров на определенной теме, а не фронтендеров, бекендеров, девопсов, если вы так негативно реагируете на отсутствие аннотаций, напишите лучше статью на эту тему, и задумайтесь сколько лет писали и без нее и никто не умер☺️)

          Ну и поверьте, чтобы изучить фикстуры, да и в целом любуууууую тему, по умолчанию знать аннотоцаии не является ни блокирующим, ни обязательным условием!

          Если человек не знает аннотаций, это не значит что он не имеет право учить что-то без них)


  1. Nutrol
    00.00.0000 00:00
    +1

    Фикстура - это превращенная в декоратор функция

    А что декорирует фикстура?


    1. manikosto Автор
      00.00.0000 00:00

      Тесты) Говорю про это когда обьясняю yield))


      1. Nutrol
        00.00.0000 00:00

        Как обычная функция ничего не принимающая, например, и просто возвращающая значение вдруг превращается в декоратор?


        1. manikosto Автор
          00.00.0000 00:00
          -3

          Из статьи:

          Для того, чтобы функцию зарегистрировать как фикстуру, в pytest есть специальный маркер @pytest.fixture, который нужно прописать над нужной функцией.


          1. Nutrol
            00.00.0000 00:00
            +2

            Открою секрет - вот этот вот самый маркер и есть декоратор, а yield это вообще про генераторы.


            1. manikosto Автор
              00.00.0000 00:00
              -4

              Ну это не секрет) Если говорить глубже, то да маркер = декоратор, по сути этот маркер декоратор превращающий в декоратор принимающую функцию) И yield в контексте pytest никак не связан с генераторами) Не путайте со стандартным yield из Python


            1. manikosto Автор
              00.00.0000 00:00
              -4

              Рекомендую ознакомиться в целом с pytest и PageObjectModel паттерном.
              Тут в оф документации https://docs.pytest.org/en/latest/how-to/fixtures.html можете найти информацию и про тестовые классы и про yield)


              1. Nutrol
                00.00.0000 00:00
                +6

                А вы доку хоть открывали? Где там упоминание, что pytest превратился в самостоятельный язык программирования, который по своему трактует ключевые слова python?

                Сомневаюсь, судя по вашей статье, что вам это поможет, но все же глянтье: https://github.com/pytest-dev/pytest/blob/main/src/_pytest/fixtures.py#L893-L922

                PS Причем здесь тестовые классы и POM?


                1. manikosto Автор
                  00.00.0000 00:00
                  -3

                  Я бы мог ответить, что судя по вопросу "зачем тесты обьединять в класс" все понятно, но к сожалению не вижу смысла обьяснять что-либо негативно настроенным людям, значит статься поможет кому-то другому)

                  Кратко поясню, есть контекст, в рамках фикстур yield выполняет функцию пред- и постусловия, и да, я читал официальную доку)

                  Вот ответ для Вас из нее, если владеете английским вероятно поймете:

                  “Yield” fixtures yield instead of return. With these fixtures, we can run some code and pass an object back to the requesting fixture/test, just like with the other fixtures. The only differences are:

                  1. return is swapped out for yield.

                  2. Any teardown code for that fixture is placed after the yield.

                  Once pytest figures out a linear order for the fixtures, it will run each one up until it returns or yields, and then move on to the next fixture in the list to do the same thing.

                  Once the test is finished, pytest will go back down the list of fixtures, but in the reverse order, taking each one that yielded, and running the code inside it that was after the yield statement.


                  1. Nutrol
                    00.00.0000 00:00
                    +1

                    Я, вообще, про классы ничего не писал) Таааак... Доку читали, уже не плохо. И где там говорится что yield не превращает функцию в генератор? Все что написано в доке этому никак не противоречит и сорцы pytest это как раз и подтверждают. Учите матчасть)


                    1. manikosto Автор
                      00.00.0000 00:00

                      Про классы пардон, не ваш вопрос, моя вина, ошибки признавать умею) Я понял о чем вы, только вот в чем суть, после прочтения моей статьи автоматизатор, особенно юнный, сможет легко зайти и использовать фикстуры на полную, даже не парясь о том, что такое генераторы. В рамках тестирования и написания фикстур, вот вообще все равно генератор это или нет. Для тестирования это разделитель пред и постусловия.

                      Пример: Как вы поступите с ребенком, когда он Вас спросит, как ездит машинка?

                      Наверное Вы ребенку скажете, что вот баранка, если ее крутить, то машинка поворачивает, если жать на педальку она едет.

                      В данной ситуации, ребенку важна и полезна только эта информация, а не та, где вы начнете говорить, что машина поворачивает, потому что передается крутящий момент на оси колес или машина едет потому что в ДВС работают поршни, туда впрыскивается бензин, и посредством его сгорания и т.д...

                      Да и в реальной жизни, вот мне пофигу как машина едет, мне достаточно верхнеуровневых знаний, и поверьте, если вы о машине знаете все глубже, от этого я или другой человек водить хуже чем вы не будет)


                      С образовательной точки зрения, я считаю моя статься несет море полезной информации.

                      В целом, спасибо за комментарий, статься написана как раз для людей, а не мат батанов и программеров с 100к + лет стажем)


                      1. funca
                        00.00.0000 00:00
                        +1

                        Наверное Вы ребенку скажете, что вот баранка, если ее крутить, то машинка поворачивает, если жать на педальку она едет.

                        Если ребенок уже знает, что баранка это съедобное изделие из муки, то у него тоже возникнет когнитивный диссонанс. Вам придется дополнительно рассказывать про шоферский жаргон. Что в целом усложняет задачу обоим: вам объяснить, ребенку - понять. Разве не проще сказать, что крутить нужно рулевое колесо?

                        В остальном про пред и пост условия полностью поддерживаю.


                      1. manikosto Автор
                        00.00.0000 00:00
                        +1

                        В статье как раз и говориться о рулевом колесе, жаргонов там вы не найдете)

                        В целом, спасибо за внимание к статье и за дискуссию)

                        Я не могу сказать что Вы не правы, отчасти правы, но скажу однозначно, обьяснить на пальцах без заумных фраз чаще на много полезнее и эффективнее, чем грузить терминологией, которая может оттолкнуть человека.

                        Уметь программировать и учить, доносить информацию так чтобы ей могли пользоваться, это разные вещи)

                        Ну и важно помнить, нет единого пути, собственно в статье я представил свой, и уверен, он точно кому-то поможет)


                      1. Nutrol
                        00.00.0000 00:00
                        +1

                        Ребенку, в отличии от юного автоматизатора, не надо будет общаться с коллегами и проходить собеседования)


                      1. manikosto Автор
                        00.00.0000 00:00
                        +1

                        Отрицание, верный признак негативного восприятия всего и вся)

                        Поверьте, этого более чем достаточно чтобы ответить на все вопросы, человек идет на автоматизатора, а не разработчика бекенда!

                        Я проходил очень много собеседований, получал офферы в очень хорошие компании, как и вы скорее всего (в хорошем смысле) и меня более чем отлично понимали!

                        Судя по тому что Вы разработчик, говорить нам особо дальше не о чем, предположу, что вероятно специфику собеседований и знаний для автоматизатора вы не совсем знаете.

                        У вас свой опыт, у меня свой, и косвенно утверждать что ваш опыт это эталон такое себе.


                      1. funca
                        00.00.0000 00:00

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

                        Расскажите, как у вас в компании вообще строится взаимодействие AQA с разработкой или вы живёте с ними в параллельных мирах не пересекаясь?


                      1. manikosto Автор
                        00.00.0000 00:00
                        -2

                        Если Вы не поймете, сотня других автоматизаторов поймет)


                      1. manikosto Автор
                        00.00.0000 00:00
                        +1

                        Ну и поверьте, если люди дошли до темы фикстур, они явно не идиоты, уж смогут обработать информацию и сформулировать для себя поинт


                      1. manikosto Автор
                        00.00.0000 00:00

                        Но еще раз скажу спасибо, любое мнение имеет место быть????

                        Ну и в названии статьи напомню «На человеческом», не на прогерском, математическом или еще каком-то языке)

                        Очень сильно не хватает такого рода обьяснений!


                      1. Ariki
                        00.00.0000 00:00
                        +1

                        В целом-то неплохая статья получилась, я прочитал с интересом. Но неверное использование терминологии никогда не идёт на пользу делу, лишь сбивает с толку. А кроме того, портит впечатление от текста и вызывает недоверие к автору. Аудитория Хабра привыкла к точности формулировок. Большинству людей, имеющих дело с кодом, просто больно, когда фикстуру называют декоратором, декоратор маркером, оператор return методом, а yield — функцией.


                      1. manikosto Автор
                        00.00.0000 00:00

                        Вот это адекватная, без негативная критика, вызывает уважение!

                        Я вас понимаю, сам использую терминологию в работе, некоторые моменты в статье поправлю, спасибо!

                        Если говорить в целом, автоматизатор, даже продвинутый, имеет явно меньше опыта с кодом, и многие термины могут быть не понятны, опять же, QA Automation, после этой статьи пойдет и напишет тест используя фикстуры и принесет пользу компании и постепенно будет углубляться в другие темы, а не пойдет читать про аннотации, про генераторы и прочее, не принеся никакой пользы в итоге


                      1. manikosto Автор
                        00.00.0000 00:00
                        +1

                        В конечном же итоге, можно всю жизнь изучать как устроен автомобиль, но ни разу не сесть за руль) Думаю тут сложно не согласиться


                      1. funca
                        00.00.0000 00:00

                        Думаю тут сложно не согласиться

                        В свою защиту вы пытаетесь выставить автотестеров какими-то дремучими. Может такова политика у вашего работодателя или ещё какая-то особенность. Со стороны эти упражнения в риторике и тщетные попытки продать читателям баг как фичу выглядят нелепо. Если вы профессионал, уже сто раз могли набраться мужества и все поправить.

                        Последние несколько лет часто работаю с QA (индусы в основном) потому, что они знают продукт подчас лучше BA и разработчиков. Иногда про себя упрекаю в дотошности, но ни разу не замечал безграмотности. Они сами меня периодически поправлют когда говорю что-то не правильно.


                      1. manikosto Автор
                        00.00.0000 00:00

                        Спасибо за ваше мнение ????


                      1. manikosto Автор
                        00.00.0000 00:00

                        @Ariki

                        Насчет return опечатался, исправил спасибо) yield - в статье я функцией не называл)

                        Так же поправил определение фикстуры)

                        Спасибо за продуктивную и не негативную критику) На сколько я вижу, некоторые люди негатив считают продуктивной критикой)


                  1. funca
                    00.00.0000 00:00

                    Да, не. Желание объяснить понятным языком понятно. Но тут, как выше заметили, в результате местами получился какой-то сюр. Видимо у вас там какой-то местный жаргон, раз называете фикстуры декоратором. Но со стороны выглядит феерично. Всё таки в статье на широкую аудиторию лучше назвать вещи своими именами.


  1. mortadella372
    00.00.0000 00:00
    +1

    что позволит запускать тесты параллельно

    Ну, все-таки без плагина xdist или подобного параллельно запускать не получится, тесты в классе (или в модуле) исполняются последовательно, в порядке объявления.


    1. manikosto Автор
      00.00.0000 00:00

      Тут я имел ввиду саму возможность параллельного запуска) Если у вас не атомарные тесты, и создается лишь 1 экземпляр драйвера на класс, то параллельно вы их не запустите, будет оооооочень много проблем)

      Но за комментарий спасибо! сделал уточнение в статье)


  1. conopus
    00.00.0000 00:00

    Еще один текст в жанре школьного изложения. Для публикации непригодно. При этом автор еще и от замечаний отбрыкивается. В качестве альтернативы рекомендую Brain Okken "Testing with pytest".


  1. dikobra4
    00.00.0000 00:00
    +1

    Спасибо за статью! Может местами не очень точно, но определенно на человеческом языке)

    Всё таки наверное правильнее было бы поставить scope в другом порядке по важности:

    1. function - инициализируем предусловия для конкретного теста, выдаем специфические тестовые данные и т.д. В идеале, если стремиться к атомарности тестов, для каждого теста можно бы и браузер отдельный запускать средствами, например selenoid

    2. session - привести стенд в исходное состояние, создать тестовые данные, подключиться к БД и очень много других действий, которые не имеет смысла выполнять больше одного раза за прогон

    3. class - для каких-то специфических операций для конкретного тест-сьюита

    Буду рад узнать, если я вдруг не прав)


    1. manikosto Автор
      00.00.0000 00:00

      Спасибо за комментарий)

      Да нет, все верно говорите, я в статье не стал все scopes перечислять, просто выделил два самых часто используемых))


  1. Zbosenko
    00.00.0000 00:00


    1. manikosto Автор
      00.00.0000 00:00

      ????


  1. upcFrost
    00.00.0000 00:00

    Статья для новичка кмк хорошая, но как минимум нет фабрик, а это очень нужная вещь. Иначе джуны начинают плодить методы с передачей всего подряд в качестве аргумента либо просто копипастить код "потому что нужно больше одного объекта"