Тестирование: назад к основам + [Puppeteer][Mocha] Совершенствуйте код с помощью тестового покрытия

Автор оригинала: Kirill Z. (@storenth)
  • Перевод

Перевод статьи подготовлен в преддверии старта курса «Автоматизация тестирования на JavaScript».





Меня несколько раз спрашивали о разнице между инженером по обеспечению качества (QA — Quality Assurance) и тестером (QC — Quality Control), и я понял, что даже если люди, разрабатывающие программное обеспечение, путают такие простые понятия, то что уже говорить про остальных? Но по большому счету, вы понимаете, что им все равно, и это их право!


Людям просто нужны качественные продукты! Менеджеры хотят иметь программное обеспечение без багов [1] наилучшего качества, пользователям нужны качественные приложения, а этого можно достигнуть путем неустанного тестирования [2]. Но что это значит? Что такое качество (Quality)? Все дело в удовлетворении — настолько тривиально! Мера качества — это счастье конечных пользователей! Достижение этой абстракции становится настоящим испытанием для команды [3].


При разработке любого продукта, особенно программного обеспечения без тестирования, мы сталкиваемся с рисками [4], а они, с большой долей вероятности, сопряжены с потерей средств [5]. Так что, если вы не большой фанат тестирования, но для вас важно качество, то я предлагаю вам подумать еще раз и дать процессам обеспечения качества делать свое дело. Это относится ко всем членам команды и особенно к инженерам, которые имеют отношение к тест дизайну [6] — инженерам по обеспечению качества.


Таким образом, посыл, что человек должен быть удовлетворен качественным приложением, подкрепляется подходами, уже сформировавшимися в лучшие практики [7]. Однажды занявшись тестированием, вы узнаете о существовании различных типов тестирования [8] и документации по тестированию (например, план тестирования). Затем вы сможете обрабатывать тест кейсы [9] на основе разных техник тест дизайна [10]. В конце концов, вы откроете для себя автоматизацию и к тому времени поймете разницу между QA и QC [11].


Глоссарий:


  1. несоответствие между фактическим и ожидаемым поведением
  2. полной проверки продукта путем верификации, валидации на основе спецификаций для обнаружения проблем
  3. люди, которые разрабатывают приложения, такие как дизайнеры, программисты, тестировщики
  4. (а) возможность негативного исхода (в соответствии с Кембриджским словарем);
    (b) действия в надежде на позитивных исход (в соответствии со словарем Google)
  5. (a) 125 миллионов пробников почвы Марса, потерянных из-за простой математической ошибки
    (b) много человеческих ошибок, приведших к крушению Boeing 737 Max
  6. пирамида тестов, фреймворк для разработки набора тестов, который оптимизирует скорость выполнения тестов с уверенностью, что ваше приложение работает должным образом
  7. семь принципов тестирования на International Software Testing Qualifications Board
  8. различные типы тестирования программного обеспечения от Atlassian
  9. этапы воспроизведения с ожидаемыми результатами в соответствии с требованиями приложения
  10. общие техники тестирования, которые вы должны знать
  11. ищите ответ здесь

Книги:


  • Тестирование Дот Ком, или Пособие по жестокому обращению с багами в интернет-стартапах, Савин Р. 2007
  • Continuous delivery. Практика непрерывных апдейтов, Эберхард В. 2017
  • Software Testing Automation Tips, Алпаев Г. 2017

[Puppeteer][Mocha] Проапгрейдите свой код с помощью тестового покрытия.


Пирамида тестов


С момента релиза Puppeteer сквозное тестирование (end-2-end) стало быстрым и надежным способом тестирования функционала. Большинство вещей, которые вы можете сделать вручную в браузере, можно сделать с помощью Puppeteer. Более того, Chrome без графики снижает нагрузку на производительность, а нативный доступ к протоколу DevTools делает Puppeteer просто потрясающим инструментом. Представьте, что каждый раз, когда мы разрабатываем интерфейс, мы просто проверяем окончательный вид в браузере — без TDD мы сталкиваемся с мороженкой-антипатерном пирамиды тестов.



Сверху вниз: Ручные тесты / Автоматизированные GUI-тесты / Интеграционные тесты / Юнит-тесты


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


Настройка


У меня есть полная пошаговая README.md инструкция, основанная на простом проекте, который я форкнул и снабдил его многофункциональным тестовым апгрейдом в целях демонстрации (или чтобы выпендриться). Итак, если у вас есть еще один, пожалуйста:


1) Установите зависимости в корне


npm i puppeteer mocha puppeteer-to-istanbul nyc -D

2) Предоставьте свой экземпляр на конечной точке (мое простое решение для *.html http-сервер)


3) Создайте каталог test и заполните {yourFeature}_test.js следующим подходящим шаблоном (заполните хуки before и after), попробуйте расширить его с помощью специфичных для проекта селекторов и поведений:


