Основы JavaScript для QA: синтаксис, функции и асинхронное программирование
Основы JavaScript для QA: синтаксис, функции и асинхронное программирование
Добро пожаловать в курс «Автоматизация тестирования на JavaScript». Это первая статья нашего цикла, и мы начнем с фундамента. Почему именно JavaScript? Ответ прост: это язык веба. Если вы тестируете веб-приложения, знание JS позволяет вам не только писать автотесты, но и понимать, как работает приложение «под капотом».
Современные инструменты автоматизации, такие как Cypress, Playwright и Puppeteer, используют JavaScript (или TypeScript) как основной язык. Поэтому, прежде чем мы начнем кликать по кнопкам браузера с помощью кода, нам нужно научиться говорить на этом языке.
Переменные и типы данных
Любая программа начинается с хранения данных. В JavaScript для этого используются переменные. Представьте переменную как коробку, на которую вы наклеили этикетку с именем. В эту коробку можно положить значение.
Объявление переменных
В современном JavaScript (стандарт ES6 и новее) мы используем два ключевых слова для создания переменных:
let— для переменных, значение которых может меняться.const— для переменных, значение которых задается один раз и не может быть переназначено.
let userName = "Alice";
userName = "Bob"; // Это нормально, имя изменилось
const url = "https://google.com";
url = "https://yandex.ru"; // Ошибка! Константу нельзя менять
В автоматизации мы часто используем const для селекторов элементов или конфигурационных данных, которые не должны меняться в процессе выполнения теста.
Основные типы данных
JavaScript — язык с динамической типизацией. Это значит, что вам не нужно указывать тип переменной при её создании, язык определит его сам.
Вот основные типы, с которыми вы столкнетесь:
- String (Строка): Текст, заключенный в кавычки.
const message = "Test passed"; - Number (Число): Любые числа (целые и дробные).
let timeout = 5000; - Boolean (Булево значение): Истина или ложь.
let isVisible = true; - Null: Специальное значение, означающее «ничего» или «пусто».
let error = null; - Undefined: Значение переменной, которая была объявлена, но ей ничего не присвоили.
В JavaScript есть старое ключевое слово
var, но в современной разработке и автоматизации его использование считается плохой практикой из-за особенностей области видимости. Используйте толькоletиconst.
Объекты и массивы
Часто данные приходят к нам в более сложных структурах.
Объект (Object) — это коллекция пар «ключ-значение». В тестах объекты часто используются для описания тестовых данных или конфигураций.
const user = {
username: "tester01",
password: "123456",
isAdmin: false
};
console.log(user.username); // Выведет: tester01
Массив (Array) — это упорядоченный список данных. Например, список найденных элементов на странице.
const browsers = ["Chrome", "Firefox", "Safari"];
console.log(browsers[0]); // Выведет: Chrome (нумерация с нуля)
Операторы сравнения
В тестах мы постоянно что-то сравниваем: ожидаемый результат с фактическим. В JavaScript есть важный нюанс при сравнении.
==(нестрогое равенство): сравнивает значения, приводя их к общему типу.===(строгое равенство): сравнивает и значения, и типы данных.
Пример:
console.log(5 == "5"); // true (строка "5" превратилась в число 5)
console.log(5 === "5"); // false (разные типы: число и строка)
Золотое правило QA: Всегда используйте строгое сравнение ===. Это убережет вас от неожиданных ошибок, когда тест проходит, хотя типы данных не совпадают.
Функции
Функция — это блок кода, который можно выполнять многократно. В автоматизации функции помогают нам переиспользовать код, например, функцию логина в систему.
Классическое объявление
function login(login, password) {
console.log("Вход пользователя " + login);
// Логика входа
}
Стрелочные функции (Arrow Functions)
В современном JS чаще используется более лаконичный синтаксис — стрелочные функции. Они особенно популярны в таких фреймворках, как Mocha, Jest или Playwright.
const login = (login, password) => {
console.log("Вход пользователя " + login);
};
Если функция состоит из одной строки и возвращает значение, можно писать еще короче:
const sum = (a, b) => a + b;
Асинхронность: главный камень преткновения
Это самая сложная, но самая важная тема для автоматизатора. Веб-браузеры работают асинхронно. Когда вы просите браузер открыть страницу или нажать кнопку, это действие происходит не мгновенно.
Синхронный vs Асинхронный код
Представьте, что вы в кофейне.
- Синхронный подход: Вы заказываете кофе и стоите у кассы, глядя на бариста, пока он не нальет напиток. Вы не можете отойти, проверить телефон или поговорить с другом. Весь процесс заблокирован, пока кофе не будет готов.
- Асинхронный подход: Вы заказываете кофе, вам дают пейджер (бипер) и вы идете за столик. Вы можете читать книгу или говорить по телефону. Когда кофе готов, пейджер пищит, и вы забираете заказ.
В JavaScript операции, такие как «загрузить страницу» или «найти элемент», подобны заказу кофе. Если бы они были синхронными, браузер бы «зависал» при каждом клике.
Promise (Обещание)
В JS результатом асинхронной операции является объект Promise (Промис). Это тот самый «пейджер» из кофейни. Промис может находиться в трех состояниях:
- Pending (Ожидание): Запрос отправлен, ждем результат.
- Resolved (Выполнено): Операция успешна (кофе готов).
- Rejected (Отклонено): Произошла ошибка (кофемашина сломалась).
Async / Await
Раньше для работы с промисами использовали цепочки .then(), но этот код было трудно читать. Современный стандарт ввел ключевые слова async и await, которые делают асинхронный код похожим на синхронный.
async— ставится перед объявлением функции. Говорит о том, что внутри функции будет асинхронность.await— ставится перед вызовом асинхронной операции. Он говорит интерпретатору: «Подожди, пока этот промис не выполнится, прежде чем идти дальше».
Пример теста на псевдокоде:
// Объявляем асинхронную функцию теста
const runTest = async () => {
console.log("Начинаем тест");
// Ждем, пока браузер откроется
await browser.open("https://example.com");
// Ждем, пока найдем кнопку и кликнем по ней
await browser.click("#login-button");
console.log("Тест завершен");
};
Если убрать await, код попытается кликнуть по кнопке еще до того, как браузер успеет открыть сайт. Это приведет к ошибке Element not found.
Условные конструкции и циклы
Для управления потоком выполнения теста нам нужны условия и циклы.
If / Else
Используется для проверки условий. Например, если элемент виден — кликнуть, иначе — сделать скриншот.
if (isVisible) {
clickElement();
} else {
takeScreenshot();
}
Циклы
Циклы полезны, когда нужно обработать список элементов (например, проверить, что все товары в корзине имеют цену).
Самый популярный цикл для работы с массивами — for...of:
const prices = [100, 200, 300];
for (const price of prices) {
if (price > 0) {
console.log("Цена корректна: " + price);
}
}
Заключение
Мы разобрали базовые кирпичики JavaScript, необходимые для старта в автоматизации:
- Переменные (
let,const) хранят данные. - Типы данных определяют, с чем мы работаем (строки, числа, объекты).
- Функции (особенно стрелочные) группируют логику.
async/awaitпозволяют управлять временем выполнения команд в браузере.
В следующей статье мы перейдем к настройке окружения: установим Node.js и напишем наш первый скрипт, который запускается вне браузера.