Практика автоматизированного тестирования интерфейса Puppeteer

внешний интерфейс Puppeteer тестовое задание
Практика автоматизированного тестирования интерфейса Puppeteer
В этой части будет записана и представлена ​​с использованием использования автоматизированного веб-тестирования KUCPETEER и полагается на конвенции, чтобы избежать неоднократно пересмотренной программы тестирования. При решении ряда главной страницы измените код ошибки времени выполнения, вызвавший не найти проблему. Статья впервые опубликована вличный блог

причина

В настоящее время мы постоянно развиваем проект с десятками страниц и 100 000+ строк кода, со сменой продуктов всегда будут такие проблемы. При добавлении или изменении некоторой бизнес-логики или функций (особенно общей логики) эта общая логика или компоненты часто вызывают некоторые другие проблемы. Из-за ограниченного количества тестировщиков нам сложно повторно протестировать все функции после завершения модуля. В то же время из-за разницы между окружением и данными (и пренебрежения полнотой кода в процессе разработки) в коде будут возникать проблемы с парсингом и отображением некоторых специальных данных, которые сложно найти в процессе разработки. и тестирование. В общем, мы надеемся иметь такой инструмент, который поможет нам решить вышеперечисленные проблемы:

  1. После внесения изменений в код и функции вы можете автоматически обращаться к страницам каждой функции для обнаружения проблем.
  2. Для большого объема содержимого данных выполните пакетный доступ, чтобы определить, есть ли проблемы с отображением разных данных.
  3. Тестовые функции и функции кода не должны быть максимально связаны друг с другом, чтобы избежать необходимости изменять тестовые примеры каждый раз, когда добавляется новая функция, а стоимость обслуживания слишком высока.
  4. Регулярные тестовые задания, своевременное обнаружение платформ данных для полноты отображения новых данных

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

Настройка функции

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

  1. заходите на каждую страницу по очереди
  2. Получите доступ к конкретному содержимому каждой страницы, например к переключению времени, переключению вкладок, переключению страниц, строкам расширения таблицы и т. д.
  3. Для ссылки на сведения в таблице данных выберите первые 100 для доступа и продолжите тестирование страницы детализации.
  4. Зафиксировать запрос об ошибке на странице
  5. Захват, подсчет и отчет об ошибках

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

  • Страничный блок, чтобы определить стабильность доступа к странице для каждой функции
  • Блок страницы сведений, в соответствии со списком данных на странице, выполняет переходы на страницу сведений о пакете и определяет стабильность страницы сведений при различных параметрах.
  • Функциональный блок, используемый для определения возникновения ошибки после щелчка и переключения различных типов отображения страницы и страницы сведений.

图片描述

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

Puppeteer

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

адрес документа

Puppeteer — это библиотека Node, которая предоставляет высокоуровневый API для управления Chromium или Chrome через протокол DevTools. Puppeteer по умолчанию работает в безголовом режиме, но его можно запустить и в «заголовочном» режиме, изменив файл конфигурации.

Мы можем использовать Puppeteer, чтобы сделать следующее:

  • Страница доступа, скриншоты
  • Автоматизируйте ввод с клавиатуры и отправляйте формы
  • Имитация действий пользователя, таких как клики
  • И т. д. и т. д. .

CUCPETEER может создать экземпляр страницы, а также методы использования просмотров страниц Goto, страницы содержит серию методов, вы можете выполнять различные операции на странице.

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  // ba认证
  await page.authenticate({
    username,
    password
  });
  // 访问页面
  await page.goto('https://example.com');
  // 进行截图
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();

Посетите целевую страницу и войдите в систему

Во-первых, для SPA (одностраничное приложение) мы все знаем, что при входе на страницу начинается рендеринг клиентского кода. Нам нужно дождаться рендеринга содержимого страницы перед выполнением соответствующих операций. У нас есть следующие методы для использования

waitUntil

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

  • load - когда срабатывает событие загрузки страницы
  • domcontentloaded — когда срабатывает событие страницы DOMContentLoaded
  • networkidle0 — срабатывает, когда больше нет сетевого подключения (по крайней мере, через 500 мс)
  • networkidle2 — срабатывает, когда есть только 2 сетевых подключения (по крайней мере, через 500 мс)

Через waitUnitl мы можем определить, что к странице обращались, когда запрос страницы завершен.

waitFor

Метод waitFor может разрешаться после завершения указанного действия.

// wait for selector
await page.waitFor('.foo');
// wait for 1 second
await page.waitFor(1000);
// wait for predicate
await page.waitFor(() => !!document.querySelector('.foo'));

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

// 等待密码输入框渲染
await page.waitFor('#password');
// 输入用户名
await page.type('input#username', "username");
// 输入密码
await page.type('input#password', "testpass");

// 点击登录按钮
await Promise.all([
  page.waitForNavigation(), // 等跳转完成后resolve
  page.click('button.login-button'), // 点击该链接将间接导致导航(跳转)
]);

await page.waitFor(2000)

// 获取cookies
const cookies = await page.cookies()

Массовый доступ к ссылкам в содержимом списка

В основном используйте функцию выбора экземпляра страницы

const table = await page.$('.table')
const links = await table.?eval('a.link-detail', links =>
  links.map(link => link.href)
);

// 循环访问links
...

Выполнять мониторинг ошибок и доступа

puppeteer может отслеживать ошибки, запросы и т. д. во время доступа к странице, чтобы мы могли фиксировать ошибки доступа к странице и сообщать о них.Это также основная функция, необходимая для тестирования~

// 当发生页面js代码没有捕获的异常时触发。
page.on('pagerror', () => {})
// 当页面崩溃时触发。
page.on('error', () => {})
// 当页面发送一个请求时触发
page.on('request')
// 当页面的某个请求接收到对应的 response 时触发。
page.on('response')

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

конечная функция

Благодаря нашему планированию тестового модуля, описанного выше, мы можем спланировать наш тестовый путь.

Посетите веб-сайт -> Логин -> Доступ Page 1 -> Тестирование базового блока -> Получить сведения о странице Link -> Нажмите страницу доступа -> Тестирование базовых блоков

-> Доступ к странице 2 ...

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

// 包含基本的测试方法,log输出等
class Base {}

// 详情页单元,进行一些基本的单元测试
class PageDetal extends Base {}

// 页面单元,进行基本的单元测试,并获取并依次访问详情页
class Page extends PageDetal {}

// 进行登录等操作,并依次访问页面单元进行测试
class Root extends Base {}

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

Например, для блока переключения времени сделаем краткое введение:

// 1. 获取测试单元的元素
const timeSwitch = await page.$('[test-role="time-switch"]');

// 若页面没有timeSwitch, 则不用进行测试
if (!timeSwitch) return

// 2. time switch的切换按钮
const buttons = timeSwitch.?('.time-switch-button')

// 3. 对按钮进行循环点击
for (let i = 0; i < buttons.length; i++) {
  const button = buttons[i]

  // 点击按钮
  await button.click()

  // 重点! 等待对应的内容出现时,才认定页面访问成功
  try {
    await page.waitFor('[test-role="time-switch-content"]')
  } catch (error) {
    reportError (error)
  }

  // 截图
  await page.screenshot()
}

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

Суммировать

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