Alexey QA note @dev_qa Channel on Telegram

Alexey QA note

@dev_qa


Всем привет
🔍 Я AQA инженер
🎤 Выступаю на конференциях и митапах
👥 Делаю митап от сообщества в Москве @moscowqa
✍️ Делюсь своими наработками и заметками и интересными статьями

Вопросы или предложения: @alexey_qa

Alexey QA note (Russian)

Здравствуйте, друзья! 🕵️ Я QA инженер из самолета ✨ Вашего внимания представляется канал от пользователя @dev_qa. Кто это такой? Что это за канал? Alexey QA note - это канал, где QA инженер по имени Алексей делится своими заметками, наработками и интересными статьями. Он также выступает на конференциях и митапах, делая митап от сообщества в Москве @moscowqa. Если у вас есть вопросы или предложения, вы всегда можете обратиться к нему по юзернейму @alexey_qa. Присоединяйтесь к каналу, чтобы быть в курсе последних новостей и разработок в области QA тестирования! 🧐

Alexey QA note

13 Nov, 15:35


🤓 Всем привет!
Октябрь и ноябрь выдался на события⬇️
Организовали непростой митап с РТК ИТ

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

Выступил с докладом на SQA Days про то, как меняется код QA-инженера в зависимости от грейда

Организовали MoscowQA с VK Tech


Планы на оставшийся ноябрь также грандиозные:
📌 еду на любимую фронтовую конференцию HolyJs, если успею подготовить доклад, выступлю на открытом микрофоне.

📌 после Holy выступаю с докладом на митапе Qaчественое общение про репортеры в playwright

📌 на следующей неделе в книжном клубе сообщества MoscowQA будем обсуждать книгу «Принципы юнит-тестирования». Подробности на канале сообщества. Подписывайтесь, если хотите участвовать в мероприятиях и митапах MoscowQA😎

📌 в ближайшее время планирую запустить свой подкаст. И даже записал первый выпуск🤓 Но чтобы анонсировать, хочу иметь в запасе 4 выпуска🤠
Какие темы было бы интересно поднять?

#breakingnews

Alexey QA note

07 Oct, 08:39


Основные функциональные пакеты
Наконец, мы подходим к основным пакетам #Playwright, которые содержат всю главную функциональность проекта.
✳️playwright-core/
✳️playwright-test/
✳️playwright/
✳️protocol/

Обратите внимание, что папка playwright-test — это просто обёртка для связывания playwright-core и playwright вместе в пакете @playwright/test, устанавливаемом через npm. Если вы посмотрите в файл index.js, вы увидите только экспорт из playwright/test, который находится в пакете playwright.

Другой пакет, на который стоит обратить внимание, — это protocol, который содержит автоматически сгенерированный код через некоторые скрипты сборки в директории utils корневой директории проекта Playwright. Он содержит YAML-файл protocol.yml, который перечисляет все интерфейсы, используемые протоколом Playwright. Если вы когда-либо захотите создать драйвер для Playwright на другом языке, это один из основных файлов, к которому стоит обратиться при создании этой библиотеки.

Теперь два основных пакета всей библиотеки Playwright — это playwright и playwright-core. Первый из них является обёрткой вокруг playwright-core и отвечает за управление всей логикой тестирования. Это включает запуск рабочих процессов тестирования, выполнение тестов, отчёты о результатах, управление повторными запусками и утверждениями тестов. Хорошим ориентиром для кода, содержащегося в этом пакете, является любая конфигурационная логика, которую вы найдёте в файле playwright.config.ts, или любой связанный с запуском тестов код, например:
// my-test.spec.ts
import { test } from "@playwright/test";

В этом случае вы, вероятно, импортируете код из пакета playwright.

Другой основной пакет — playwright-core, который содержит всю функциональность автоматизации браузера. Эта функциональность разделена на два основных компонента: клиентскую библиотеку и серверную библиотеку. Серверная библиотека, находящаяся в packages/playwright-core/src/server, содержит всю логику, отвечающую за действия автоматизации браузера. Это означает, что она отправляет команды через Chrome DevTools Protocol (CDP) или аналогичные протоколы, чтобы сообщить браузеру выполнить такие действия, как "нажать кнопку входа", "ввести 'Hello' в текстовое поле" или "перейти на 'https://news.ycombinator.com'". Серверная библиотека содержит реализации для каждого из поддерживаемых браузеров и предоставляет унифицированный API через WebSocket-сервер для доступа к этой функциональности из других процессов.

