Перейти к основному содержимому

Автоматизация тестирования: полное руководство

Основы автоматизации

Преимущества автоматизации тестирования

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

Недостатки автоматизации тестирования

  • Автотесты хрупки к изменениям в коде (любое изменение в UI может «сломать» тест)
  • Автоматизация проверяет только запрограммированные сценарии и не обнаружит дефекты вне их рамок
  • Поддержка большого набора автотестов требует времени и ресурсов – со временем больше усилий уходит на поддержку и анализ результатов, чем на создание новых тестов
  • Не всё можно автоматизировать: например, юзабилити, визуальные аспекты интерфейса, переводы или инсталляцию лучше проверять вручную
  • Начальные вложения в автоматизацию (инструменты, инфраструктура, разработка тестов) могут быть значительными, и выгода проявится только при длительном и мудром использовании автотестов

Критерии выбора тест-кейсов для автоматизации

  • Чтобы определить, что автоматизировать в первую очередь, рекомендуется оценить ROI от каждого теста
  • В приоритет попадают тесты, которые выполняются часто (например, при каждом релизе), критичны для бизнеса или являются ключевыми сквозными сценариями
  • Автоматизировать имеет смысл стабильный функционал, где ожидаемый результат чётко определён и проверка не требует творческого подхода
  • Хорошие кандидаты – регрессионные тесты, дымовые тесты, проверки сложной бизнес-логики на разных наборах данных
  • При отборе важно убедиться, что автоматический анализ результата теста не займёт больше времени, чем ручная проверка, иначе автоматизация теряет смысл

Что не рекомендуется автоматизировать

  • Проверки, требующие субъективной оценки (UI/UX, удобство использования)
  • Разовые сценарии или тесты с трудно предсказуемым результатом (например, новое нестабильное функциональность)
  • Сценарии, где автоматизация технически затруднена или экономически неоправданна – например, ручная проверка может быть быстрее и проще

Фреймворки и подходы к автоматизации

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

Page Object Model (Page Object)

Page Object – это шаблон проектирования, при котором каждая страница приложения или важный экран представляется в тестовом коде как отдельный объект (класс) с методами для взаимодействия с элементами UI.

Суть паттерна:

  • Создание уровня абстракции, отделяющего сами тесты от деталей расположения элементов
  • Тесты обращаются к методам Page Object, а внутри этих методов инкапсулирована логика поиска элементов на странице
  • Это изолирует изменения в интерфейсе: если разработчики изменили локаторы или структуру страницы, достаточно поправить Page Object, и все тесты снова заработают
  • Такой подход повышает читаемость тестов (они выглядят как последовательность действий пользователя) и снижает дублирование кода

Инструменты: Page Object широко используется во всех веб-фреймворках автоматизации – например, при работе с Selenium WebDriver (на любом языке) это де-факто стандарт. Библиотеки вроде Selenide (Java) или Cypress (JS) также поощряют использование Page Object. В мобильном тестировании Page Object применяется в связке с Appium, Espresso, XCUITest и даже в BDD-фреймворках, интегрируясь со SpecFlow/Cucumber.

Data-Driven Testing (DDT) – тестирование, управляемое данными

В этом подходе тестовые данные отделены от тестовых сценариев.

Принцип работы:

  • Сам тестовый скрипт универсален и способен принять на вход набор параметров
  • Различные наборы данных хранятся вне кода (например, в таблицах, CSV/Excel файлах, базе данных)
  • Один и тот же тест прогоняется с разными входными данными и проверяет соответствующие ожидаемые результаты
  • Это позволяет покрыть множество вариаций ввода без копирования кода
  • Например, вместо написания 1000 однотипных тестов для проверки поля ввода на разных значениях, можно иметь один тест и таблицу из 1000 строк данных

Инструменты: Подход DDT поддерживается во многих фреймворках:

  • В Java можно использовать JUnit/TestNG (аннотации @ParameterizedTest или DataProvider) для подачи данных в тесты
  • В .NET аналог – NUnit/XUnit с [TestCase]-атрибутами
  • Специализированные средства, такие как Katalon Studio, позволяют привязывать внешние файлы данных (Excel, CSV) к тест-кейсу для параметризации
  • Даже Postman/Newman поддерживает запуск одного теста API с разными наборами данных (например, через CSV)
  • Data-Driven подход часто комбинируется с Page Object и другими фреймворками для проверки одинаковой логики на разных данных

