x
 
Василий
14 ноября 2019
Советы почтой каждую неделю
Пожалуйста, получите наше письмо, чтобы подтвердить свой адрес:
Вы подписаны на «Советы за неделю»:

Вторая часть: что и как тестировать у модуля


Автотесты «на пальцах»

Модули — это функ­ции, классы, модели, кон­трол­леры — кир­пи­чики, из кото­рых постро­ено приложение.

Автотесты «на пальцах»

Что тестировать?

У моду­лей есть пуб­лич­ный интер­фейс, через кото­рый с ними рабо­тают дру­гие модули. Если пред­ста­вить, что модуль — это машина, то её пуб­лич­ный интер­фейс — это функ­ции доступ­ные води­телю: «ехать прямо», «повер­нуть налево», «вклю­чить радио».

Пуб­лич­ный интер­фейс исполь­зует при­ват­ные функ­ции, доступ­ные только самому модулю. В слу­чае с маши­ной — это всё, что скрыто под капо­том: «скор­рек­ти­ро­вать угол опе­ре­же­ния зажи­га­ния» или «под­нять дав­ле­ние в топ­лив­ной рампе».

При­ват­ные функ­ции посто­янно меня­ются, пере­име­но­вы­ва­ются и исче­зают, пуб­лич­ные функ­ции меня­ются редко. Так в Тесле уже нет ни зажи­га­ния, ни топ­лив­ной рампы, а функ­ции «повер­нуть налево» и «вклю­чить радио» на месте.

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

Как тестировать?

Функ­ции можно раз­де­лить на два типа: запросы и команды. Запросы воз­вра­щают что‑то и ничего не меняют: user.isEditor(), array.find(), spread.isOnScreen(). Команды что‑то меняют и, бывает, что‑то воз­вра­щают: user.destroy(), array.splice(), spread.delete().

Чтобы убе­диться, что функ­ция‑запрос рабо­тает пра­вильно, про­верьте то, что она возвращает:

// Про­ве­рим функ­цию, кото­рая из имени автора совета
// выде­ляет фами­лию и воз­вра­щает её в роди­тель­ном падеже
//
​// С помо­щью describe задают струк­туру теста: что тести­руем и в каких усло­виях
describe('#genitiveFamilyName', () => {
  describe('with initials', () => {
    // С помо­щью it опи­сы­вают ожи­да­ния от кода
    it('returns it as is', () => {
      // С помо­щью expect све­ряют ожи­да­ния с реаль­но­стью:
      // если они не сов­па­дут, тесто­вый фрейм­ворк пока­жет ошибку
      expect(genitiveFamilyName('А. Г.')).toEqual('А. Г.')
    })
  })
  ​
  it('returns surname in genitive form', () => {
    expect(genitiveFamilyName('Мак­сим Илья­хов')).toEqual('Илья­хова')
  })
  ​
  it('returns surname in genitive form for female names', () => {
    expect(genitiveFamilyName('Таня Биби­кова')).toEqual('Биби­ко­вой')
  })
})

Чтобы убе­диться, что функ­ция‑команда рабо­тает пра­вильно, про­верьте послед­ствия её вызова:

Мы не случайно отбиваем пустыми строками куски кода. Так отделяют фазы теста: настройку, испытание и проверку. Подробнее расскажу о них в следующих советах
// Про­ве­рим функ­цию, кото­рая моди­фи­ци­рует ДОМ-дерево,
// про­ну­ме­ро­вы­вая и раз­ме­чая якоря
​
describe('#morph', () => {
  it('marks empty anchors as .is__blank so we can ignore them in navigation', () => {
    const html = `<div class="anchor"></div>`
    const $ = cheerio.load(html)
    ​
    morph($)
    ​
    expect($('.anchor').attr('class')).toContain('is__blank')
  })
  ​
  it('enumerates them', () => {
    const html = `
      <div class="anchor">One</div>
      <div class="anchor">Two</div>
      <div class="anchor">Three</div>
    `
    const $ = cheerio.load(html)
    ​
    morph($)
    ​
    const anchorIds = $('.anchor').get().map(el => el.id)
    ​
    expect(anchorIds).toEqual(['anchor-1', 'anchor-2', 'anchor-3'])
  })
})

Мы не случайно отбиваем пустыми строками куски кода. Так отделяют фазы теста: настройку, испытание и проверку. Подробнее расскажу о них в следующих советах

Ещё по теме

P. S. Это был совет о веб‑разработке. Хотите знать всё о коде, тестах, фронтенд‑разработке, цеэсэсе, яваскрипте, рельсах и джейде? Присылайте вопросы.
Вёрстка и прототипирование — дисциплина Школы дизайнеров. Набор открыт. Чем раньше поступите, тем ниже стоимость и выше шанс на бесплатное место.
 

Поделиться
Отправить

Комментарии

Владимир Родкин
14 ноября 2019

Хорошая аналогия с автомобилем. Помню, когда начинал работать по ТДД, писал тесты на приватные методы тоже. Но постепенно пришло осознание, что это по сути — дублирование. И к тому же усложняет будущие рефакторинги.


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

Мы публикуем комментарии, которые добавляют к уже сказанному новые мысли и хорошие примеры. Мы ожидаем, что такие комментарии составят около 20% от общего числа.

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

Вот такой веб 2.0.

Как называть классы в ЦСС. Часть вторая Как объяснить значимость фичи разработчику? 1 Как называть классы в ЦСС. Часть первая Расскажите об обязанностях технического директора в бюро. Вторая часть: встречи один на один




Недавно всплыло

Какой фотоаппарат выбрать для путешествий? 2 Как вы справляетесь с разнобоем? 4 Трудно найти вдохновение на текст 2 Как улучшить запись автоответчика? 4