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

89

Я смотрел веб-трансляции Роба Коннериса в приложении MVCStoreFront и заметил, что он тестировал даже самые обыденные вещи, например:

public Decimal DiscountPrice
{
   get
   {
       return this.Price - this.Discount;
   }
}

Был бы такой тест:

[TestMethod]
public void Test_DiscountPrice
{
    Product p = new Product();
    p.Price = 100;
    p.Discount = 20;
    Assert.IsEqual(p.DiscountPrice,80);
}

Хотя я полностью сторонник модульного тестирования, я иногда задаюсь вопросом, действительно ли полезна эта форма первой разработки теста, например, в реальном процессе у вас есть 3-4 уровня над кодом (бизнес-запрос, документ требований, документ архитектуры) , где фактическое определенное бизнес-правило (Цена со скидкой - Цена - Скидка) могло быть определено неверно.

Если это так, то ваш модульный тест ничего для вас не значит.

Кроме того, ваш модульный тест - еще одна точка отказа:

[TestMethod]
public void Test_DiscountPrice
{
    Product p = new Product();
    p.Price = 100;
    p.Discount = 20;
    Assert.IsEqual(p.DiscountPrice,90);
}

Теперь тест ошибочен. Очевидно, что в простом тесте это не проблема, но предположим, что мы тестировали сложное бизнес-правило. Что мы здесь получаем?

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

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

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

РЕДАКТИРОВАТЬ: пара людей постоянно упоминает, что тестирование помогает обеспечить соблюдение спецификации. По моему опыту, спецификации тоже чаще всего были неправильными, но, возможно, я обречен работать в организации, где спецификации написаны людьми, которым не следует писать спецификации.

FlySwat
источник
5
во многих случаях юнит-тест - это спецификация и документация!
Стивен А. Лоу
32
... а затем модульный тест модульного теста модульного теста ... но как насчет теста unit ^ 4 и теста unit ^ 5 ... aaaaaaaaahhhhhhhhh!
dacracot
14
Никакое количество тестов не спасет вас от неправильной спецификации.
Bill the Lizard
4
Кто-нибудь еще только что слышал звук, похожий на хлопок одной ладони?
gnovice 02
9
Я думаю, уместная цитата: «Это просто черепахи до самого конца».
Куинн Тейлор,

Ответы:

63

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

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

В-третьих, некоторые утверждают, что TDD решает эту проблему. То есть, если вы просто напишете 20 тестов, и они пройдут, вы не совсем уверены, что они на самом деле что-то тестируют. Но если каждый тест, который вы написали изначально, не удался , а затем вы его исправили, вы гораздо более уверены, что он действительно тестирует ваш код. ИМХО, на это уходит больше времени, чем оно того стоит, но это процесс, который пытается решить вашу проблему.

Джейсон Коэн
источник
2
Когда я играю в адвоката дьявола, я вижу дополнительные уровни как больше возможных точек отказа, что не прибавляет мне уверенности. В моей реальной работе я работаю со многими командами в сильно распределенном предприятии SOA. Каждая из этих команд может поставить под угрозу проект, если их уровень выйдет из строя.
FlySwat
2
Вот почему вы используете фиктивные объекты для тестирования каждого слоя отдельно.
Toon Krijthe
10
Отлично, поэтому мой тест пройдет с использованием IMockedComplexObject, но когда я действительно использую ComplexObject в реальном мире, он терпит неудачу ... Я снова ничего не получил.
FlySwat
16
@Jonathan - нет, вы обрели уверенность в том, что ваш код работает - при условии, что вы разработали интерфейс ComplexObject и соответствующим образом протестировали с этим интерфейсом. В худшем случае вы поймете, что ваше понимание ComplexObject не то, что вы ожидали.
tvanfosson
9
@FlySwat: В ответ на ваш комментарий об IMockedComplexObject я цитирую комментарий Cwash по другому ответу: «Вы не издеваетесь над тем, что пытаетесь проверить, вы издеваетесь над тем, что вы не пытаетесь тестировать».
Брайан,
39

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

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

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

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