Keyword-Driven Testing (KDT) – тестирование, управляемое ключевыми словами

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

Принцип работы:

  • Ключевые слова представляют бизнес-действия (нажатие кнопки, ввод текста, переход на страницу и т.п.)
  • Тест создаётся как последовательность таких слов
  • За каждым ключевым словом скрыта реализация (код), выполняющая соответствующее действие
  • Главная идея – отделить написание логики теста от программирования
  • Специалисты без навыков кода могут составлять тесты из готовых «слов» в таблице (например, Excel) или специальном инструменте
  • Инженеры автоматизации реализуют сами эти слова в коде один раз

Инструменты:

  • Исторически подход KDT реализован в таких продуктах, как HP/Micro Focus UFT (QTP) – там сценарий можно составлять из действий в таблице
  • Популярный open-source инструмент – Robot Framework, где тесты пишутся на простом текстовом языке ключевых слов, а под капотом для них определяются keywords-библиотеки
  • Robot Framework содержит готовые библиотеки для Selenium, API и др., и позволяет расширять набор ключевых слов на Python или Java
  • Katalon Studio также поддерживает keyword-driven подход: он предоставляет множество встроенных кейвордов (например, WebUI.click() для клика, WS.sendRequest() для API) и позволяет создавать свои
  • KDT-фреймворк требует наличие двух слоёв – набора файлов/таблиц с последовательностями ключевых слов (тестов) и соответствующей реализации действий (функций), вызываемых по этим ключам

BDD (Behavior-Driven Development) и BDD-фреймворки

BDD – это методология разработки через поведение, расширение идей TDD. В контексте автоматизации тестирования BDD позволяет писать проверки на понятном языке в форме пользовательских сценариев.

Принцип работы:

  • Тесты BDD оформляются как истории и сценарии на языке Gherkin: Given/When/Then (Дано/Когда/То)
  • Шаги описаны почти естественным языком, понятным и бизнес-аналитикам, и тестировщикам, и разработчикам
  • Пример сценария: «Дано: пользователь открыт страницу авторизации; Когда: он вводит верный логин и пароль; Тогда: происходит вход в систему и отображается главная страница.»
  • Каждый такой шаг затем связан с автоматическим исполнением – разработчики пишут step definitions (методы на языке программирования), которые запускаются для шагов сценария

Инструменты:

  • Наиболее известный BDD-фреймворк – Cucumber
  • Он поддерживает множество языков (Java, JavaScript, Ruby, Python и др.): сценарии пишутся в файлах .feature на языке Gherkin, а шаги реализуются, например, на Java (с аннотациями @Given, @When, @Then)
  • Для платформы .NET аналогичным образом работает SpecFlow – фактически «Cucumber для C#»
  • BDD-фреймворки интегрируются с тест-рушами (JUnit, NUnit, etc.) для запуска
  • Применение BDD удобно там, где требуется согласование тестов с требованиями: описание сценариев может служить живой документацией

Пример фрагмента сценария на Gherkin и соответствующий шаг в Cucumber:

Сценарий: Успешная авторизация
Дано пользователь на странице входа
Когда он вводит корректные учетные данные
Тогда отображается сообщение "Welcome!"
@When("^он вводит корректные учетные данные$")
public void enterCredentials() {
// шаг: ввод логина и пароля, нажать кнопку входа
}

Таким образом, BDD обеспечивает общий язык для всех участников разработки и тестирования, а фреймворки Cucumber/SpecFlow выполняют связующую роль между текстом сценария и кодом автотеста.

Практические примеры

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

Автоматизация тестирования веб-приложений

Selenium WebDriver (Java)

Selenium – один из самых популярных инструментов для UI-тестирования веб-приложений. Он управляет браузером, имитируя действия пользователя. Ниже показан простой тест на Java: открываем страницу Google Accounts и проверяем заголовок страницы:

WebDriver driver = new FirefoxDriver();
driver.get("https://accounts.google.com");
// Ожидаемый заголовок страницы:
String expectedTitle = "Sign in - Google Accounts";
String actualTitle = driver.getTitle();
// Проверяем соответствие заголовка:
if (expectedTitle.equals(actualTitle)) {
System.out.println("Title is correct");
} else {
System.out.println("Title is incorrect");
}
driver.quit();

В этом скрипте driver.get() открывает браузер и переходит по заданному URL. Затем с помощью driver.getTitle() получаем заголовок текущей страницы и сравниваем его с ожидаемым значением. По результату выводится сообщение об успехе или неудаче. В реальных тестах вместо System.out.println обычно используются assertions (например, assertEquals), чтобы автоматически отмечать тест пройденным или проваленным.

Cypress (JavaScript)

Cypress – современный фреймворк для автоматизации фронтенда, который работает непосредственно в браузере. Он использует синтаксис JavaScript + Mocha. Пример теста на Cypress:

describe('Home Page', () => {
it('должна успешно загрузиться', () => {
cy.visit('https://your-website.com');
cy.contains('Welcome to your-website');
});
});

Здесь cy.visit() открывает указанную страницу в браузере, а cy.contains() проверяет наличие на странице текста "Welcome to your-website". Мы описываем набор тестов в блоке describe и отдельный тест с помощью it. Cypress автоматически ждёт загрузки страницы и появления элементов, поэтому дополнительные ожидания не нужны – если текст не появится, последний шаг упадёт, отмечая тест не пройденным.

Cypress также предоставляет множество команд для взаимодействия с элементами, например: cy.get('input[name="username"]').type('testuser') для ввода текста, cy.get('button[type="submit"]').click() для клика по кнопке, и удобные ассерт-шорткаты вроде cy.url().should('include', '/dashboard') для проверки URL. Все такие команды выполняются последовательно, Cypress сам синхронизирует их с состоянием страницы.

Playwright (TypeScript/JavaScript)

Playwright – еще один мощный инструмент для веб-автотестов от Microsoft. Он поддерживает JavaScript/TypeScript, Python, .NET, Java. Пример на TypeScript (с использованием встроенного тест-раннера Playwright):

import { test, expect } from '@playwright/test';

test('Проверка заголовка документации Playwright', async ({ page }) => {
await page.goto('https://playwright.dev/');
await page.getByRole('link', { name: 'Get started' }).click();
await expect(page).toHaveTitle(/Playwright/);
});

В этом тесте сначала открывается главная страница Playwright, затем выполняется клик по ссылке "Get started" (по тексту ссылки), после чего с помощью ассерции expect(...).toHaveTitle(/Playwright/) проверяется, что заголовок страницы содержит слово "Playwright". Playwright автоматически ждёт, когда страница загрузится и заголовок обновится, поэтому этот ассерт надёжно подтвердит переход на страницу «Get Started». В Playwright доступны и другие проверки: например, expect(page).toHaveURL('...'), expect(locator).toHaveText('...') и т.д., а также удобные методы для нахождения элементов (page.locator, page.getByRole и др.). Этот фреймворк, как и Cypress, выполняет тесты очень быстро и обладает встроенной поддержкой ожиданий (auto-wait).

Автоматизация мобильного тестирования

Appium (Android, iOS)

Appium – кроссплатформенный фреймворк для мобильных UI-тестов. Он позволяет одним кодом управлять и Android-, и iOS-приложениями, используя под капотом соответствующие автоматоры (UIAutomator/Espresso для Android, XCUITest для iOS). Ниже код теста на Java, который проверяет работу стандартного приложения Калькулятор на Android:

DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("platformName", "Android");
caps.setCapability("deviceName", "Emulator");
caps.setCapability("appPackage", "com.android.calculator2");
caps.setCapability("appActivity", "com.android.calculator2.Calculator");
// Запуск приложения через Appium:
WebDriver driver = new RemoteWebDriver(
new URL("http://127.0.0.1:4723/wd/hub"), caps);
// Нажимаем 2 + 4 = :
WebElement two = driver.findElement(By.name("2"));
WebElement plus = driver.findElement(By.name("+"));
WebElement four = driver.findElement(By.name("4"));
WebElement equals = driver.findElement(By.name("="));
two.click(); plus.click(); four.click(); equals.click();
// Проверяем, что результат равен 6:
WebElement result = driver.findElement(By.tagName("EditText"));
assert result.getText().equals("6");
driver.quit();