С другой стороны, клиентская библиотека содержит все пользовательские API, которые вы используете при написании скриптов автоматизации браузера. Например, если у вас есть такой скрипт:
// my-automation-script.ts
import { chromium } from "@playwright/test";

(async function () {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto("https://playwright.dev");
})();


Вы фактически импортируете chromium из экземпляра класса в playwright-core/client/playwright.

Затем вызовы browser.newPage и page.goto делают запросы к интерфейсам в серверной библиотеке, которая взаимодействует с браузерами через CDP или аналогичные протоколы. Это означает, что если вы когда-либо захотите написать собственный инструмент автоматизации браузера, независимый от конкретного браузера, полезной отправной точкой будет использование серверной библиотеки из пакета playwright-core, поскольку она предоставляет всесторонний и проверенный API для такой функциональности.

Такой принцип разделения ответственности работает хорошо, потому что позволяет поддерживать несколько языков, которые могут использовать API автоматизации браузера Playwright. Фактически, если вы посмотрите на другие реализации библиотеки Playwright, вы обнаружите те же шаблоны проектирования (например, ChannelOwner), что и в клиентской библиотеке, найденной в playwright-core.

Перевод

Еще интересные статьи про архитектуру playwright:
➡️https://qacomet.com/playwright/how-playwright-initializes/
➡️https://medium.com/@divyarajsinhdev/understanding-playwright-architecture-e456fcee0222

Полезно? Ставьте 👍 👎

Alexey QA note

07 Oct, 08:39


Архитектура playwright🏠

Когда ты работаешь с инструментом важно исследовать его внутренности и понимать как он работает
Давайте разберем playwright

Корневая директория📝
В корневой директории мы находим следующие папки:
🌸playwright/
🌸browser_patches/
🌸docs/
🌸examples/
🌸packages/
🌸tests/
🌸utils/

А также файл package.json, который включает следующие ключи:
{
"name": "playwright-internal",
"private": true,
"workspaces": ["packages/*"]
}


Файл package.json намекает, что основная функциональность находится внутри директории packages/, поскольку корневой файл помечен как private, имеет в названии "internal" и использует ключ "workspaces", который сообщает Node.js, что проект имеет несколько пакетов. Давайте быстро рассмотрим другие директории верхнего уровня перед тем, как углубиться в папку packages/👇

✳️browser_patches — эта папка содержит патчи для браузеров, добавляющие дополнительные элементы управления и функции к некоторым движкам браузеров, используемых в этом проекте. Интересно, что здесь есть патч для WebKit, позволяющий ему работать на Windows.
✳️ docs — папка docs содержит файлы Markdown, которые компилируются в документацию, представленную на сайте Playwright.
✳️ examples — здесь находятся примеры тестовых скриптов, к которым можно обратиться при начале работы с проектом Playwright.
✳️ tests — даже библиотеки для тестирования должны иметь автоматизированные тесты, которые написаны с использованием Playwright.
✳️ utils — директория utils содержит различные инструменты, используемые во время сборки, Docker-образы, функциональность для Azure, генератор файлов типов и многое другое.

Директория packages✏️
Директория packages содержит более 20 отдельных пакетов, что усложняет понимание. Мы разделим этот список на понятные категории.

Пакеты для отчётности и генерации тестов
Playwright содержит множество различных пакетов для отчётности о тестах, каждый со своим набором функций. Кратко, список пакетов в этой категории:
✳️html-reporter/
✳️recorder/
✳️trace-viewer/
✳️trace/
✳️web/

Эти пакеты содержат код, связанный с обработкой отчётов о тестах или их генерацией с помощью пакета recorder. Кроме того, есть trace и trace-viewer, которые могут записываться во время выполнения тестов Playwright. Пакет web/ предоставляет утилиты, общие для различных веб-инструментов, перечисленных здесь.

Пакеты, специализированные для браузеров
Каждый из этих пакетов просто экспортирует пакет playwright-core вместе со скриптом установки только для соответствующего браузера. Вы можете найти их на npmjs, например, playwright-chromium — это отдельный пакет, который имеет Playwright, специализированный только для автоматизации Chromium.
✳️ playwright-chromium/
✳️ playwright-firefox/
✳️ playwright-webkit/