Кстати, лично я бы не стал использовать 100 в качестве цены в тестовом примере (точнее, если бы я это сделал, я бы добавил еще один тест с другой ценой). Причина в том, что кто-то в будущем может подумать, что Скидка должна быть процентной. Одна из целей таких тривиальных тестов - убедиться, что ошибки при чтении спецификации исправлены.

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

Стив Джессоп
источник
4
Неправильный тест позволит неработающему коду выйти на волю. Вот где вводится неудача. Это дает ложное чувство уверенности.
FlySwat
9
Это правда, но отсутствие теста также позволяет выявить сломанный код. Ошибка заключается в том, что если код проходит модульное тестирование, он должен быть правильным - я излечился от этого довольно рано в своей карьере. Таким образом, сломанный модульный тест не выпускает сломанный код на волю, он только выпускает его в интеграционное тестирование.
Стив Джессоп,
7
Кроме того, даже неправильный тест может выявить неработающий код, если он содержит ошибки, отличные от реализации. Я считаю, что тесты не обязательно должны быть правильными, они нужны для того, чтобы привлечь ваше внимание к проблемным областям.
Стив Джессоп,
2
очень интересный ответ.
Питер,
22

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

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

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

Наконец, ответ на ваш главный вопрос « Как вы проводите модульное тестирование модульного теста? » Заключается в том, что вам не нужно этого делать. Каждый модульный тест должен быть до безумия простым. Вызовите метод с конкретным входом и сравните его с ожидаемым результатом. Если спецификация метода изменится, вы можете ожидать, что некоторые модульные тесты для этого метода также должны измениться. Это одна из причин, по которой вы проводите модульное тестирование на таком низком уровне детализации, поэтому необходимо изменить только некоторые модульные тесты. Если вы обнаружите, что тесты для множества различных методов меняются при одном изменении требования, возможно, вы не проводите тестирование на достаточно высоком уровне детализации.

Билл Ящерица
источник
«Вызвать метод с конкретным входом и сравнить его с ожидаемым выходом». но что, если вывод - сложный тип ... как документ XML. Вы не можете просто "==", вам нужно будет написать конкретный код сравнения, и тогда, возможно, ваш метод сравнения может быть ошибочным ??
Энди
@andy: Вы должны протестировать свой метод сравнения отдельно. После того, как вы его тщательно протестировали, вы можете положиться на его работу в других тестах.
Bill the Lizard
здорово, спасибо Билл. Я начал работать на новом месте, и это мой первый раз с модульным тестированием. Я думаю, что в принципе это работает, и мы используем круиз-контроль там, где он действительно полезен, но большие наборы тестов, похоже, постигает та же участь, что и унаследованный код ... Я просто не уверен в этом ...
Энди
11

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

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

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

[РЕДАКТИРОВАТЬ]

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

tvanfosson
источник
Возможно, в этом моя проблема. Я могу визуализировать алгоритм бизнес-правила намного проще, чем визуализировать результат, поэтому у меня нет проблем с реализацией самого кода, но я считаю издевательство над правилом излишним. Может, дело в том, как я думаю.
FlySwat
Это именно то, что вы делаете в модульном тесте. Разбейте этот алгоритм на части и проверьте каждую часть. Обычно я обнаруживаю, что мой код записывается сам, потому что я уже написал ожидаемое значение в своем модульном тесте.
tvanfosson
Mock - это перегруженный термин в тестовой среде. Вы не издеваетесь над тем, что пытаетесь протестировать, вы издеваетесь над тем, что не пытаетесь протестировать ... Когда вы пишете тест для своего бизнес-правила, вы создаете код, который его вызывает - он вовсе не насмехается над ним .
cwash 03
@cwash - я не уверен, как ваш комментарий относится к моему ответу. Я не упомянул издевательство ... и согласен с вашим наблюдением.
tvanfosson 03
@tvanfosson - мой последний комментарий был в ответ на @FlySwat "... высмеивание правила как избыточного". Извините, я забыл указать.
cwash 03
10

