Я знаю, что одним из определяющих принципов разработки через тестирование является то, что вы сначала пишете свои модульные тесты, а затем пишете код для прохождения этих модульных тестов, но нужно ли делать это таким образом?
Я обнаружил, что часто не знаю, что тестирую, пока не напишу это, в основном потому, что последние несколько проектов, над которыми я работал, в большей степени основывались на проверке концепции, а не были разработаны.
Раньше я пытался писать свои модульные тесты, и это может быть полезно, но мне это не кажется естественным.
Это должен быть настоящий вопрос, а не очередной опрос. Я бы предпочел, чтобы Омар немного изменил формулировку вопроса, чтобы сделать его правильным, а не вопросом типа опроса.
Я счастлив перефразировать, но не уверен, на что это переформулировать.
Как насчет чего-нибудь вроде «Когда лучше всего писать модульные тесты, до того, как вы начнете кодировать, или после того, как закончите?»
Мне было бы интересно узнать методологию, которую все используют для написания своих модульных тестов. Пытаются ли они полностью разобраться в проблеме перед написанием тестов? Или они пишут тесты, основанные на текущем понимании, и изменяют эти тесты позже, если понимание изменится?
Омар, я пробовал отредактировать ваш вопрос, чтобы сделать его менее субъективным. Если вы считаете, что я сделал из него хеш-код, не стесняйтесь откатывать мои правки.
Дэвид, мне это нравится.