Пакеты для установки браузеров
Эти пакеты включают только скрипты установки для каждого из браузеров. Например, playwright-browser-chromium соответствует пакету @playwright/browser-chromium на npmjs.
✳️playwright-browser-chromium/
✳️playwright-browser-firefox/
✳️playwright-browser-webkit/

Пакеты для тестирования компонентов
Эти пакеты связаны с экспериментальной системой тестирования компонентов в Playwright. Они предоставляют функциональность, аналогичную тому, как Jest может рендерить отдельные компоненты для разных библиотек.
✳️playwright-ct-core/
✳️playwright-ct-react/
✳️playwright-ct-react17/
✳️playwright-ct-solid/
✳️playwright-ct-svelte/
✳️playwright-ct-vue/
✳️playwright-ct-vue2/

Alexey QA note

05 Oct, 09:26


Автоматизация тестирования:
#automation
#playwright
#cypress
#selenium

Инструменты:
#tools
#postman
#k6
#grafana

Процессы тестирования:
#process
#agile
#TDD
#BDD

Обучение и рекомендации:
#learning
#recommendation
#books

Практики:
#practices
#cleanСode
#unitTests

Общие темы и тренды:
#trends
#updates

Alexey QA note

25 Sep, 10:57


😉Заключение:
Правильное использование noWaitAfter помогает создавать быстрые и надёжные тесты, оптимизируя время ожидания в зависимости от типа действия.

Источник

Было полезно? Ставьте 👍 👎

Теги: #playwright #tools #testing

Alexey QA note

25 Sep, 10:57


Тестирование с параметром noWaitAfter в Playwright🕐

Параметр noWaitAfter в Playwright позволяет настроить, как обрабатываются действия, такие как клики по ссылкам, отправка форм или запуск сетевых запросов. Он определяет, должен ли Playwright ждать завершения вызванного события (навигации или перехода на другую страницу) перед тем, как перейти к следующему шагу.
➡️ noWaitAfter: false (по умолчанию): Playwright ждёт завершения действия перед переходом к следующему шагу.
➡️ noWaitAfter: true: Playwright немедленно переходит к следующему шагу, даже если действие ещё не завершено.

Сценарии использования:
💙 noWaitAfter: true в обработчиках локаторов
С версии Playwright 1.44 параметр noWaitAfter: true можно использовать с обработчиками локаторов. Это особенно полезно при работе с оверлеями или другими элементами, которые могут мешать выполнению действий.
test('Закрытие оверлея с noWaitAfter: true', async ({ page }) => {
await page.goto('http://localhost:3000');

// Локатор для оверлея
const overlayLocator = page.locator('#overlay');

// Добавляем обработчик локатора для закрытия оверлея
await page.addLocatorHandler(overlayLocator, async overlay => {
await overlay.locator('#closeButton').click(); // Закрытие оверлея
}, { times: 3, noWaitAfter: true }); // Макс. 3 раза, без ожидания после клика

// Взаимодействие с кнопкой после закрытия оверлея
await page.click('#fetchWeatherButton');

// Проверка отображения прогноза погоды
await page.waitForSelector('#weatherDisplay:has-text("Прогноз погоды для Chennai")');
});

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

💙 noWaitAfter: false для получения данных
Когда требуется подождать завершения сетевого запроса, например, получения прогноза погоды, параметр noWaitAfter: false гарантирует, что Playwright дождётся завершения запроса.
test('Получение данных погоды с noWaitAfter: false', async ({ page }) => {
await page.goto('http://localhost:3000');

// Клик по кнопке "Получить прогноз погоды" и ожидание завершения запроса
await page.click('#fetchWeatherButton', { noWaitAfter: false });

// Проверка отображения данных после загрузки
await page.waitForSelector('#weatherDisplay:has-text("Прогноз погоды для Chennai")');
const weatherText = await page.textContent('#weatherDisplay');
console.log(weatherText);
});

Здесь Playwright ждёт, пока данные полностью загрузятся, чтобы тест был надёжным.

💙 noWaitAfter: true для UI-манипуляций
Для операций, таких как переключение видимости элементов или обновление интерфейса, нет необходимости ждать завершения действий. Параметр noWaitAfter: true позволяет пропускать лишние ожидания.
test('UI-манипуляции с noWaitAfter: true', async ({ page }) => {
await page.goto('http://localhost:3000');

// Клик по кнопке без ожидания
await page.click('#toggleButton', { noWaitAfter: true });
await page.waitForSelector('#toggleElement.visible');

// Симуляция быстрых кликов без ожидания
await page.click('.rapidButton', { noWaitAfter: true });

// Кастомное действие, активируемое таймером
await page.click('#customActionButton', { noWaitAfter: true });
await page.waitForSelector('#customActionResult:has-text("Действие завершено!")');
});

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