const puppeteer = require('puppeteer');
const pti = require('puppeteer-to-istanbul');
const assert = require('assert');

/**
 * ./test/script_test.js
 * @name Feature testing
 * @desc Create Chrome instance and interact with page.
 */

let browser;
let page;

describe('Feature one...', () => {
    before(async () => {
        // Создание экземпляра браузера
        browser = await puppeteer.launch()
        page = await browser.newPage()
        await page.setViewport({ width: 1280, height: 800 });
        // Подключите покрытие JavaScript и CSS
        await Promise.all([
            page.coverage.startJSCoverage(),
            page.coverage.startCSSCoverage()
          ]);
        // Конечная точка для эмуляции изолированного окружения
        await page.goto('http://localhost:8080', { waitUntil: 'networkidle2' });
    });
    // Первый тестовый набор
    describe('Visual regress', () => {
        it('title contain `Some Title`', async () => {
            // Настройка
            let expected = 'Some Title';
            // Выполнение
            let title = await page.title();
            // Проверка
            assert.equal(title, expected);
        }).timeout(50000);

    });
    // Второй тестовый набор
    describe('E2E testing', () => {
        it('Some button clickable', async () => {
            // Настройка
            let expected = true;
            let expectedCssLocator = '#someIdSelector';
            let actual;
            // Выполнение
            let actualPromise = await page.waitForSelector(expectedCssLocator);
            if (actualPromise != null) {
                await page.click(expectedCssLocator);
                actual = true;
            }
            else
                actual = false;
            // Проверка
            assert.equal(actual, expected);
        }).timeout(50000);
    // Сохранить покрытие и закрыть контекст браузера
    after(async () => {
        // Отключить покрытие JavaScript и CSS
        const jsCoverage = await page.coverage.stopJSCoverage();
        await page.coverage.stopCSSCoverage();

        let totalBytes = 0;
        let usedBytes = 0;
        const coverage = [...jsCoverage];
        for (const entry of coverage) {
            totalBytes += entry.text.length;
            console.log(`js fileName covered: ${entry.url}`);
            for (const range of entry.ranges)
                usedBytes += range.end - range.start - 1;
        }
        // вывести в лог исходное байтовое покрытие
        console.log(`Bytes used: ${usedBytes / totalBytes * 100}%`);
        pti.write(jsCoverage);
        // Закрыть экземпляр браузера
        await browser.close();
    });
});

Выполнение


  1. Запустите описанный выше тест для сценариев в конечной точке с помощью команды mocha
  2. Получите покрытие, собранное при выполнении теста с nyc report.
  3. Я предлагаю вам использовать ваш package.json с помощью следующих сценариев, что делает его очень простым для выполнения задач, таких как npm test или npm run cover

 "scripts": {
    "pretest": "rm -rf coverage && rm -rf .nyc_output",
    "test": "mocha --timeout 5000 test/**/*_test.js",
    "server": "http-server ./public",
    "coverage": "nyc report --reporter=html"
  },

Покрытие


Мой проект покрыт на приблизительно 62%



Мы можем получить отчет в виде html и посмотреть поближе.



Вы можете видеть, что Branches и Functions покрыты на 100%. В то время как я тестировал функцию покрытия Puppeteer (типа Coverage devTool) я создал этот багрепорт.



[Bug] Неверные ветви попадают в статистику покрытия #22
Размещено storenth 27 декабря 2018
Когда готов nyc report --reporter=htm, я пытался посмотреть на ./coverage/index.html и обнаружил большой дефект в числе покрытия Branch, оно всегда равно 100%. Чтобы изучить эту проблему, я предлагаю клонировать этот простой репозиторий для локального воспроизведения.


Холивар Unit против E2E


Как кто-то, у кого достаточно страсти к исследованиям, чтобы не завыть от скуки за этим процессом, вот что я вам скажу: нам нужно уделять больше внимания средам модульного тестирования, таким как Mocha, для написания от Unit до Acceptance тестов, нежели самим писать их. Я думаю, не важно, какой тест вы пишете, если ваша кодовая база покрыта. Времена изменились. Теперь, с доступным функционалом покрытия, другие инструменты, такие как матрица прослеживаемости в качестве меры качества, выглядят ужасно, потому что заинтересованные стороны все еще должны полагаться на слова тестера.


Внесите свой вклад


Я настоятельно рекомендую уделить некоторое время и ознакомиться с моим github-working-draft проектом прежде, чем вы наломаете дров. Я буду признателен за любое сотрудничество и обратную связь. Не стесняйтесь обращаться ко мне с любыми вопросами.




Узнать подробнее о курсе «Автоматизация тестирования на JavaScript»



OTUS. Онлайн-образование
Цифровые навыки от ведущих экспертов

Комментарии 0

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

Самое читаемое