Привет, Хабр! Меня зовут Максим, я инженер по автоматизации тестирования в компании 1221СИСТЕМС и хотел бы поделиться своим опытом и рассказать путь настройки автотестов от минимального рабочего состояния до масштабного проекта. Поделюсь тем, какие инструменты я внедрил для улучшения процессов на нашем проекте.

Это статья для тех, у кого уже есть:

- Базовое понимание python

- Понимание паттернов автоматизации (если пока нет – рекомендую ознакомиться с этой статьей https://habr.com/ru/articles/777262/)
Рекомендую использовать из неё хотя бы следующие паттерны:

  1. Page Object Pattern – для каждой страницы тестируемого приложения создаётся отдельный объект. Сам тест ничего не знает о веб-элементах, он обращается к определённому методу, который работает с нужной страницей.

  2. Steps Pattern – тест разбивается на отдельные шаги, для удобства читаемости и дальнейшей поддержки.

  3. Паттерн проверок (Assert/Checker) – это сравнение ожидаемого и фактического результата, у каждого теста он должен быть.

Для начала, попробуем создать свой первый API / WEB автотест на Python, множество примеров которых можно найти на просторах интернета. В целом, это несложно, можно осилить за полчаса-час.

В нашем примере тест API отправляет GET запрос с ответом 200, а WEB-тест открывает Google-поиск и вписывает в поисковую строку слово «привет».

API Тест

# В блоке импорта добавляем библиотеку requests
import requests

def test_api():
    # Объявляем заголовки
    headers = {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
    # Объявляем url, на который будем отправлять запрос. В данном случае, используем тестовый сервер.
    url = 'https://petstore.swagger.io/v2/user/login'
    # Указываем параметры для будущего запроса на авторизацию
    params = {
        'username': 'kot',
        'password': 'kot'
    }
    # Производим авторизацию на сайте
    response = requests.get(url=url, headers=headers, params=params)
    # Сравниваем фактический код ответа с ожидаемым
    assert response.status_code == 200

WEB Тест

# В блоке импорта добавляем библиотеки
from selenium.webdriver.chrome.service import Service
import time
from selenium import webdriver
from selenium.webdriver.common.by import By

options = webdriver.ChromeOptions()
#TODO В начале нужно скачать chromedriver для вашей версии Chrome и ниже указать путь до него
service = Service("chromedriver.exe")
# Объявляем url, который будем открывать
url = "https://www.google.com/"
driver = webdriver.Chrome(service=service)

try:
    # Открываем заданный сайт
    driver.get(url=url)
    # Ждем 1 секунду, чтобы страница прогрузилась
    time.sleep(1)
    # Впишем в поисковую строку слово «привет»
    element = driver.find_element(By.XPATH, '//textarea[@title="Поиск"]')
    element.send_keys('привет')

finally:
    time.sleep(10)
    print('Все успешно')
    driver.close()
    driver.quit()

В чем проблема таких тестов?

Их очень сложно поддерживать и масштабировать.

Что важно для поддержания тестов и их масштабирования?

  • Использование единого кода в разных местах;

  • При этом изменения в код должны вноситься только в одном месте.

Например, у нас есть 2 теста: первый заходит в поисковик Google и вводит запрос в поисковую строку, а второй – в поисковик Яндекс и делает то же самое. Мы можем вынести метод перехода на страницу (без указания конкретного url) в отдельный файл, на который будем ссылаться в дальнейшем.

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

Рассмотрим инструменты, которые помогают улучшить процессы автоматизации на проекте.

  1. Перед написанием автотестов продумывайте все связи и выстраивайте архитектуру.

    Проект автоматизации – это такой же код, как и в разработке, поэтому чем позже вы вносите изменения, тем больше они будут стоить денег и времени. Конечно, всё сразу предусмотреть невозможно, но с каждым проектом вы набираетесь опыта, который сможете привносить в новые задачи.

  2. Создавайте скрипты подготовки данных для ваших автотестов.

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

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

    При попытке разобраться, почему это произошло, тестировщики порой тратят несколько часов и не могут понять, в чём дело. Решение этой проблемы – создать скрипты для актуализации / создания сущностей, которые будут использовать ваши автотесты. Такой скрипт ищет тестового пользователя по определенному параметру. Если пользователь был изменён, скрипт откатит его к дефолтным значениям, а если не найдёт пользователя совсем – создаст нового с дефолтными данными.

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

  3. Используйте фреймворк Allure

    От любого автоматизатора рано или поздно потребуют отчета о прохождении автотестов. Возникает вопрос: как их представить? Не показывать же код и результаты в IDEA? =)

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

    Моя задача в этой статье – показать, что такой инструмент есть и кратко рассказать о его возможностях.

    1. Аннотация step для описания шагов. Рекомендую использовать её для описания любого действия. Эта информация будет подтягиваться в Allure, и будет легче найти место, где упали тесты.

      Пример кода с использованием step:

      @allure.step('Ввести текст в поле поиска')
      def fill_text_in_search(self, locator, text):
        web_element = self.find_element(locator)
        web_element.send_keys(text)
        return self
      Пример отображение шагов в Allure
      Пример отображение шагов в Allure

    2. Аннотация link. Позволяет прикрепить полезные ссылки для быстрого доступа.

      Пример кода с использованием link

      @allure.link('https://www.google.com/')
      def test_web(self):
        self.APP.habr.go_to_page('https://www.google.com/')
        self.APP.habr.fill_text_in_search('Привет Google')
      Пример отображение ссылки в Allure
      Пример отображение ссылки в Allure


    3. Аннотация screenshot. Без неё не должен обходиться ни один веб-тест, так как именно она показывает нам, что было на экране в момент падения / успешного завершения. В случае падения по такому скриншоту будет гораздо легче определить, в чем заключалась проблема.

      Для подключения этой аннотации в Импортах нужно указать следующий строку:

      from allure_commons.types import AttachmentType

      А также код самого скриншота, чтобы прикрепить его в дальнейшем к Allure:

      allure.attach(self.GetDriver().get_screenshot_as_png(),
                    name="Screenshot", attachment_type=AttachmentType.PNG)
      Пример отображение скриншота в Allure
      Пример отображение скриншота в Allure
  4. Используйте маркеры.

    Mark - aннотация pytest. Маркеры позволяют разбивать ваши тесты по группам, блокам функционала или просто WEB / API.

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

    @allure.title('Тест для Habr')
    @allure.mark.ApiTest
    @allure.mark.Account
    @allure.mark.CRITICAL
      def test(self):
        pass

    Главное, не забудьте вынести ваши маркеры в файл pytest.ini
    Пример ниже:

    markers =
      Account
      ApiTest
      #Приоритет
      CRITICAL
  5. Используйте системы тестовой документации.

    Test IT – одна из таких систем. Конечно, есть и другие, но покажу на её примере, так как мы в работе используем именно её.

    Хорошим тоном считается, если у вас есть система, в которой хранится вся тестовая документация. Через такую систему вы можете создавать тестовые планы или просто объединить скоуп тестов для определенной проверки. Для подключения проекта к системе Test IT вам необходимо вписать в код буквально 6 параметров в отдельном файле connection_config.ini:

    • url

    • privatetoken

    • projectID

    • configurationID

    • adapterMode

    • automaticUpdationLinksToTestCases


    К примеру, если в терминале вашей IDEA запустить команду «pytest --testit», то все ваши тесты запустятся, а результаты отобразятся в Test IT.

    Пример отображения автотестов в Test IT
    Пример отображения автотестов в Test IT

    Через Test IT можно:

    • Классифицировать ошибки падений;

    • Формировать список упавших в прогоне автотестов и запускать их заново;

    • Связывать автотесты с тест-кейсами;

    И еще много разных возможностей. Подробнее – в документации Test IT.

    Дисклеймер! Test IT - платный инструмент. В данной статье я делюсь своим опытом и не рекламирую никакие программы.

  6. Используйте CI / CD инструменты

    Ваши тесты должны запускаться независимо и удалённо (не на локальной машине / сервисе). Я рекомендую ознакомиться с CI / CD инструментами, позволяющими это сделать, заранее, так как у них может отличаться функционал и стоимость.

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

    Могут использоваться следующие варианты:

    • Jenkins

    • GitLab

    • и другие

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

Резюме

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

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

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

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


  1. e_x_z_o
    03.09.2024 13:43

    Очень подробно, спасибо!
    Кстати, у Test IT видела, что недавно был анонс бесплатного тарифа.


    1. BelMaxS Автор
      03.09.2024 13:43

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


  1. Galaxyone
    03.09.2024 13:43

    При импорте библиотеки можешь делать следующим образом:
    import requests as r
    Таким образом, будет короче вызвать метод

    response = r.get(url=url, headers=headers, params=params)


    1. BelMaxS Автор
      03.09.2024 13:43

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


      1. Galaxyone
        03.09.2024 13:43

        Понял) При assert на статус-код советую выводить следующее выражение в конце проверки, чтобы получать конкретную ошибку:

        assert response.status_code == 200, f'Ожидался статус-код 200 ОК, но получен {response.status_code}'

        Также можно сократить, необязательно их уточнять:

        response = requests.get(url, headers, params)

        Ps: в качестве проверки на тело ответа можно валидировать схемы


        1. BelMaxS Автор
          03.09.2024 13:43

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

          2. Пример, который я привожу, я даю в максимально полном формате, чтобы он был понятен всем. А так да, можно сократить.

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

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


        1. Andrey_Solomatin
          03.09.2024 13:43

          А еще можно добавть --showlocals к запуску пайтеста, и не париться с сообщениями.

          Ну и прекращаем использовать магические константы. Тем более что их уже за вас определили. https://docs.python.org/3/library/http.html#http.HTTPStatus


          1. BelMaxS Автор
            03.09.2024 13:43

            Спасибо за информацию!


  1. Andrey_Solomatin
    03.09.2024 13:43

    Вы в реальных тестах действительно используете requests.get ? Или для простоты добавили?

    Обычно когда запросов много, хочется переиспользовать клиента, так как установка соеденения это дорого. https://requests.readthedocs.io/en/latest/user/advanced/#session-objects


    1. BelMaxS Автор
      03.09.2024 13:43

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

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


  1. igorm1r
    03.09.2024 13:43

    Спасибо за подробную статью