Зачем использовать noWaitAfter?
➡️ Ускорение тестов. Пропуская ненужные ожидания, можно значительно повысить скорость выполнения тестов.
➡️ Обеспечение точности. Использование noWaitAfter: false гарантирует, что Playwright будет ждать завершения действий, требующих сетевых запросов или навигации, что снижает риск ложноположительных результатов.

Когда использовать noWaitAfter?
➡️ Используйте noWaitAfter: false для действий, связанных с навигацией или загрузкой данных.
➡️ Используйте noWaitAfter: true для манипуляций с интерфейсом и других действий, не требующих ожидания.

Теги: #playwright

Alexey QA note

17 Sep, 08:49


Декораторы в Playwrightт для мобильного тестирования📲

Нашел классную статью, где автор предлагает избавиться от дублирования кода и упростить поддержку тестов в Playwright. Как? С помощью декораторов TypeScript инкапсулировать платформенно-зависимую логику и создать единый тест для мобильных и настольных платформ.

Читать здесь📖

Теги: #playwright #cleanСode

Alexey QA note

13 Sep, 08:38


🔎Мокирование конкретных классов вместо интерфейсов
Приложение отправляет уведомления пользователям через SMS.
class SmsService {
sendSms(number: string, message: string): void {
// Логика отправки SMS
}
}

class NotificationManager {
constructor(private smsService: SmsService) {}

notifyUser(user: User, message: string): void {
this.smsService.sendSms(user.phoneNumber, message);
}
}

Антипаттерн:
В тестах мокируется конкретный класс SmsService.
describe('NotificationManager', () => {
it('should send SMS notification', () => {
const smsService = new SmsService();
spyOn(smsService, 'sendSms');
const manager = new NotificationManager(smsService);
manager.notifyUser({ phoneNumber: '1234567890' }, 'Test Message');
expect(smsService.sendSms).toHaveBeenCalledWith('1234567890', 'Test Message');
});
});

Почему это плохо:
Привязывает тест к конкретной реализации.
Трудно заменить SmsService на другую реализацию (например, для разных стран).
Решение:
Использовать интерфейс для абстракции сервиса отправки сообщений.
interface IMessageService {
sendMessage(recipient: string, message: string): void;
}

class SmsService implements IMessageService {
sendMessage(recipient: string, message: string): void {
// Логика отправки SMS
}
}

class NotificationManager {
constructor(private messageService: IMessageService) {}

notifyUser(user: User, message: string): void {
this.messageService.sendMessage(user.phoneNumber, message);
}
}



🔎Тестирование с мокированием интерфейса:

describe('NotificationManager', () => {
it('should send message notification', () => {
const messageService: IMessageService = {
sendMessage: jasmine.createSpy('sendMessage'),
};
const manager = new NotificationManager(messageService);
manager.notifyUser({ phoneNumber: '1234567890' }, 'Test Message');
expect(messageService.sendMessage).toHaveBeenCalledWith('1234567890', 'Test Message');
});
});


😉Что-то вроде выводов:
Стремитесь писать тесты, которые проверяют поведение через публичный интерфейс и фокусируются на результатах, а не на деталях реализации. Это сделает ваш код более надежным, а тесты — более ценными инструментами в процессе разработки.

Теги: #cleanСode #unitTests #TDD #BDD

Alexey QA note

13 Sep, 08:38


💻Антипаттерны юнит тестов

Продолжаем тему с юнит тестами, и поговорим какие существуют антипаттерны при написании юнит тестов.

🔎Тестирование приватных методов
У вас есть класс PaymentProcessor, который обрабатывает платежи и содержит приватный метод для валидации транзакций.
class PaymentProcessor {
private validateTransaction(transaction: Transaction): boolean {
// сложная логика
return transaction.amount > 0 && transaction.currency === 'USD';
}

processPayment(transaction: Transaction): string {
if (this.validateTransaction(transaction)) {
return 'Payment processed';
} else {
return 'Invalid transaction';
}
}
}