Не всегда, но я считаю, что это действительно помогает, когда я это делаю.
Я обычно пишу их по мере написания кода. В лучшем случае я напишу тесты, существует ли класс / модуль, прежде чем я его напишу.
Я не планирую достаточно далеко вперед и настолько подробно, чтобы написать тест раньше, чем код, который он собирается тестировать.
Я не знаю, является ли это ошибкой в моем мышлении или методе или просто в TIMTOWTDI.
TIMTOWTDI? что это вообще такое?
Есть несколько способов сделать это. Код + тесты примерно в то же время еще можно тестировать. Набросайте код, напишите хорошие тесты, доделайте код.
Я не пишу сначала фактические модульные тесты, но я создаю тестовую матрицу, прежде чем начну кодировать, перечисляя все возможные сценарии, которые необходимо будет протестировать. Я также составляю список случаев, которые необходимо будет протестировать при внесении изменений в любую часть программы в рамках регрессионного тестирования, которое будет охватывать большинство базовых сценариев в приложении в дополнение к полному тестированию той части кода, которая измененный.
Были учеба, которые показывают, что модульные тесты, написанные после написания кода, являются лучшими тестами. Предостережение заключается в том, что люди не склонны писать их после мероприятия. Так что TDD - хороший компромисс, поскольку, по крайней мере, тесты написаны.
Так что, если вы пишете тесты после того, как написали код, это хорошо для вас, я бы посоветовал вам придерживаться этого.
Я склонен обнаруживать, что делаю смесь. Чем лучше я понимаю требования, тем больше тестов я могу написать заранее. Когда требования - или мое понимание проблемы - слабые, я обычно пишу тесты позже.
не могли бы вы дать ссылки на исследования? Спасибо
Ссылка в этом ответе указывает на сообщение в блоге, в котором ставятся под сомнение результаты исследования, а не на фактические исследования с разными результатами. В результате я бы обесценил достоверность первой строки этого ответа.
Ссылка указывает на подробный анализ выводов, сделанных командой исследования, и причин, по которым их выводы были неправильными. Исследование на самом деле ясно показало, что тест после теста лучше, чем тест до него (при условии, что он проводится).
Я начинаю с того, как я хотел бы назвать свой «модуль» и заставить его компилироваться. нравиться:
picker = Pick.new
item=picker.pick('a')
assert item
тогда я создаю
class Pick
def pick(something)
return nil
end
end
затем я продолжаю использовать Pick в моем «тестовом» случае, чтобы увидеть, как я бы хотел, чтобы он вызывался, и как я буду относиться к различным типам поведения. Всякий раз, когда я понимаю, что у меня могут быть проблемы с некоторыми границами или какая-то ошибка / исключение, я пытаюсь запустить его и получить новый тестовый пример.
Итак, короче. да. Соотношение, когда вы проходите тестирование раньше, намного выше, чем когда вы его не проводите.
Помните, что с экстремальным программированием ваши тесты фактически являются документацией. Итак, если вы не знаете, что тестируете, значит, вы не знаете, что должно делать ваше приложение?
Вы можете начать с "Историй", которые могут выглядеть примерно так:
«Пользователи могут получить список вопросов»
Затем, когда вы начнете писать код для решения модульных тестов. Для решения вышеуказанной проблемы вам понадобится как минимум пользователь и класс вопросов. Итак, вы можете начать думать о полях:
«Класс пользователя имеет имя DOB-адрес TelNo Locked Fields»
и т.п. Надеюсь, это поможет.
Лукавый
Да, если вы используете настоящие принципы TDD. В противном случае, пока вы пишете модульные тесты, у вас все получается лучше, чем у большинства.
По моему опыту, обычно проще написать тесты до кода, потому что, делая это таким образом, вы получаете простой инструмент отладки, который можно использовать при написании кода.
Я пишу их одновременно. Я создаю скелетный код для нового класса и тестового класса, а затем пишу тест для некоторых функций (который затем помогает мне увидеть, как я хочу, чтобы новый объект вызывался), и реализую его в коде.
Обычно я не получаю элегантный код с первого раза, это обычно довольно взломанный. Но как только все тесты заработают, вы можете проводить рефакторинг до тех пор, пока не получите что-то довольно аккуратное, аккуратное и надежное.
Здесь есть несколько хороших комментариев, но я думаю, что одна вещь игнорируется.
написание тестов в первую очередь движет вашим дизайном. Это важный шаг. Если вы пишете тесты «одновременно» или «вскоре после», вы можете упустить некоторые конструктивные преимущества выполнения TDD в микрошагах.
Поначалу это кажется действительно дрянным, но удивительно наблюдать, как вещи разворачиваются на ваших глазах в дизайн, о котором вы изначально не думали. Я видел, как это случилось.
TDD - это сложно, и это не для всех. Но если вы уже применяете модульное тестирование, попробуйте его в течение месяца и посмотрите, как оно влияет на ваш дизайн и производительность.
Вы проводите меньше времени в отладчике и больше времени на размышления о внешнем дизайне. Это два огромных плюса в моей книге.
Как вы сначала создаете модульный тест? IDE выдаст много предупреждений и ошибок, а интеллект не будет работать! Я не понимаю, как это сделать.
Пусть IDE сгенерирует заглушку метода. Сначала все тесты не пройдут.
@Pokus - быстрый ответ ... Я выключаю автоматическое завершение операторов, чтобы intellisense не мешал мне. CTRL + пробел всегда будет вызывать его, если мне это нужно. Я очень рекомендую ReSharper (jetbrains.com/resharper). Это сильно помогает моему рабочему процессу TDD.
Я думаю, идея состоит в том, что вы сначала пишете interfae и реализуете его с помощью заглушек, которые (в C#) генерируют нереализованные исключения. Все ваши тесты не пройдут, и написание кода заставит тесты проходить один за другим.
@Ben - вы можете очистить список символов, которые будут фиксироваться из списка автозаполнения; тогда это сделает только TAB. Лучшее обоих миров.
правда ли, что TDD только для опытных людей? как новый программист могу я еще попробовать?
Я думаю, что написание теста в первую очередь помогает определить, что на самом деле должен делать код. Слишком часто люди не имеют четкого определения того, что должен делать код или как он должен работать. Они просто начинают писать и придумывают это по ходу дела. Создание теста в первую очередь заставляет вас сосредоточиться на том, что будет делать код.
Написание тестов сначала определяет, как будет выглядеть ваш код, т.е. он имеет тенденцию делать ваш код более модульным и тестируемым, поэтому вы не создаете «раздутых» методов с очень сложными и перекрывающимися функциями. Это также помогает выделить все основные функции в отдельные методы для упрощения тестирования.
TDD - это не тесты, а то, как тесты управляют вашим кодом. Итак, в основном вы пишете тесты, чтобы позволить архитектуре развиваться естественным образом (и не забывайте проводить рефакторинг !!! иначе вы не получите от этого большой пользы). То, что у вас есть арсенал регрессионных тестов и исполняемая документация после этого, является приятным побочным эффектом, но не основной причиной TDD.
Итак, мой голос: Сначала тест
PS: И нет, это не означает, что вам не нужно планировать свою архитектуру раньше, но что вы можете переосмыслить ее, если тесты скажут вам это сделать !!!!
Директивы - это предложения о том, как вы могли бы сделать что-то для улучшения общего качества или производительности или даже того и другого конечного продукта. Это ни в коем случае не законы, которые нужно соблюдать, если только вы не попадете в мгновение ока богом правильной практики кодирования.
Вот мой компромисс в отношении дубля, и он мне показался весьма полезным и продуктивным.
Обычно сложнее всего понять требования, а за ними - удобство использования вашего класса, API, пакета ... Затем - фактическая реализация.
Итак, да, я пишу тесты перед кодированием, но никогда раньше я не понимал, что нужно сделать с определенным уровнем детализации. Обычно это тесты высокого уровня, которые рассматривают все как черный ящик. Обычно остается в виде интеграционных тестов и не претерпевает значительных изменений после стабилизации интерфейсов.
Затем я пишу несколько тестов (модульных тестов) для реализации, стоящей за ним, они будут намного более подробными и будут часто меняться по мере развития реализации, по мере ее оптимизации и расширения.
Это строго говоря TDD? Экстремальный? Гибкий...? что бы ни... ? Я не знаю, и, честно говоря, мне все равно. Работает для меня. Я корректирую его по мере необходимости и по мере развития моего понимания практики разработки программного обеспечения.
мои 2 цента
Я руководил командами разработчиков последние 6-7 лет. Что я могу сказать наверняка, так это то, что как разработчик и разработчики, с которыми я работал, имеет феноменальную разницу в качестве кода, если мы знаем, как наш код вписывается в общую картину.
Разработка через тестирование (TDD) помогает нам ответить на вопрос «Что?» прежде чем мы ответим "Как?" и это имеет большое значение.
Я понимаю, почему могут возникнуть опасения, что он не будет следовать ему при разработке / проектировании PoC. И вы правы, возможно, нет полного смысла следовать этому процессу. В то же время я хотел бы подчеркнуть, что TDD - это процесс, который попадает в фазу разработки (я знаю, что это звучит устаревшим, но вы понимаете, что :) когда спецификации низкого уровня ясны.
Лично я считаю, что модульные тесты сильно теряют свою эффективность, если их не провести до написания кода.
Извечная проблема с тестированием заключается в том, что как бы мы ни думали об этом, мы никогда не придумаем все возможные сценарии, чтобы написать тест, который нужно покрыть.
Очевидно, что само модульное тестирование не предотвращает этого полностью, так как это ограничительное тестирование, рассматривающее только одну единицу кода, не охватывающую взаимодействия между этим кодом и всем остальным, но оно обеспечивает хорошую основу для написания чистого кода в первую очередь, который должен хотя бы ограничить шансы проблем взаимодействия между модулями. Я всегда придерживался принципа сохранения кода настолько простым, насколько это возможно - на самом деле я считаю, что это один из ключевых принципов TDD.
Итак, начнем с теста, который в основном говорит о том, что вы можете создать класс этого типа и построить его теоретически, написав тест для каждой строки кода или, по крайней мере, покрывая каждый маршрут через конкретный фрагмент кода. Создавайте на ходу! Очевидно, основан на предварительном предварительном дизайне, созданном изначально, чтобы дать вам основу для работы.
Как вы говорите, это очень неестественно для начала и может показаться пустой тратой времени, но я на собственном опыте убедился, что это окупается в долгосрочной перспективе, когда статистика дефектов приходит и показывает модули, которые были полностью написаны с использованием TDD. имеют гораздо меньше дефектов с течением времени, чем другие.
Я занимаюсь программированием 20 лет и практически никогда не писал ни строчки кода, на которой не запускал бы какой-то модульный тест - честно говоря, я знаю, что люди делают это все время, но как кто-то может выпустить строка кода, которая не проходила какой-либо тестовый прогон, мне не по силам.
Часто, если нет тестовой среды, я просто пишу main () в каждом написанном мной классе. Это добавляет немного беспорядка в ваше приложение, но кто-то всегда может удалить его (или закомментировать), если он хочет, я думаю. Мне действительно хотелось бы, чтобы в вашем классе был только метод test (), который автоматически компилировался для сборок выпуска - мне нравится, что мой тестовый метод находится в том же файле, что и мой код ...
Итак, я занимался разработкой как через тестирование, так и через тестирование. Могу сказать вам, что TDD действительно может помочь, когда вы начинающий программист. Это поможет вам научиться видеть свой код «извне», что является одним из самых важных уроков, которые может усвоить программист.
TDD также помогает вам начать работу, когда вы застряли. Вы можете просто написать очень маленький фрагмент, который, как вы знаете, должен делать ваш код, а затем запустить его и исправить - это вызывает привыкание.
С другой стороны, когда вы добавляете к существующему коду и в значительной степени точно знаете, что хотите, это пустая трата времени. Ваш «Другой код» часто проверяет ваш новый код на месте. Вам по-прежнему нужно быть уверенным, что вы тестируете каждый путь, но вы получите хорошее покрытие, просто запустив тесты из внешнего интерфейса (за исключением динамических языков - для тех, у вас действительно должны быть модульные тесты для всего, несмотря ни на что).
Между прочим, когда я работал над довольно большим проектом Ruby / Rails, у нас был очень высокий% тестового покрытия. Мы реорганизовали основной, центральный класс модели на два класса. Это заняло бы у нас два дня, но с учетом всех тестов, которые нам потребовались для рефакторинга, это закончилось ближе к двум неделям. Тесты НЕ полностью бесплатны.
Это помогает, когда вы пишете то, что привыкли писать, сначала написать все то, что вы регулярно проверяли бы, а затем написать эти функции. В большинстве случаев не эти функции являются наиболее важными для программного обеспечения, которое вы пишете. Теперь, с другой стороны, нет серебряных пуль, и никогда не следует следовать букве. Суждение разработчика играет большую роль при принятии решения об использовании разработки, управляемой тестированием, а не последней разработки, основанной на тестировании.
До, во время и после. Раньше это часть спецификации, контракт, определение работы Это когда особые случаи, когда при внедрении обнаруживаются неверные данные, исключения. После - обслуживание, развитие, изменение, новые требования.
Я не уверен, но из вашего описания я чувствую, что может быть неправильное понимание того, что на самом деле означает test-first. Это означает, что нет означает, что вы сначала пишете свои тесты все. Это действительно означает, что у вас очень плотный цикл
Один цикл (3-5) обычно занимает всего пару минут. Используя этот метод, вы фактически эволюционировать разрабатываете, пока вы пишете тесты и производственный код параллельно. Здесь вообще не так уж много начального дизайна.
По вопросу о том, что это «необходимо» - нет, очевидно, нет. Было бесчисленное количество успешных проектов без TDD. Но есть убедительные доказательства того, что использование TDD обычно приводит к значительно более высокому качеству, часто без отрицательного воздействия на производительность. И это тоже весело!
Да, и что касается ощущения «неестественного», это просто вопрос того, к чему вы привыкли. Я знаю людей, которые очень любят получать зеленую полосу (типичный знак xUnit, обозначающий «все тесты пройдены») каждые пару минут.
Сейчас так много ответов, и все они разные. Это полностью соответствует действительности. Все делают по-разному. Я думаю, что существует огромное недоразумение в отношении модульного тестирования. Мне кажется, что люди слышали о TDD и сказали, что это хорошо. Затем они начали писать модульные тесты, не понимая, что такое TDD на самом деле. Они только что получили часть «о да, мы должны написать тесты», и они согласны с этим. Они также слышали о том, что «вы должны сначала написать свои тесты», но они не относятся к этому серьезно.
Я думаю, это потому, что они не понимают преимуществ test-first, которые, в свою очередь, можно понять только после того, как вы проделаете это таким образом в течение некоторого времени. И они, кажется, всегда находят 1.000.000 оправданий, почему им не нравится сначала писать тесты. Потому что это слишком сложно, когда выясняется, как все будет сочетаться друг с другом и т. д.
Самое смешное, если они начнут спорить: «Я не убежден в том, что это первое испытание, но я никогда не делал этого таким образом» ... отлично ...
Интересно, откуда изначально взялось модульное тестирование. Потому что, если концепция действительно происходит от TDD, то просто смешно, как люди ошибаются.
Пожалуйста, сделайте это сообщество вики, так как это больше, чем опрос, чем реальный вопрос.