В чем разница между Self и Cls?

Ответ

Вопрос не соответствует категории "QA / Тестирование". В контексте тестирования на Python, self и cls используются при создании вспомогательных классов, фикстур или паттернов (например, Page Object).

  • self — это ссылка на экземпляр класса. Используется в обычных методах для доступа к атрибутам и методам конкретного объекта. В тестах через self мы обращаемся к драйверу браузера, данным теста или вспомогательным методам.
  • cls — это ссылка на сам класс. Используется в методах класса, помеченных декоратором @classmethod. Такие методы полезны для настройки, общей для всех тестов в классе (например, одноразовая инициализация).

Практический пример в тестах с использованием Pytest и Page Object Model:

import pytest
from selenium.webdriver.common.by import By

class LoginPage:
    # Элементы страницы
    USERNAME_INPUT = (By.ID, "username")
    PASSWORD_INPUT = (By.ID, "password")
    SUBMIT_BUTTON = (By.ID, "submit")

    def __init__(self, driver):
        # 'self.driver' - это конкретный экземпляр WebDriver для этого объекта страницы
        self.driver = driver

    # Обычный метод экземпляра (использует self)
    def login(self, username, password):
        self.driver.find_element(*self.USERNAME_INPUT).send_keys(username)
        self.driver.find_element(*self.PASSWORD_INPUT).send_keys(password)
        self.driver.find_element(*self.SUBMIT_BUTTON).click()

class TestLogin:
    # Метод класса (использует cls). Выполняется один раз перед всеми тестами в классе.
    @classmethod
    def setup_class(cls):
        # 'cls.driver' будет атрибутом класса, доступным всем тестам
        cls.driver = webdriver.Chrome()
        cls.driver.implicitly_wait(10)

    # Каждый тестовый метод - это метод экземпляра (использует self)
    def test_valid_login(self):
        # 'self.driver' здесь наследуется от класса
        login_page = LoginPage(self.driver)
        login_page.login("test_user", "secure_pass")
        assert "Dashboard" in self.driver.title

    @classmethod
    def teardown_class(cls):
        cls.driver.quit()

Таким образом, self работает с состоянием конкретного теста или объекта, а cls — с настройками, общими для всей группы тестов.

Ответ 18+ 🔞

А, ну это же классика, ёпта! Сейчас разложу по полочкам, чтобы даже мартышлюшка поняла. Вопрос, конечно, не совсем про тесты, но раз уж залезли в дебри Python, то хуй с горы — разберёмся.

Смотри, в тестах на Python, особенно когда пишешь какие-нибудь свои хитрые обёртки, фикстуры или этот ваш модный Page Object, без self и cls нихуя не сделаешь. Это как отвёртка и молоток — инструменты на все случаи жизни.

  • self — это твой личный раб, привязанный к конкретному экземпляру. Представь, что у тебя десять одинаковых машин. self — это ключи от одной, конкретной тачки. Ты можешь в неё сесть, завести, поцарапать дверь — и это касается только её. В тестах через self ты лезешь в драйвер браузера, который запущен для этого конкретного теста, или дергаешь данные, которые подготовил только для него. Без self ты просто будешь орать в пустоту, типа «залогинься!», а комп тебе в ответ: «да похуй, чувак, я нихуя не понял, где логиниться-то?».

  • cls — это уже начальник цеха. Это ссылка на сам класс, на чертеж. Используется в методах, которые помечены @classmethod. Зачем? Ну, например, чтобы один раз, для всех тестов в классе, сделать какую-то общую, овердохуищную подготовку. Запустить один драйвер на всех, подключиться к базе, нагенерить тестовых данных. Чтобы каждый тест по десять раз этого не делал и не тратил время. cls говорит: «Ребята, я тут всем вам кое-что приготовил, пользуйтесь».

Вот смотри, как это выглядит в жизни, когда ты не просто тесты пишешь, а пытаешься сделать это с умом:

import pytest
from selenium.webdriver.common.by import By

class LoginPage:
    # Координаты кнопочек и полей. Это как карта сокровищ, общая для всех.
    USERNAME_INPUT = (By.ID, "username")
    PASSWORD_INPUT = (By.ID, "password")
    SUBMIT_BUTTON = (By.ID, "submit")

    def __init__(self, driver):
        # А вот это уже 'self.driver' — конкретная лодка (браузер), на которой мы поплывём по этой карте СЕЙЧАС.
        self.driver = driver

    # Обычный метод — работает с КОНКРЕТНОЙ лодкой (self).
    def login(self, username, password):
        self.driver.find_element(*self.USERNAME_INPUT).send_keys(username)
        self.driver.find_element(*self.PASSWORD_INPUT).send_keys(password)
        self.driver.find_element(*self.SUBMIT_BUTTON).click()

class TestLogin:
    # Метод КЛАССА! Выполнится ОДИН РАЗ перед всеми тестами. Видишь '@classmethod'? Видишь 'cls'?
    @classmethod
    def setup_class(cls):
        # 'cls.driver' — это как общий гараж (атрибут класса). Мы загоняем туда одну машину на всех.
        cls.driver = webdriver.Chrome()
        cls.driver.implicitly_wait(10)

    # А это уже каждый тест по отдельности. 'self' тут — это конкретный заезд на конкретной трассе.
    def test_valid_login(self):
        # Каждый тест берет машину из общего гаража (cls.driver) через self.driver.
        login_page = LoginPage(self.driver)
        login_page.login("test_user", "secure_pass")
        assert "Dashboard" in self.driver.title

    @classmethod
    def teardown_class(cls):
        # И после всех заездов гараж закрываем. Тоже через cls.
        cls.driver.quit()

Короче, резюмирую, чтобы волнение ебать успокоилось: self — это «я, здесь и сейчас, в этом конкретном тесте». cls — это «мы, как команда, для всех тестов в этом классе». Используешь self для действий, cls — для общей подготовки и уборки. Всё гениальное просто, как три копейки.