Антипаттерн:
Делаем метод публичным и тестирование метода validateTransaction напрямую.
Почему это плохо:
Нарушает принцип инкапсуляции.
Тесты становятся хрупкими при изменении внутренней реализации.
Решение:
Тестировать публичный метод processPayment, который использует приватный метод.
Или провести рефакторинг и вынести validateTransaction в отдельный класс.


🔎Раскрытие приватного состояния объекта
Класс Inventory управляет списком товаров на складе.
class Inventory {
private items: Item[] = [];

addItem(item: Item): void {
this.items.push(item);
}
getItems(): ReadonlyArray<Item> {
return this.items;
}

// Другие методы...
}

Антипаттерн:
Чтобы упростить тестирование, приватное свойство items делается публичным.
Решение:
Тестировать публичный метод processPayment, который использует приватный метод.


🔎Утечка доменных знаний в тесты
Система рассчитывает налог в зависимости от категории продукта.
class TaxCalculator {
calculateTax(product: Product): number {
if (product.category === 'Food') {
return product.price * 0.05;
} else if (product.category === 'Electronics') {
return product.price * 0.2;
}
return product.price * 0.1;
}
}

Антипаттерн:
Тест дублирует бизнес-логику при расчете ожидаемого результата.
describe('TaxCalculator', () => {
it('should calculate tax for food category', () => {
const calculator = new TaxCalculator();
const product = { price: 100, category: 'Food' };
// тут дублируется логика
const expectedTax = product.price * 0.05;
const tax = calculator.calculateTax(product);
expect(tax).toBe(expectedTax);
});
});

Почему это плохо:
Тест повторяет логику, которую должен проверять.
При изменении логики необходимо менять и код теста.
Решение:
Использовать конкретные значения для ожидаемых результатов.
describe('TaxCalculator', () => {
it('should calculate 5% tax for food category', () => {
const calculator = new TaxCalculator();
const product = { price: 100, category: 'Food' };
const tax = calculator.calculateTax(product);
expect(tax).toBe(5);
});

it('should calculate 20% tax for electronics category', () => {
const calculator = new TaxCalculator();
const product = { price: 200, category: 'Electronics' };
const tax = calculator.calculateTax(product);
expect(tax).toBe(40);
});
});

Теги: #unitTests #cleanСode #TDD #BDD #learning #recommendation #practices

Alexey QA note

06 Sep, 10:41


Выход playwright 1.47

Обновления Playwright:

1⃣ Network Tab (небольшие улучшения в UI mode и trace viewer)
Фильтрация по типу запроса и URL
Улучшенное отображения query parameters
Превью для шрифтов

2⃣ Опция — tsconfig
Теперь можно указать конкретный tsconfig для всех импортируемых файлов:
npx playwright test --tsconfig tsconfig.test.json


3⃣ APIRequestContext
Поддержка URLSearchParams в query параметрах:
const response = await request.get('url', { params: 'userId=1' });


https://github.com/microsoft/playwright/releases/tag/v1.47.0

Теги: #playwright #updates

Alexey QA note

02 Sep, 09:43


🖥Структура юнит тестов

Меня читают много разработчиков и скорее всего это пост для них.

При написании юнит тестов возникает необходимость структурировать код таким образом, чтобы он был понятным, легко поддерживаемым и эффективно выявлял ошибки. Один из наиболее популярных подходов для достижения этих целей — паттерн AAA (Arrange-Act-Assert).

Патерн делит процесс написание тестов на 3 логические части:
⚪️ Arrange (Подготовка) — вы готовите все необходимые данные и зависимости для теста
⚪️ Act (Действие) — выполняете основное действие, которое хотите протестировать
⚪️ Assert (Проверка) — на заключительном этапе вы проверяете результаты действия.

Пример прям из тестов текущего проекта:
test('Закрывает Drawer при вызове onClose', () => {
// Arrange
render(<Comments />);
const closeButton = screen.getByRole('button', { name: 'close' });

// Act
fireEvent.click(closeButton);
TypeScript
// Assert
expect(mockedUseStore().services.comments.close).toHaveBeenCalled();
});


Рекомендации🤔
Почти все эти рекомендации можно соблюдать автоматически настроив правила
eslint-a с плагином eslint-plugin-jest.