Здесь сначала через DesiredCapabilities задаются параметры устройства и приложения: платформа Android, имя устройства (эмулятора), пакет и главное Activity калькулятора. Затем создаётся RemoteWebDriver, указывающий адрес запущенного сервера Appium. Далее с помощью driver.findElement(By.name("...")) находим кнопки калькулятора по отображаемому имени и кликаем по ним в нужной последовательности. Получив элемент с результатом (тег EditText – поле вывода), проверяем его текст. По завершении driver.quit() закрывает приложение и сессию Appium. Этот же код легко адаптируется под iOS, стоит лишь поменять capabilities (например, platformName на iOS и задать bundleId приложения вместо пакета).

Espresso (Android)

Espresso – фреймворк из Android SDK для написания UI-тестов нативных Android-приложений. Тесты на Espresso пишутся на Java или Kotlin и выполняются в контексте приложения (как Instrumentation-тесты). Пример теста на Espresso (Java):

@Test
public void greeterSaysHello() {
onView(withId(R.id.name_field)).perform(typeText("Steve"));
onView(withId(R.id.greet_button)).perform(click());
onView(withText("Hello Steve!")).check(matches(isDisplayed()));
}

В этом примере имитируется ввод текста "Steve" в текстовое поле с id = name_field, затем нажимается кнопка с id = greet_button. После этого с помощью onView(withText("Hello Steve!")) получаем элемент, содержащий строку "Hello Steve!" – ожидаемое приветствие – и методом .check(matches(isDisplayed())) проверяем, что этот элемент отображается на экране (то есть приветствие появилось). Espresso автоматически синхронизирует действия с UI-потоком приложения: вызов perform(click()) дождётся, пока кнопка станет доступна, а check(matches(...)) – пока UI обновится после предыдущих действий. Таким образом, тест получится надёжным и не будет "флапать" из-за асинхронности.

Espresso предоставляет богатый API для UI-тестов Android: можно искать view по withId, withText, по содержимому, комбинировать матчера (allOf и т.п.), а также выполнять сложные сценарии (прокрутка списков, навигация между Activity, проверка Toast-сообщений и др.). Поскольку Espresso требует доступа к коду приложения, обычно им пользуются мобильные разработчики или автоматизаторы, работающие с проектом Android (в отличие от Appium, который подходит и для black-box тестирования без доступа к исходникам).

XCTest / XCUITest (iOS)

Для автоматизации тестирования iOS-приложений Apple предоставляет фреймворк XCTest. Он же с дополнениями (XCUITest) используется для UI-тестирования на устройствах iPhone/iPad. Тесты пишутся на Swift или Objective-C в Xcode. Рассмотрим фрагмент UI-теста на Swift, который проверяет сценарий логина в приложении:

func testLoginFlow() {
let email = app.textFields["email"]
email.tap()
email.typeText("cmecid@gmail.com")

let pwd = app.secureTextFields["password"]
pwd.tap()
pwd.typeText("pwd")

app.switches["rememberMe"].tap()
app.buttons["login"].tap()

let message = app.staticTexts["Hello World!"]
XCTAssertTrue(message.waitForExistence(timeout: 5))
}

Здесь используется объект app (экземпляр XCUIApplication), представляющий тестируемое приложение. Тест находит текстовые поля по Accessibility Identifier (в квадратных скобках указываются идентификаторы элементов: "email", "password"), симулирует ввод текста в поля (tap() сфокусирует поле, затем typeText введёт строку), переключает тумблер "rememberMe" и нажимает кнопку входа "login". После этого проверяется наличие некого текстового элемента с надписью "Hello World!" – для этого вызывается waitForExistence(timeout: 5), ожидая до 5 секунд появления элемента, и XCTAssertTrue(...exists) для проверки, что элемент появился. (В данном случае "Hello World!" – это ожидаемое сообщение на следующем экране после логина).