Как проверить тест ? Мутационное тестирование - ценный метод, который я лично использовал с удивительно хорошим эффектом. Прочтите связанную статью для получения более подробной информации и ссылок на еще более академические ссылки, но в целом он «проверяет ваши тесты», изменяя исходный код (например, изменяя «x + = 1» на «x - = 1»), а затем повторный запуск ваших тестов, гарантируя, что хотя бы один тест не пройден. Любые мутации, не вызывающие сбоев теста, помечаются для дальнейшего исследования.

Вы будете удивлены, узнав, как вы можете получить 100% покрытие строк и веток с помощью набора тестов, которые выглядят исчерпывающими, и в то же время вы можете фундаментально изменить или даже закомментировать строку в своем источнике без каких-либо жалоб со стороны тестов. Часто это сводится к тому, что тестирование не с правильными входными данными, чтобы охватить все граничные случаи, иногда это более тонко, но во всех случаях я был впечатлен тем, как много из этого получилось.

Анджей Дойл
источник
1
+1 интересная концепция, о которой я еще не слышал
Вим Коенен
9

При применении разработки через тестирование (TDD) каждый начинает с провала теста. Этот шаг, который может показаться ненужным, на самом деле здесь, чтобы убедиться, что модульный тест что-то тестирует. В самом деле, если тест никогда не терпит неудачу, он не приносит никакой пользы и, что еще хуже, приводит к ложной уверенности, поскольку вы будете полагаться на положительный результат, который ничего не доказывает.

При строгом соблюдении этого процесса все «юниты» защищены сеткой безопасности, которую создают юнит-тесты, даже самые обычные.

Assert.IsEqual(p.DiscountPrice,90);

Нет причин, по которым тест развивается в этом направлении - или я что-то упускаю из ваших рассуждений. Когда цена равна 100, а скидка 20, цена со скидкой равна 80. Это похоже на инвариант.

Теперь представьте, что ваше программное обеспечение должно поддерживать другой вид скидки, основанной на процентах; возможно, в зависимости от приобретенного объема ваш метод Product :: DiscountPrice () может стать более сложным. И возможно, что внесение этих изменений нарушит простое правило скидки, которое у нас было изначально. Затем вы увидите значение этого теста, который немедленно обнаружит регресс.


Красный - Зеленый - Рефакторинг - это напоминание о сути процесса TDD.

Красный относится к красной полосе JUnit, когда тест не проходит.

Зеленый - это цвет индикатора выполнения JUnit, когда все тесты пройдены.

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


Теперь, чтобы обратиться к вашей точке зрения о «3-4 уровнях над кодом», это верно для традиционного (похожего на водопад) процесса, а не для гибкого процесса разработки. А гибкость - это мир, из которого исходит TDD; TDD - краеугольный камень экстремального программирования .

Agile - это прямая коммуникация, а не бесконечные документы с требованиями.

филант
источник
8

Хотя я полностью сторонник модульного тестирования, я иногда задаюсь вопросом, действительно ли эта форма первой разработки теста действительно полезна ...

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

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

... [I] В реальном процессе, у вас есть 3-4 уровня над кодом (бизнес-запрос, документ с требованиями, документ архитектуры), где фактически определенное бизнес-правило (цена скидки - это цена - скидка) может быть неправильно определено. В таком случае ваш модульный тест ничего не значит для вас.

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

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

Кроме того, ваш модульный тест - еще одна точка отказа ...

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

Если вы пишете тесты после кода, вы рискуете написать «плохой» тест, потому что для того, чтобы убедиться, что ваш тест действительно работает, вам нужно увидеть, что он сломан и работает. Когда вы пишете тесты после кода, это означает, что вам нужно «вскрыть ловушку» и ввести ошибку в код, чтобы увидеть, что тест не прошел. Большинство разработчиков не только обеспокоены этим, но и утверждают, что это пустая трата времени.

