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

Четвёртая часть: гигиена


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

  1. Тести­ро­вать только пуб­лич­ный интерфейс.

  2. Про­ве­рять, что вер­нул запрос.

  3. Про­ве­рять послед­ствия вызова команды.

  4. Исполь­зо­вать заглушки вме­сто внеш­них запросов.

  5. Про­ве­рять факт вызова внеш­ней команды.

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

Пишите в едином стиле и используйте линтеры

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

Чтобы мини­ми­зи­ро­вать коли­че­ство таких оши­бок, про­грам­ми­сты при­ду­мали стили коди­ро­ва­ния — стан­дарты оформ­ле­ния кода. В них опи­сы­вают, как фор­ма­ти­ро­вать, струк­ту­ри­ро­вать и орга­ни­зо­вы­вать код и ком­мен­та­рии, какую исполь­зо­вать систему име­но­ва­ния, какого кода стоит избегать.

См. совет о линтерах

Чтобы за сти­лем коди­ро­ва­ния сле­дили роботы, а не люди, про­грам­ми­сты при­ду­мали лин­теры — про­граммы, авто­ма­ти­че­ски про­ве­ря­ю­щие код на соот­вет­ствие выбран­ному стилю кодирования.

См. совет о линтерах

Для всех попу­ляр­ных фрейм­вор­ков тести­ро­ва­ния есть пла­гины к лин­те­рам, кото­рые про­ве­ряют спе­ци­фич­ные для тестов вещи:

К сожа­ле­нию, не всё можно про­ве­рить авто­ма­ти­че­ски: лин­тер не смо­жет понять, насколько хорошо код покрыт про­вер­ками, нет ли лиш­них зави­си­мо­стей, понятны ли чело­веку опи­са­ния про­ве­рок. Поэтому помимо лин­те­ров сове­тую изу­чить сбор­ники луч­ших прак­тик тестирования:

Разделяйте фазы теста

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

Чтобы быст­рее нахо­дить и вос­при­ни­мать эти фазы, отде­ляйте их друг от друга пере­во­дом строки:

// Плохо: всё в кучу
it('wipes user data from state', () => {
  const state = { userName: 'Tony Stark', userFirstName: 'Tony', userEmail: 'tony@stark.com' }
  expect(reducer(state, { type: 'SWITCH_TO_INITIAL_SCREEN' })).toEqual(jasmine.objectContaining({
    userName: null,
    userFirstName: null,
    userEmail: null,
  }))
})
​
// Хорошо: фазы отде­лены, видно, что и как про­ве­ряем
it('wipes user data from state', () => {
  const state = {  // Настройка
    userName: 'Tony Stark',
    userFirstName: 'Tony',
    userEmail: 'tony@stark.com',
  }
  ​      
  const newState = reducer(state, { type: 'SWITCH_TO_INITIAL_SCREEN' }) // Испы­та­ние
  ​
  expect(newState).toEqual(jasmine.objectContaining({ // Про­верка
    userName: null,
    userFirstName: null,
    userEmail: null,
  }))
})



Пишите для людей

Тесты читают люди. Чем чело­веч­нее, лако­нич­нее и понят­нее они напи­саны, тем легче людям с ними рабо­тать. Исполь­зуйте опи­са­ния тестов, понят­ные чело­веку, а не машине:

// Плохо: бес­по­лез­ное опи­са­ние
it 'works'
​
// Хорошо
it 'sends welcome email to presentee'
​
​
// Плохо: гово­рим с маши­нами
it 'sets lock_status to nil'
​
// Хорошо
it 'unlocks next achievement'
​
​
// Плохо: опять гово­рим с маши­нами
it 'calls UsersMailer.reset_notification'
​
// Хорошо
it 'sends password reset instructions'

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

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

Комментарии

Юрий Хан
13 февраля 2020

А вот, допустим, у нас есть функция и мы хотим тестировать, что при недопустимом аргументе она выбрасывает исключение. И допустим, что фреймворк тестирования предоставляет для этого синтаксическую конструкцию, в которой сначала пишется ожидаемый класс исключения, а потом в теле — код, который должен это исключение выбросить.
def test_invalid_format():     with pytest.raises(ValueError): # проверка         int('invalid integer') # испытание
Как в этом случае разделять фазы?


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

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

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

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

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




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

Как просить коллег о помощи, как оценить код программиста, навигация между книгами бюро, как научиться спрашивать 2 1 Трудно найти вдохновение на текст 2 Какой фотоаппарат выбрать для путешествий? 2