Как вы сделали модульное тестирование более приятным? [закрыто]

18

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

Это не вопрос «что такое правильный путь для модульного тестирования». Я просто хочу знать маленькие личные уловки, которые уменьшают скуку (смею сказать) написания юнит-тестов.

Preets
источник
1
Я люблю писать модульные тесты и другие тесты отчасти потому, что почти все остальные отстой в этом (иногда они также отстают в создании инструментов, которые я тестирую) Нет, я не отстой как разработчик. Мне просто нравится удобство использования, привлекательность глаз и автоматизация. MbUnitБиблиотека изменила мою жизнь. Авто тестирование важно. Автоматическое тестирование экономит время. Авто тестирование экономит деньги. Автоматическое тестирование может спасти жизни. Авто тестирование это единственный способ. Автотестирование - это еще одна сеть безопасности. Когда я один из 50 человек, работающих над огромной архитектурой, я чувствую себя еще одним кирпичиком в стене. С юнит-тестами я в контроле.
Работа
Лень и разочарование при юнит-тестировании - это нормальная реакция на работу, которую наш мозг считает бесполезной. Я ненавижу писать и поддерживать модульные тесты, которые имеют небольшую или отрицательную рентабельность инвестиций. Тем не менее, написание полезных тестов - приятная задача, но это умение самостоятельно распознавать, что полезно, а что - мусор. Есть парень, который пишет книгу на эту тему на основе своего блога, вы можете прочитать здесь: enterprisecraftsmanship.com/2016/06/01/…
KolA

Ответы:

22

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

Я считаю, что есть два способа модульного тестирования, которые действительно делают его приятным:

  1. Используя Test Driven Development (TDD) - сначала написание тестов позволяет мне подумать о следующей функциональности или поведении, которые мне нужны в моем коде. Я нахожусь в движении к своей конечной цели маленькими шагами и вижу ощутимый прогресс в достижении этой цели каждые несколько минут чрезвычайно полезным и приятным.
  2. Когда есть ошибки, вместо того, чтобы идти прямо к отладчику, это забавная задача - найти способ написать неудачный модульный тест, который воспроизводит ошибку. Чрезвычайно приятно наконец выяснить обстоятельства, которые делают ваш код неудачным, затем исправить его и посмотреть, как индикатор станет зеленым для нового неудачного теста (и останется зеленым для всех ваших существующих тестов).
Paddyslacker
источник
12

Самодовольное превосходство.

Я только полушутя «Посмотрите на меня, вырабатывая хорошие привычки в программировании! Это« модульное тестирование »- это то, чего я с десяти лет назад никогда бы не сделал - какой дурак! И просто подумайте обо всех ошибках, которые я собираюсь обнаружить в результате эту скучную, утомительную работу, которую я делаю сейчас - мой код будет потрясающим! Я точно получу повышение! * "

* - Нет, я не буду.

Я нахожу это как тренировка или здоровое питание; до тех пор, пока не начнутся ощутимые выгоды («Святые шары, я действительно ЕСМЬ ловлю кучу ошибок регрессии, которые могли бы попасть в производство!»), моральная гордость от осознания того, что вы делаете Правильное, может помочь вам нести вас. через.

BlairHippo
источник
7

Во-первых, я почти никогда не сижу там и не пишу юнит-тесты. Модульные тесты - это средство для достижения цели, а не самоцель. Они являются способом ответа «выполняет ли этот код основную задачу, которую он должен».

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

def fact x
  if x == 0
    1
  else 
    x * fact(x-1)
  end
end

>> fact 10
=> 3628800
>> fact 7
=> 5040

Но теперь вы обнаружите ошибку:

>> fact -1
SystemStackError: stack level too deep
    from (irb):2:in `fact'
    from (irb):5:in `fact'
    from (irb):10

Итак, вы исправите это:

def fact x
  if x < 0
    raise "Can't take the factorial of a negative number"
  elsif x == 0
    1
  else 
    x * fact(x-1)
  end