✖️ Избегайте тесты где используются несколько секций Arrange, Act, Assert.
Например:
 test('Закрывает и открывает Drawer при вызове onClose', () => {
// Arrange
render(<Comments />);
const closeButton = screen.getByRole('button', { name: 'close' });

// Act
fireEvent.click(closeButton);

// Assert
expect(mockedUseStore().services.comments.close).toHaveBeenCalled();

// Arrange
const openCommentButton = screen.getByRole('button', { name: 'Комментарии' });

// Act
fireEvent.click(openCommentButton);

// Assert
expect(modal).toBeVisible();
});


✖️ Избегайте if в тестах.
Тесты должны быть последовательны и без ветвлений.
Включите правило линтера: no-conditional-in-test.

✔️ Один тест — одно действие
✔️ Один тест — одно утверждение, это не всегда возможно, старайтесь, чтобы в каждом тесте проверялось одно конкретное поведение. Это упрощает диагностику при возникновении ошибок.
Можно использовать правила линтера:
➡️ expect-expect — правило следит, что во всех тестах есть expect
➡️ max-expects — максимальное число expect в тестах

По мотивам книги Принципы юнит-тестирования📖

Теги: #unitTests #cleanСode #testing #TDD

Alexey QA note

29 Aug, 09:02


Как сделать так, чтобы в ветку попадал только чистый и рабочий код?👩‍🍳

В разработке важно, чтобы в ветку попадал код, который соответствует стандартам и не ломает приложение или на код-ревью не писали 💩 Один из эффективных способов это обеспечить — использование Git хуков, особенно pre-commit. Этот хук запускает проверки до того, как изменения будут зафиксированы, и позволяет автоматизировать запуск линтера и тестов перед каждым коммитом.

Для упрощения этого процесса есть масса различных библиотек📖:
📍husky (nodejs)
📍pre-commit (python)
📍использовать нативные (для любого проекта)

Пример настройки для nodejs husky📝
Прежде чем приступать к настройки у нас должны быть установлены linter, prettier

Пример package.json
{ 
"scripts": {
"lint": "eslint .",
"format": "prettier . --write",
"test": "jest"
}
}

Команда init упрощает настройку husky в проекте. Он создает pre-commit в .husky/ и обновляет сценарий для подготовки в package.json.
 npx husky init

Дальше просто добавляем наши скрипты проверки качества кода
echo "npm prettier && npm lint && npm test" > .husky/pre-commit

После можно попробовать сделать коммит и наши скрипты запустятся

Если вам надо закоммитить быстро можно отключить запуск хуков
git commit -m "..." -n


Было полезно? Ставьте 👍 👎

Теги: #husky #lint #prettier #git #commit

Alexey QA note

28 Aug, 06:49


Локаторы vs селекторы🤓💪

Что такое селекторы и локаторы в Playwright?

📌 Селекторы — это строки, которые используются для сопоставления элементов в DOM страницы. Playwright поддерживает различные типы селекторов, включая поиск по тексту, CSS, XPath и другие.

📌 Локаторы — это абстракция, построенная на основе селекторов, которая позволяет находить любые элементы на странице, а также обеспечивает "умные" ожидания, являющиеся ключевой функцией Playwright.

Я планирую написать подробное руководство о том, как и какой локатор лучше использовать. Вот выдержка из документации по рекомендуемым локаторам. Если ни одна из функций не подходит, можно добавить атрибут data-testid:
🔵page.getByRole() для поиска по явным и неявным атрибутам доступности.
🔵page.getByText() для поиска по текстовому содержимому.
🔵page.getByLabel() для поиска по лейблу
🔵page.getByPlaceholder() для поиска поля ввода по плейсхолдеру.
🔵page.getByAltText() для поиска элемента, по альтернативному тексту.
🔵page.getByTitle() для поиска элемента по его атрибуту title.
🔵page.getByTestId() для поиска элемента по атрибуту data-testid.

Было полезно? Ставьте 👍 👎

Теги: #playwright

Alexey QA note

26 Aug, 13:09


👁Захват и анализ сетевого трафика прямо в браузере

Захват и анализ сетевого трафика через chrome://net-export. Это может быть полезно ⬇️
🔎Если требуется захватить сетевой трафик в течение длительного периода времен
🔎Когда нужно анализировать трафик, связанный с несколькими сетями или интерфейсами (например, при переключении между Wi-Fi и сотовой сетью)
🔎Если DevTools не дает всей необходимой информации о сетевых ошибках или задержках, chrome://net-export/ может предоставить более подробные данные, включая информацию о сетевых пакетах, DNS-запросах и внутренней работе браузера.
🔎Для отслеживание 2 вкладок.

