Разработка через тестирование: улучшаем навыки

в 14:15, , рубрики: разработка, тестирование, Тестирование IT-систем, Тестирование веб-сервисов

Тестирование важный навык, которым должен обладать каждый разработчик. Тем не менее, некоторые делают это неохотно.

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

image

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

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

Теперь представим, что вы закончили работу над приложением и вернетесь к нему через несколько месяцев. Вы не будете помнить каждую деталь старого кода. Вы измените его… и черт возьми… что-то сломалось. Как вы это исправите? Посмотрите на каждый созданный файл и настроите его, чтобы он снова работал? Может и получится. Но изменив этот файл, вы сломаете что-то еще.

Возьмем еще один пример. После нескольких месяцев напряженной работы, вы наконец получили позицию, которую давно хотели! Вы включаетесь в команду и начинаете что-то создавать. Вы работаете с кодом других разработчиков и наоборот. И в один день все ломается. Если команда не интегрировала тесты в свое приложение, я вам не завидую.

Каждая команда должна писать тесты, когда создает программное обеспечение или приложения. Вы же не хотите быть человеком, который не знает, как тестировать?

Да, написание тестов требует времени. Да, сначала сложно. Да, создавать приложения интереснее. Но тесты важны и экономят время, если они правильно реализованы.

Моя цель сегодня: улучшить навыки тестирования. Мы рассмотрим unit тестирование и разработку через тестирование с помощью Jest (инструмент тестирования JavaScript). Конечно, есть другие инструменты тестирования, которые вы можете использовать, например, Mocha и Chai.

Давайте начнем!

Unit тестирование

Когда вы решаете протестировать приложение, вы сталкиваетесь с различными типами тестирования: unit тестирование (модульное), интеграционные тесты и функциональные тесты. Остановимся на модульных тестах.

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

Преимущества модульного тестирования:

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

Разработка через тестирование (TDD)

Чтобы понять и использовать разработку через тестирование, запомните эти 2 правила:

  1. Пишите тест, который не проходит, до написания кода.
  2. Затем пишите код, который сможет пройти тест.

Когда мы используем TDD, мы говорим о цикле “red, green, refactor”.

Red: вы пишите провальный тест без написания кода.
Green: пишите простейший код, который сможет пройти тест. Даже если код кажется вам наиглупейшим.
Refactor: рефакторинг кода, если необходим. Не беспокойтесь, если вы поменяете код и ваши юнит-тесты сломаются, если что-то пойдет не так.

Структурирование тестового файла

Jest предоставляет функции для структурирования тестов:

describe: используется для группировки ваших тестов и описания поведения вашей функции/модуля/класса. Он принимает два параметра. Первый — это строка, описывающая вашу группу. Второй — это функция обратного вызова, в которой у вас есть тестовые примеры или hook функции.

it или test: ваш модульный тест. Параметры такие же как и у describe. Должен быть описательным. Именование теста зависит от вас, но можно начинать с «Should».

beforeAll (afterAll): hook функция запускает до (и после) все тесты. Принимает один параметр, который является функцией, которую вы будете запускать до (и после) всех тестов.

beforeEach (afterEach): hook функция, которая выполняется до (и после) каждого теста. Принимает один параметр, который является функцией, которую вы будете запускать до (и после) каждого теста.

Перед тем, как писать любой тест, вы должны знать следующее:

Вы можете пропустить тест, используя .skip на describe и it: it.skip(...) или describe.skip(...). Используя .skip, вы говорите Jest игнорировать тест или группу.

Вы можете выбрать именно те тесты, которые хотите запустить, используя .only на describe и it: it.only(...) или describe.only(...). Это полезно, если у вас много тестов и вы хотите сосредоточиться только на одном или хотите «отладить» ваши тесты.

Настройка Jest

Чтобы показать вам те функции тестирования, которые мы рассматривали выше, нам нужно настроить Jest. Это очень просто.

Вам нужны только Node.js и npm или Yarn. Убедитесь, что вы используете последнюю версию Node.js, поскольку мы будем использовать ES6. Создайте новый каталог и инициализируйте его.

mkdir test-example && cd test-example
npm init -y
# OR
yarn init -y

-y отвечает “да” на все вопросы npm или yarn. Он должен был создать очень простой файл package.json.

Затем добавьте Jest в среду разработки

yarn add jest --dev

Затем добавьте следующий скрипт в ваш package.json:

"scripts": {
  "test": "jest"
}

yarn test будет запускать ваши тестовые файлы в каталоге. По умолчанию Jest распознает файлы, находящиеся внутри каталога __tests__, или файлы, которые заканчиваются на .spec.js, либо .test.js.

На этом все. Вы готовы писать первый тест.

Matchers (образцы)

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

expect(input).matcher(output)

Jest имеет много образцов, вот самый важный:

toBe: сравнивает strict equality (===).

expect(1 + 1).toBe(2)
let testsAreEssential = true
expect(testAreEssential).toBe(true)

toEqual: сравнивает значения между двумя переменными, массивами или объектами.

let arr = [1, 2]
arr.push(3)
expect(arr).toEqual([1, 2, 3])
let x= 1
x++
expect(x).toEqual(2)

toBeTruthy (toBeFalsy): указывает, истинно ли значение (или ложно).

expect(null).toBeFalsy()
expect(undefined).toBeFalsy()
expect(false).toBeFalsy()
expect("Hello world").toBeTruthy()
expect({foo: 'bar'}).toBeTruthy()

toContain: проверяет, содержит ли массив элемент.

expect(['Apple', 'Banana', 'Strawberry']).toContain('Apple')

toThrow: проверяет, вызывает ли функция ошибку.

function connect () {
  throw new ConnectionError()
}
expect(connect).toThrow(ConnectionError)

Первые тесты

Теперь мы собираемся написать наш первый тест и поиграть с нашими функциями. Сначала создайте в своем каталоге файл example.spec.js и вставьте следующее:

describe('Example', () => {
  beforeAll(() => {
    console.log('running before all tests')
  })
  afterAll(() => {
    console.log('running after all tests')
  })
  beforeEach(() => {
    console.log('running before each test')
  })
  afterEach(() => {
    console.log('running after each test')
  })
  it('Should do something', () => {
    console.log('first test')
  })
  it('Should do something else', () => {
    console.log('second test')
  })
})

Обратите внимание, что нам не нужно импортировать все функции, которые мы используем. Они уже предоставлены Jest.

Запустите yarn test:

image

Поскольку у вас нет утверждений в тестах, они пройдут. Вы видели разные инструкции console.log? Вы должны лучше понимать, как работают ваши функции и тестовые примеры.

Теперь удалите все hook функциии добавьте .skip в первый тест:

describe('Example', () => {
  it.skip('Should do something', () => {
    console.log('first test')
  })
  it('Should do something else', () => {
    console.log('second test')
  })
})

Запустите yarn test еще раз:

image

Ничего страшного, если первый тест работать не будет.

Добавьте третий тест и используйте .only:

describe('Example', () => {
  it('Should do something', () => {
    console.log('first test')
  })
  it('Should do something else', () => {
    console.log('second test')
  })
  it.only('Should do that', () => {
    console.log('third test')
  })
})

Еще раз запустим yarn test:

image

Во второй части статьи мы сделаем простую реализацию стека в JavaScript с помощью TDD.

Автор: Digital Skynet

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js