Skip to content

6. Продолжаем разрабатывать автотесты

Daniil Shatukhin edited this page Aug 29, 2022 · 2 revisions

Самодокументация кода

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

Для таких случаев есть два вида самодкументирования:

  • Если код являет собой действие, то его необходимо вынести в отдельную функцию;
  • Если код являет собой объект или сущность, то его следует вынести в переменную.

Принцип DRY (Don’t repeat yourself)

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

Варианты создания функции

У нас есть два варианта создать функцию из select. Мы можем передавать селектор параметром, а можем передавать полный элемент.

С помощью элемента:

def select(element: SeleneElement, /, *, option: str):
    element.perform(command.js.scroll_into_view).click()
    browser.all('[id^=react-select-][id*=-option]').element_by(have.exact_text(option)).click()

select(browser.element('#state'), option='Uttar Pradesh')
select(browser.element('#city'), option='Lucknow')

С помощью селектора:

def select_(selector: str, /, *, option: str):
    browser.element(selector).perform(command.js.scroll_into_view).click()
    browser.all('[id^=react-select-][id*=-option]').element_by(have.exact_text(option)).click()

select_('#state', option='Uttar Pradesh')
select_('#city', option='Lucknow')

Модульная парадигма

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

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

Как создать пакет в PyCharm

В главном пакете в корне проекта нажимаем правой кнопкой мыши. Выбираем «New», а затем «Python Package». Пакету даем осмысленное название, которое отражало бы его содержимое и назначение. К примеру, для пакета, в котором находится реализация выбора элементов на странице, можно дать название «controls».

Как создать модуль в пакете

В корне пакета нажимаем правой кнопкой мыши. Выбираем «New», затем «Python File». Также даём осмысленное название. К примеру, мы создаём модуль для работы с селектами, поэтому и называем его «select»

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

from demoqa_tests.controls.select import function_one, function_two

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

Объектно-ориентированная парадигма

У модульно парадигмы есть плюсы, которые помогают навести порядок в коде и сделать его более читаемым. Но есть и минусы, когда к одному пакету обращается слишком много раз и Python приходится запускать по несколько процессов. К примеру, если абстрагироваться и представить, что пакеты, которые мы создаём, представляют собой ящик с инструментами, то в момент работы кода к один ящик пытаются поделить сразу несколько исполнителей. Логично, что одного ящика не хватает сразу нескольким работникам.

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

Как создать класс в Python

К примеру, в коде нашего модуля было следующее:

element: SeleneElement = ...


def add(from_: str, /, *, autocomplete: Optional[str] = None):
    element.type(from_)
    browser.all(
        '.subjects-auto-complete__option'
    ).element_by(have.text(autocomplete or from_)).click()

Если мы переделаем модульную парадигму в объектно-ориентированную, то код будет выглядеть следующим образом:

class TagsInput:
    
    def __init__(self):
        self.element: SeleneElement = ...


def add(self, from_: str, /, *, autocomplete: Optional[str] = None):
    element.type(from_)
    browser.all(
        '.subjects-auto-complete__option'
    ).element_by(have.text(autocomplete or from_)).click()

Как этим пользоваться

Теперь у нас есть фабрика, которая может изготавливать новые ящики с инструментами. К примеру, если нам понадобился новый ящик, то в коде это будет выглядеть следующим образом:

tags_input = TagsInput()

Если понадобится ещё один, то:

tags_input = TagsInput()
tags_input2 = TagsInput()

Содержание
Командная строка
Кодировка UTF-8 в Java
Список полезных книг для автоматизаторов тестирования на языке Java
Список полезных книг для автоматизаторов тестирования на языке Python Структура проекта Github README.md

Java:
1. Вводное занятие. Сразу к практике.
2. Git. GitHub. Погружаемся.
3. Погружаемся в инструментарий и библиотеки
4. Основы Java
5. Продолжаем разрабатывать автотесты. PageObjects
6. JUnit 5
7. Allure Reports
8. Работа с файлами
9. Selenide #1
10. Jenkins. Создаем первую задачу
11. Управляем параметрами в коде и в Jenkins
12. Отправляем уведомления о результатах прохождения автотестов
13. Учимся быстро разрабатывать проекты для тестовых заданий
14. Selenoid
15. Библиотека Owner
16. REST API. Пишем автотесты с Rest assured
17. REST API. Декомпозируем UI тесты. Подключаем отчетность
18. REST API. Продолжаем изучать
19. Мобильная автоматизация #1. Разрабатываем автотесты с Browserstack
20. Allure TestOps
21. Переезд на собственную инфраструктуру Java

Python:
1. Вводное занятие. Сразу к практике!
2. Погружаемся в инструментарий и библиотеки
3. Git. GitHub. Погружаемся.
4. Основы Python
5. Selene #1
6. Основы Python. Часть II
7. Основы Python. Часть III
8. Page Object
9. Allure Reports
10. Работаем с файлами Python
11. Jenkins. Создаем первую задачу и управляем параметрами Python
12. Телеграм бот. Отправляем уведомления о результатах прохождения тестов
13. Pytest
14. Selenoid
15. Pytest. Часть II
16. Venv, Poetry и управление зависимостями проекта
17. REST API. Часть I. Пишем автотесты с Requests
18. REST API. Часть II. Продолжаем изучать
19. Мобильная автоматизация #1. Разрабатываем автотесты с Browserstack
20. Мобильная автоматизация #2. Разрабатываем автотесты с эмулятором Android устройства
21. Allure TestOps
22. Переезд на собственную инфраструктуру Python

Clone this wiki locally