В Chrome есть встроенная функция net-export, которая проста и удобна в использовании:
1️⃣ Откройте страницу chrome://net-export.
2️⃣Нажмите «Start Logging to Disk».
3️⃣Укажите расположение и название файла, который будет сохранен в формате JSON.
4️⃣После завершения работы нажмите «Stop Logging to Disk»

В итоге, chrome://net-export/ чаще используется для более глубокого и продолжительного анализа сетевой активности, когда стандартных возможностей DevTools недостаточно для решения задач.

Дальше открываешь полученный JSON netlog-viewer.appspot.com

Ставьте 👍👎
Теги: #chrome #netexport #devtools

Alexey QA note

23 Aug, 15:00


Видео с гейзенбага 🪲

Выложили мой доклад с последнего heisenbug.

В прошлом году я рассказывал о проблемах перфоманса, а в весной сделал акцент на проблемы рендеринга. Всем любителям девтулзов и не равнодушным к веб-тестированию рекомендую к просмотру🖥

Теги: #heisenbug #доклад #tools

Alexey QA note

22 Aug, 07:12


⚡️Хранение и управление скриптами, которые используются для ускорения тестирования в DevTool

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

1️⃣ Закладки в браузере
Вы можете хранить небольшие скрипты прямо в закладках браузера. Я использую такой метод для запросов и авторизации. Это удобно для простых и часто используемых скриптов.

🚩Как сохранить: Создайте новую закладку и вместо URL вставьте ваш JavaScript-код, предварительно добавив префикс javascript:. Например:

javascript:(function(){
// Ваш код здесь
const countElement = $$('[class^="_ObjectsListCard"]').length;
console.log(`Количество проектов: ${countElement}`);
})();

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

2️⃣ GitHub/GitLab репозиторий
Если скрипты регулярно обновляются и их нужно делиться с коллегами, использование репозитория на GitHub или GitLab.

3️⃣ Chrome DevTools Snippets
Chrome DevTools имеет встроенную возможность хранения скриптов в виде сниппетов. Это отличный способ хранить и запускать скрипты непосредственно в инструментах разработчика.

Как использовать: В Chrome DevTools перейдите на вкладку "Sources" и откройте раздел "Snippets". Здесь вы можете создавать и хранить свои скрипты. Запускать их можно прямо из этого раздела.
Прямой доступ в DevTools, легкость использования, подходит для часто используемых скриптов.
Скрипты сохраняются локально и не синхронизируются между устройствами.

4️⃣ Написание своего расширения
Если у вас есть набор скриптов, которые используются регулярно и в разных проектах, создание собственного расширения для Chrome может быть удобным решением.

Как использовать: Создайте простое расширение для Chrome, которое будет содержать ваши скрипты и интерфейс для их управления (например, кнопки для запуска).
Полный контроль над функциональностью, возможность автоматизации многих задач, синхронизация через учетную запись Google.
Требуется знание разработки расширений, больше времени на разработку и поддержку.


😉Заключение
Выбор способа хранения зависит от ваших потребностей и частоты использования скриптов. Для простых задач подойдут закладки или сниппеты в DevTools. Если скрипты требуют совместной работы или версионирования, лучше использовать GitHub/GitLab. Если же у вас сложные и регулярные задачи, имеет смысл рассмотреть создание собственного расширения для Chrome.

Ставьте 👍 👎
Теги: #DevTools #tools

Alexey QA note

21 Aug, 08:39


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

В таких ситуациях можно попытаться вызвать соответствующие события вручную:
const nameInput = document.querySelector('#name');
nameInput.value = 'Тестовое имя';
nameInput.dispatchEvent(new Event('input', { bubbles: true }));
nameInput.dispatchEvent(new Event('change', { bubbles: true }));


Если и это не помогает, стоит рассмотреть использование других инструментов для автоматизации, таких как Selenium или Cypress, которые могут эмулировать взаимодействие пользователя с элементами страницы на более глубоком уровне.

О хранении и управлении скриптами будет завтра. Было полезно? Ставьте 👍👎

Теги: #automation #tools

Alexey QA note

21 Aug, 08:39


👨‍💻Скрипты в консоль
В основном консоль используют для отслеживания ошибок на сайте.

Я предлагаю открыть консоль по новому для обычного QA.