XCTest тесты интегрируются в Xcode: их можно запускать на симуляторе или реальном устройстве. Фреймворк предоставляет методы для большинства пользовательских действий: tap(), typeText(), жесты свайпа и прокрутки, запуск приложения app.launch(), завершение app.terminate() и т.п. Локаторы в XCUITest строятся на основе Accessibility (как видно, используются идентификаторы строковые). Если они не заданы в приложении, можно применять поиск по типу элемента, иерархии или координатам, но это менее надежно. Обычно разработчики добавляют Accessibility Identifier для важных элементов, чтобы упростить автоматизацию.

Автоматизация API тестирования

REST Assured (Java)

REST Assured – это библиотека для тестирования REST API на Java. Она позволяет писать запросы и проверки ответа в «читаемом» стиле, используя Given/When/Then конструкцию (флюентный интерфейс). Пример API-теста с REST Assured:

given()
.baseUri("http://ergast.com/api/f1")
.when()
.get("/2017/circuits.json")
.then()
.assertThat()
.statusCode(200)
.and().contentType(ContentType.JSON)
.and().header("Content-Length", equalTo("4567"));

В этом коде мы выполняем GET-запрос к REST API (эндинг /2017/circuits.json) и сразу проверяем несколько условий для ответа. А именно: HTTP статус должен быть 200 OK (statusCode(200)), тип содержимого – JSON (contentType(JSON)), и заголовок Content-Length равен "4567". Такие проверки можно комбинировать цепочкой .and(), как показано выше, улучшая читаемость. Кроме заголовков и статуса, REST Assured умеет проверять и тело ответа, используя синтаксис Hamcrest-матчеров. Например, мы могли бы дописать: .body("MRData.CircuitTable.Circuits.circuitId", hasSize(20)) – это проверка на основе JSON Path, что в ответе поле Circuits.circuitId содержит 20 элементов. Библиотека автоматически парсит JSON или XML ответ, и позволяет удобно проверять вложенные поля (equalTo для значений, hasItem для содержимого списков, greaterThan/lessThan для чисел и т.п.). Благодаря лаконичности синтаксиса, тесты API на REST Assured получаются компактными и понятными.

Postman (тестовые скрипты)

Postman – популярный инструмент для ручного тестирования API, но у него есть мощный функционал автоматизации в виде тестовых скриптов. После выполнения запроса в Postman можно запускать JavaScript-код во вкладке Tests (Post-response), который будет проверять ответ. Этот код пишется с использованием библиотеки pm (Postman) и assertion-библиотеки Chai. Рассмотрим примеры тестов на Postman-скрипте:

pm.test("Код ответа 200", function () {
pm.response.to.have.status(200);
});
pm.test("Ответ вернул правильное имя", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.firstname).to.eql("Mark");
});
pm.test("Депозит оплачен", function () {
pm.expect(jsonData.depositpaid).to.be.true;
});

Первый тест проверяет, что код ответа равен 200 (ОК). Второй выполняет парсинг JSON-ответа (pm.response.json()) и сравнивает значение поля firstname с ожидаемым значением "Mark". Третий убеждается, что поле depositpaid истинно (true). Эти примеры показывают, как в Postman можно последовательно проверять и статус, и содержимое ответа.

В Postman доступны и другие методы: например, pm.response.text() – получить тело ответа как текст и проверить через pm.expect(...).to.include("substring") наличие подстроки, или pm.response.headers – доступ к заголовкам. Можно использовать переменные окружения (pm.environment.get("...")) и даже писать сложную логику (циклы, условия) для валидации. Postman-скрипты позволяют быстро автоматизировать проверки прямо в UI Postman, а затем их можно объединять в коллекции и запускать через Newman (CLI) или CI/CD. Однако для масштабной автоматизации (большое количество тестов, версионирование) часто предпочитают кодовые решения (как REST Assured или специализированные фреймворки), интегрируя их в тестовый проект.

Katalon Studio (кейс API)

Katalon Studio – это комплексный инструмент, который позволяет автоматизировать тестирование API без написания большого объема кода, используя удобный рекордер и встроенные кейворды. Тем не менее, под капотом Katalon использует скрипты на Groovy/Java, и можно писать проверки вручную. Пример скрипта теста API в Katalon (Groovy):

import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS

def response = WS.sendRequest(findTestObject('API/Users/GetUser')) // выполнить GET запрос
WS.verifyResponseStatusCode(response, 200) // проверить статус 200
WS.verifyElementPropertyValue(response