Какими свойствами должен обладать хороший автоматизированный тест?

Ответ

Качественный автотест соответствует принципам FIRST и другим best practices:

  • F — Fast (Быстрый) Тесты должны выполняться быстро, чтобы давать быструю обратную связь и не тормозить CI/CD.

  • I — Independent/Isolated (Независимый/Изолированный) Тест не должен зависеть от состояния, оставленного другими тестами, или от внешних сервисов (используйте моки/стабы).

  • R — Repeatable (Повторяемый) Результат теста должен быть детерминированным: при одинаковых входных данных и окружении он всегда дает один и тот же результат.

  • S — Self-Validating (Самопроверяемый) Тест должен однозначно завершаться статусом PASS или FAIL без необходимости ручной интерпретации логов.

  • T — Timely (Своевременный) Тест должен быть написан в нужное время (часто — сразу после реализации фичи).

Дополнительные критически важные свойства:

  • Читаемость и простота (Readable/Simple) Код теста должен быть понятен. Используйте паттерны типа Arrange-Act-Assert (AAA).
  • Поддерживаемость (Maintainable) Тест должен быть устойчив к незначительным изменениям в UI/API. Использование Page Object Model (POM) для UI-тестов помогает в этом.
  • Проверяет одну вещь (Focused) Один тест — одна ответственность. Это упрощает отладку при падении.

Пример хорошего автотеста (Python, pytest):

import pytest

def test_user_can_add_item_to_cart(authenticated_user, clean_cart):
    # Arrange: Подготовка данных и состояния
    item = Item(id=123, name="Test Book", price=29.99)
    catalog_page = CatalogPage()
    cart_page = CartPage()

    # Act: Выполнение тестируемого действия
    catalog_page.open()
    catalog_page.add_item_to_cart(item.id)
    cart_page.open()

    # Assert: Проверка ожидаемого результата
    cart_items = cart_page.get_items()
    assert len(cart_items) == 1
    assert cart_items[0].name == item.name
    assert cart_items[0].price == item.price

Ответ 18+ 🔞

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

Представь себе: ты написал тест, запускаешь его, а он, сука, бежит дольше, чем я ищу в холодильнике пиво после пятницы. Это пиздец, а не тест! F — Fast (Быстрый) — это святое. Если обратная связь приходит через полчаса, ты уже забыл, что там тестировал. CI/CD встанет колом, а тимлид начнёт нервно курить.

Дальше — I — Independent (Независимый). Это, блядь, основа основ! Твой тест — как тот мужик в бане: должен сам всё за собой помыть и не оставлять хуйни для следующего. Никаких "о, а вот предыдущий тест создал юзера, и я на нём проверю". Хуй там! Каждый тест — сам себе режиссёр, актёр и уборщица. Зависимости? Моки и стабы, ёпта! Подменил этот ебучий внешний сервис заглушкой и спи спокойно.

R — Repeatable (Повторяемый). Вот это, блядь, магия! Запустил раз — упал. Запустил два — прошёл. Запустил три — "ой, а база упала". Это не тест, а лотерея ебаная. Результат должен быть как удар кирпичом по яйцам: предсказуемый и болезненный. Одинаковые входные = одинаковый исход. Никаких "а сегодня пятница, и API немного грустит".

S — Self-Validating (Самопроверяемый). Это про то, чтобы не надо было, как дураку, вглядываться в логи и гадать: "Ну это зелёный или красный? А может, синий?". Тест должен орать: "ПАСС!" или "ФАК!" — и всё. Без танцев с бубном и чтения трёх томов отчётов. Сам всё проверил, сам вынес вердикт.

T — Timely (Своевременный). А вот это, бля, часто пролетает. Написал фичу, выкатил, а про тесты вспомнил через месяц. Потом садишься, смотришь на код и думаешь: "А какого хуя это вообще должно работать?". Пиши тест, пока в голове ещё свежо, а не когда уже всё заросло паутиной.

А теперь, сука, самое вкусное — дополнительные плюшки, без которых тест превращается в говно.

Читаемость, ёпта! Ты открываешь тест, а там такая каша из циклов, условий и вызовов, что волнение ебать, терпения ноль ебать. Используй Arrange-Act-Assert (AAA). Разложил всё по полочкам: подготовил, сделал, проверил. Как рецепт борща — всё понятно даже твоей бабке.

Поддерживаемость. Сегодня кнопка зовётся "Submit", а завтра дизайнер проснулся и переименовал её в "Отправь нахуй". И все твои тесты посыпались. Поэтому — Page Object Model (POM), детка! Всю эту хуйню с селекторами и методами засунул в один класс, а в тесте работаешь с человеческими понятиями: cart_page.open(), catalog_page.add_item(). Поменяли селектор — поправил в одном месте, а не в трёхстах тестах.

Проверяет одну вещь. Не надо в одном тесте проверять, что юзер может залогиниться, добавить товар в корзину, оформить заказ и получить скидку на день рождения твоей собаки. Один тест — одна ответственность. Упал — сразу понятно, где искать пиздец.

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

import pytest

def test_user_can_add_item_to_cart(authenticated_user, clean_cart):
    # Arrange: Щас всё подготовим, чтоб не было сюрпризов
    item = Item(id=123, name="Test Book", price=29.99)
    catalog_page = CatalogPage()
    cart_page = CartPage()

    # Act: Делаем то, что тестируем. Без лишних телодвижений.
    catalog_page.open()
    catalog_page.add_item_to_cart(item.id)
    cart_page.open()

    # Assert: А теперь, сука, проверим, что всё получилось, как задумано.
    cart_items = cart_page.get_items()
    assert len(cart_items) == 1
    assert cart_items[0].name == item.name
    assert cart_items[0].price == item.price

Видишь? Чисто, понятно, без воды. Никакой "магии". Запустил — получил ответ. Вот это и есть качественный автотест, а не эта пиздопроебибна, которую иногда в проектах встречаешь.