Когда я только начинал свой путь в IT, я играл в одну браузерную игру. Тогда я и представить не мог, что существует автоматизация. Мой первый код на JavaScript был связан со сбором подарков в игре.

Чтобы собрать раньше всех в игре я использовал самый примитивный код, который вставлял в консоль
setInterval(()=> {
$('#gift').click()
}, 150)


Суть кода понятна каждому, где мы просто кликаем по селекту каждые 150 мс.


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

В основном консоль используют для отслеживания ошибок, но мало кто знает, что ее можно использовать для простой автоматизации или в качестве помощника.

Кейс 1: Подсчёт элементов на странице📝
Этот кейс вы уже упомянули, и он действительно полезен для быстрой оценки, например, количества отображаемых элементов.
const countElement = $$('[class^="_ObjectsListCard"]').length;
console.log(`Количество проектов: ${countElement}`);


Кейс 2: Парсинг данных со страницы (ссылки)🔗
Иногда нужно собрать все ссылки со страницы, например, для проверки их на работоспособность или для подготовки тест-кейсов.
const links = [...document.querySelectorAll('a')].map(link => link.href);
console.log('Все ссылки на странице:', links);


Кейс 3: Парсинг данных с таблицы (таблицу)🫥
Недавно я работал над задачей, связанной с таблицей, чтобы получить данные о списках поступающих и оценить вероятность поступления своего брата. Данные из таблицы для дальнейшего анализа, можно использовать следующий скрипт:
const tableRows = [...document.querySelectorAll('table tbody tr')];
const data = tableRows.map(row => {
const columns = row.querySelectorAll('td');
return {
column1: columns[0].innerText,
column2: columns[1].innerText,
column3: columns[2].innerText,
};
});
console.log('Данные из таблицы:', data);


Кейс 4: Парсинг данных и выполнение вычислений 🎙
Можно не только парсить данные, но и сразу выполнять вычисления. Например, если нужно суммировать значения в колонке:
const tableRows = [...document.querySelectorAll('table tbody tr')];
const total = tableRows.reduce((sum, row) => {
const value = parseFloat(row.querySelector('td:nth-child(3)').innerText);
return sum + (isNaN(value) ? 0 : value);
}, 0);
console.log(`Сумма значений в третьей колонке: ${total}`);


Кейс 5: Отправка запросов для подготовки данных🟢
Иногда требуется подготовить данные или проверить API без использования Postman или других инструментов. Это можно сделать прямо из консоли:
fetch('<https://example.com/api/data>', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ key: 'value' }),
})
.then(response => response.json())
.then(data => console.log('Ответ от сервера:', data))
.catch(error => console.error('Ошибка:', error));


Кейс 6: Подключение к сокетам
Если ваш проект использует WebSocket, можно подключиться к сокету и прослушивать события прямо в консоли:
const socket = new WebSocket('wss://example.com/socket');

socket.onopen = () => {
console.log('Соединение установлено');
socket.send(JSON.stringify({ action: 'subscribe', channel: 'updates' }));
};

//далее отправляем различные запросы


Кейс 7: Заполнение форм
Для ускорения тестирования форм можно использовать автоматическое заполнение и отправку данных:
document.querySelector('#name').value = 'Тестовое имя';
document.querySelector('#email').value = '[email protected]';
document.querySelector('form').submit();
console.log('Форма заполнена и отправлена');

Теги: #tools

Alexey QA note

17 Aug, 10:13


#дайджест 📢


⚡️ В nodeJS 22.6 добавили поддержку typescript

⚡️ Playwright в 👩‍💻 версии **1.46
🌟 позволяет указывать клиентские сертификаты, теперь не надо игнорировать https
🌟 новая опция CLI --only-changed позволяет запускать только тестовые файлы, которые изменились с момента последней фиксации git
🌟 Обновление UI Mode / Trace Viewer
🌟 В APIRequestContext.fetch() появилась новая опция maxRetries. Она позволяет повторять попытку при возникновении сетевой ошибки ECONNRESET.
🌟 Опция Box в фикстурах уменьшает мусор в отчетах

⚡️👩‍💻 k6 v0.53.0
Добавили поддержку нативных ECMAScript модулей
и другие улучшения

⚡️ WebdriverIO 👩‍💻 v9
Все сеансы будут автоматически использовать протокол Bidi
Подробнее

Теги: #updates

1,171

subscribers

77

photos

1

videos