Tools

ESlint. Code coverage. Load testing. Continuous integration

Жигалов Сергей

Code quality tools

  • Обнаружить ошибки до интерпретации кода
  • Привести код к общему стилю
  • Убрать лишний код
  • Повысить качество кода
  • Сделать кодревью полезным

ESlint

The pluggable linting utility for JavaScript and JSX eslint-logo

Линтинг Ошибки


function getPokerHand(dice) {
    if (Array.isArray(dice))
        console.log('Dise is', typeof dice);
        throw new Error('Dice is not array');

    return 'Покер';
}
        
eslint-errors

Линтинг Неиспользуемые переменные


/**
 * Represents a sum
 *
 * @param a The first number.
 * @param {number} b
 */
function sum(a, b) {
    return a + c;
}
        
eslint-unused-vars

ESlint


# Установка eslint
npm install eslint --save-dev

# Создание конфига
./node_modules/.bin/eslint --init

# Запуск eslint
./node_modules/.bin/eslint .
        

ESlint Конфигурация


// .eslintrc.json

{
    "env": {
        "es6": true,
        "node": true
    },
    "parserOptions": {
        "ecmaVersion": 2017
    },
    "rules": { /* ... */ }
}
        

ESlint Конфигурация


// .eslintrc.json
{
    /* ... */
    "rules": {
        "no-unused-vars": 0, // выключено
        "max-len": [1, 100], // предупреждение
        "max-params": [2, 3] // ошибка
    }
}
        

ESlint Пресеты

Список

ESlint --fix

До


function formatDate(date) {
    var hours=('0'+date.getHours()).slice(-2)
    const minutes=('0'+date.getMinutes()).slice(-2);
    let nextDay=new Date(date.setDate(date.getDate()+1)).toDateString();
    if (nextDay==new Date())
        return 'в '+hours+':'+minutes

    /* ... */
}
        

ESlint --fix

После


function formatDate(date) {
    const hours = (`0${date.getHours()}`).slice(-2);
    const minutes = (`0${date.getMinutes()}`).slice(-2);
    const nextDay = new Date(date.setDate(date.getDate() + 1)).toDateString();

    if (nextDay == new Date()) { return `в ${hours}:${minutes}`; }

    /* ... */
}
        

ESlint Исключения


function controller(err, req, res, next) {
    console.error(err.stack);
    res.status(500).send('Something broke!');
}
        
eslint-express-error

ESlint Исключения


function controller(err, req, res, next) {
    /* eslint max-params: 0, no-unused-vars: 0 */

    console.error(err.stack);
    res.status(500).send('Something broke!');
}
        

Code coverage

istanbul


# Установка istanbul
npm install istanbul --save-dev

# Запуск istanbul
./node_modules/.bin/istanbul cover
    ./node_modules/.bin/_mocha
    qa-task-03/tests

# Открываем отчет с результатом coverage
open coverage/lcov-report/index.html
        
DEMO

istanbul Отчет


./node_modules/.bin/istanbul cover ...

====== Coverage summary =======
Statements   : 95.24% ( 20/21 )
Branches     : 93.75% ( 15/16 )
Functions    : 100% ( 3/3 )
Lines        : 95.24% ( 20/21 )
===============================
        
100% покрытие не означает хорошее

Пример


function playPoker(firstDice, secondDice) {
    const first = getPokerHand(firstDice);
    const second = getPokerHand(secondDice);

    const compareHands =
        pokerHands.indexOf(first) -
        pokerHands.indexOf(second);

    return compareHands === 0
        ? 'Ничья'
        : compareHands > 0 ? 'Первый' : 'Второй';
}
        

Тесты


describe('playPoker', () => {
    it('should return `Ничья` for equal poker hand', () => {
        const actual = playPoker([1, 1, 2, 3, 4], [1, 1, 2, 3, 5]);

        assert.equal(actual, 'Ничья');
    });

    it('should return `Первый` when first hand great then second', () => {
        const actual = playPoker([1, 1, 1, 1, 4], [1, 1, 1, 3, 4]);

        assert.equal(actual, 'Первый');
    });

    /* ... */
});
        

unit-coverage


# Устанавливаем unit-coverage
npm install --save-dev unit-coverage

# Запускаем ковередж
node_modules/.bin/unit-coverage run
    -s 'qa-task-03/src/**'
    -t 'qa-task-03/tests/**'
    -S relative
    -O sources=qa-task-03/src
    -O tests=qa-task-03/tests
    -- --recursive qa-task-03/tests/
        
Ковередж проверяет только вызовы. Правильность проверяет разработчик.

Continuous Integration

CI - это практика разработки программного обеспечения, которая заключается в слиянии рабочих копий в общую ветвь разработки несколько раз в день и выполнении частых автоматизированных сборок проекта

Continuous Integration Этапы

  1. Клонирование репозитория
  2. Установка зависимостей, сборка
  3. Запуск всех видов тестов
  4. Сбор метрик
  5. Уведомление ответственных

Continuous Integration Плюсы

Дает быструю обратную связь

Дисциплинирует команду

Неизбежное тестирование кода

Автоматизация рутины

Continuous Integration Сервер

teamcity TravisCI drone-io

Continuous Integration TravisCI

  • Зарегистрироваться на travis-ci.org
  • Активировать репозиторий
  • Добавить .travis.yml

Continuous Integration Активировать

TravisCI-activate

Continuous Integration .travis.yml


language: node_js
node_js:
  - "node"
before_script:
  - npm run cover
        

Нагрузочное тестирование

(англ. load testing) — подвид тестирования производительности, сбор показателей и определение производительности и времени отклика программы в ответ на внешний запрос с целью установления соответствия требованиям, предъявляемым к программе

Яндекс.Танк

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

Общая схема

load-cheme

Танковая терминология Танкист

человек, который проводит нагрузочное тестирование

Танковая терминология Танк

сервер, с которого отправляются http-запросы.

Танковая терминология Мишень

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

Танковая терминология Патрон

запрос от нагрузочного сервера к приложению.
Танкисты заряжают ленты с патронами и стреляют по мишеням из танков на полигоне.

Одна стрельба

load-test

Профили нагрузки

  • Константная
    • Утечки памяти
    • Время ответа сервиса
  • До разладки
    • Максимальный RPS

Серия стрельб Константная

load-rps

Серия стрельб До разладки

load-rps

SLA

(англ. Service Level Agreement) — договор между заказчиком и поставщиком, содержащий <...> согласованный уровень качества предоставления данной услуги.

SLA Пример

95% пользователей получат ответ не позже чем через 300ms

Метрики производительности

  • Время выполнения запроса
  • Потребление ресурсов центрального процессора
  • Потребление оперативной памяти
  • Потребление сетевых ресурсов
  • Работа с дисковой подсистемой

Яндекс.Танк Установка

Тестирование в Яндексе: строим свой Лунапарк

Apache benchmarking tool


ab -c 2 -n 100 https://some/url

Requests per second:    3.78 [#/sec] (mean)
Time per request:       264.300 [ms] (mean, across all concurrent requests)

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:       95  111  11.5    112     157
Processing:   198  416 645.6    296    5271
Waiting:      134  341 645.7    222    5194
Total:        302  527 645.1    407    5385
        

Почитать