Что мы здесь получаем?

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

Говоря о Feathers, есть два замечательных ресурса, которые вы должны изучить по этому поводу:

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

[I] Если цена со скидкой неверна, команда тестирования все равно найдет проблему, как модульное тестирование сохранило работу?

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

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

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

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

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

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

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

мыть
источник
7

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

Как тестирование будет стоить затраченных усилий? По моему опыту, как минимум четырьмя способами, по крайней мере, при разработке через тестирование:

  • это поможет вам создать хорошо развязанный дизайн. Вы можете использовать только хорошо развязанный код модульного тестирования;
  • это помогает вам определить, когда вы закончите. Необходимость указывать необходимое поведение в тестах помогает не создавать функциональные возможности, которые вам на самом деле не нужны, и определять, когда они будут завершены;
  • он дает вам страховочную сетку для рефакторинга, что делает код более восприимчивым к изменениям; а также
  • это экономит вам много времени на отладку, что ужасно дорого (я слышал оценки, что обычно разработчики тратят до 80% своего времени на отладку).
Илья Пройс
источник
5

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

Если правила изменятся, тест не удастся, и это хорошо. Так что в этом случае вам также придется изменить тест.

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

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

Мультяшный Крайте
источник
4

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

Джим С
источник
Это не касается ни одной из моих мыслей. Я понимаю основную мантру TDD ... Я не вижу пользы.
FlySwat
4

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

Johnsyweb
источник
3

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

Обычно это легче увидеть на чем-то большем, чем на тривиальном примере ... и на тривиальных примерах, ну, если вы каким-то образом испортите модульный тест, человек, просматривающий его, поймает ошибку в тесте или ошибку в коде, или и то и другое. (Они пересматриваются, не так ли?) Как указывает Тванфоссон , модульное тестирование - это лишь часть плана SQA.

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

Дэйв ДюПлантис
источник
3

Я понимаю вашу точку зрения, но она явно преувеличена.

Ваш аргумент в основном таков: тесты приводят к неудачам. Поэтому тесты плохие / пустая трата времени.

Хотя в некоторых случаях это может быть правдой, вряд ли большинство.

TDD предполагает: больше тестов = меньше отказов.

Тесты скорее выявляют точки отказа, чем знакомят с ними.

Луч
источник
1

Здесь может помочь еще большая автоматизация! Да, написание модульных тестов может потребовать много работы, поэтому воспользуйтесь некоторыми инструментами, которые помогут вам. Взгляните на что-то вроде Pex от Microsoft, если вы используете .Net. Он автоматически создает для вас наборы модульных тестов, исследуя ваш код. Он предложит тесты, которые дадут хорошее покрытие, пытаясь охватить все пути через ваш код.

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

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


источник
1

Я немного подумал о том, как правильно ответить на этот вопрос, и хотел бы провести параллель с научным методом. ИМО, вы могли бы перефразировать этот вопрос: «Как вы проводите эксперимент?»

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

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

В отличие от экспериментов , у нас есть хитрость в рукаве, чтобы убедиться, что наши тесты действительны, кроме конвергентной достоверности. Мы можем грамотно ввести ошибку, которая, как мы знаем, должна быть обнаружена тестом, и посмотреть, действительно ли тест завершился неудачно. (Если бы мы только могли сделать это в реальном мире, мы бы гораздо меньше зависели от этой конвергентной валидности!) Более эффективный способ сделать это - посмотреть, как ваш тест завершится неудачно, прежде чем реализовывать его (красный шаг в Red, Green, Refactor ).

мыть
источник
1

При написании тестов нужно использовать правильную парадигму.

  1. Начните с написания ваших тестов.
  2. Убедитесь, что они не смогли начать с.
  3. Заставьте их пройти.
  4. Проверяйте код, прежде чем проверять свой код (убедитесь, что тесты проверены.)

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

Джонатан
источник
0

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

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


источник