end

>> fact -1
RuntimeError: Can't take the factorial of a negative number
    from (irb):3:in `fact'
    from (irb):10

Но теперь вы действительно должны проверить, чтобы убедиться, что он все еще работает:

>> fact 10
=> 3628800
>> fact 7
=> 5040

Как видите, вы продолжаете повторять одни и те же тесты ... и вам приходится сравнивать результаты визуально. Модульное тестирование - это способ избежать повторения в этом случае; это уменьшает, сколько работы вам нужно сделать. И хотя это глупый маленький пример, в реальном мире это становится все более и более важным, и все более и более трудным для тестирования вручную. Это, конечно, означает, что люди просто не тестируют отдельные компоненты; они просто тестируют всю программу. Но потом появляются ошибки, и их гораздо сложнее найти. Или ошибки случаются, и они исправляются, но кто-то вводит ту же ошибку снова, потому что никто не добавил тестовый пример, чтобы убедиться, что этого не произошло. Или кто-то смотрит на большой кусок кода и говорит: «Я понятия не имею, что это должно делать, поскольку он не задокументирован и не имеет тестов ... если я исправлю эту ошибку, я понятия не имею, сломаю ли я что-нибудь еще в зависимости от этого; может быть, я просто перепишу это с нуля. "

Модульные тесты уменьшают всю дополнительную работу в этих случаях. Лучший способ сделать их забавными - убедиться, что люди понимают всю работу, которую они заменяют, и дополнительную гибкость, которая возникает благодаря знанию того, что должен делать каждый фрагмент кода. В некоторой степени люди должны иметь немного больше опыта в написании и поддержке большой базы кода, чтобы понять, насколько важным может быть модульное тестирование; если весь их код будет написан один раз и выброшен, они никогда не получат его.

И модульные тесты не должны быть написаны после факта, как дополнительная работа, когда у вас есть код, который вы «знаете», уже работает. Модульные тесты должны быть написаны в первую очередь или, как минимум, (так как вы иногда забываете написать их в первую очередь) сразу после написания кода. Это называется разработкой на основе тестирования, и она может помочь улучшить ваши API; если вы напишете тесты, которые вначале используют API, вы узнаете, где API труднее всего использовать, прежде чем даже писать код, и его можно будет значительно проще перепроектировать, чем если бы вы только добавляли тесты позже.

Брайан Кэмпбелл
источник
@ Биран, я согласен. Но все это делает это "правильным". Но как сделать это приятным? Даже чуть-чуть?
Улицы
@Prees Это приятно, потому что вы избегаете повторного ручного тестирования. Это гораздо приятнее, когда вы делаете это в первую очередь , а не после факта, потому что это становится частью процесса проектирования, а не рутинной работой по коду, который уже «работает».
Брайан Кэмпбелл
Итак, потратьте время на то, чтобы делать это плохо, так что если вы делаете это правильно, то вы чувствуете себя забавно в сравнении? ... Это может сработать, на самом деле ....
BlairHippo
@Biran, я согласен, нужно делать это «первым» - не только для устранения скуки, но и, я полагаю, это правильный путь, чтобы пожинать истинные преимущества модульного тестирования.
Улицы
@Biran, спасибо! Недавно я использовал TDD в своем хобби-проекте, и это изменило мой взгляд на модульное тестирование.
Улицы
5

Я не знаю. Что действительно делает модульное тестирование более приятным для меня, так это мысль о всех разочаровывающих, длительных, скучных и неуместных отладках, которые мне не придется проходить каждый раз, когда я изменяю программное обеспечение :)

back2dos
источник
2
Это интересно. Потому что лично, когда кто-то находит ошибку в моем коде, я погружаю голову в стыд, но в то же время процесс отладки для меня на самом деле довольно интересен и гораздо веселее, чем модульное тестирование. Это похоже на решение головоломки, где вы должны поймать эту хитрую ошибку.
Улицы
@Preets: согласен, иногда это может быть весело, но для меня дизайн гораздо интереснее, чем реализация. Поэтому я не люблю тратить много времени на реализацию. Я предпочитаю, чтобы он был прямым и предсказуемым, особенно потому, что он позволяет составлять более надежные графики. Как бы мне ни нравился процесс создания программного обеспечения, я думаю, что результат имеет решающее значение.
back2dos
О, я полностью согласен! Система со случайными ошибками может привести к бессонным ночам. Мой выбор был просто предпочтением в нереальном мире, где не было ничего, кроме веселья!
Улицы
3

Самодовольное превосходство, которое вы ощущаете, когда проверяете код, который является надежным, надежным и стабильным. И если вы пишете модульные тесты с помощью инструмента покрытия кода, вы можете похвастаться в своих комментариях проверки, что ваше покрытие кода составляет 90% или выше.

С Джонсон
источник
3

Очевидно, что удовлетворение от разработки в первую очередь вызывает удовлетворение, и вы испытываете чувство, когда ваш дизайн и тесты объединяются. Однако написание тестов для уже существующего / унаследованного кода может быть ошеломляющим и разочаровывающим. Когда наш проект находился в режиме обслуживания, я написал тесты для непроверенного кода, используя отчет о покрытии в качестве игры. Вы можете создать небольшую конкуренцию с собой и / или другими, чтобы увеличить количество покрытия. Конечно, вы можете зайти слишком далеко и создать плохие тесты, но это может быть хорошим мотиватором.

Мэтт Н
источник
поскольку устаревший код, как правило, нелегко тестировать, я испытываю трудности при написании хороших модульных тестов - поэтому процесс не только болезненен, но и результат (модульные тесты) также не особенно полезен: - / я нахожу это самым разочаровывающим .. Хотя игра с освещением хороша
Preets 11.10.10
1

Попробуй попасть в Поток . Ставьте перед собой жесткие, но достижимые цели. Что может быть целью в модульном тестировании? Например, старайтесь писать быстрее, сохраняя качество. Модульные тесты не требуют слишком много размышлений, поэтому ошибиться вряд ли. Сконцентрируйтесь на своей цели и часто проверяйте, чтобы увидеть, как вы приближаетесь к ней.

Тамас Селеи
источник
почему вы говорите, что юнит-тест не требует слишком много размышлений? Если вы работаете с TDD, это требует много размышлений. Разве это не правда?
Улицы
Вы правы, я не принял во внимание TDD.
Тамас Селеи
0

Иногда, чтобы получить мотивацию, я записываю свой текущий «охват кода» в начале дня. Затем каждый раз, когда я пишу тест и выполняю его, я запускаю комплект и обновляю номер покрытия. Это весело, и это помогает напомнить мне, почему я делаю это. (Есть и другие причины, но мне нравятся цифры. Может быть, это только я!)

Марси
источник
0

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

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

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

Неизбежно, ответ - громкое «нет».

Принимая мою судьбу, я продолжаю толкать эти квадратные объекты с буквами, цифрами и символами на них передо мной, которые мы называем клавиатурой, зная из первых рук, что при каждом нажатии на клавиатуру конец юнит-тестирования ближе, чем он была когда - либо был.

bugfoot
источник
Не каждый тест хорош или полезен. Это то, что обычно не упоминают TDD и другие тестовые евангелисты. Бьюсь об заклад, в некоторые редкие моменты вам действительно нравится модульное тестирование, когда вы знаете, что оно тестирует сложную логику, тестирование элегантно и не связано с реализацией, и довольно ненавистно, когда вы вынуждены тестировать тривиальную ерунду только для достижения некоторого целевого охвата кода, требуемого руководящие принципы проекта.
КолА
@KolA Вы правы, что существуют сложные модульные тесты, требующие творчества, но написание бесконечных модульных тестов может высосать радость даже из изначально интересных.
багфут