От новичка до гуру: Курсы программирования на CyberDuff

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

Я смотрел веб-трансляции Роба Коннериса в приложении 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, так как я пока не могу принять его как полезный. Я тоже хочу, потому что хочу оставаться прогрессивным, но для меня это просто не имеет смысла.

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

28.10.2008

  • во многих случаях модульный тест является спецификацией и документацией! 28.10.2008
  • ... а затем unit test модульный тест модульного теста ... но как насчет unit ^ 4 test и unit ^ 5 test ... aaaaaaaaahhhhhhhhh! 28.10.2008
  • Никакое количество тестов не спасет вас от неправильной спецификации. 29.10.2008
  • Голосование за мета-характер вопроса. : D Юнит-тест юнит-тест? Блестяще! 04.01.2009
  • Здесь есть Йо, чувак, я просто не хочу быть тем, кто его напишет. 17.02.2009
  • Кто-нибудь еще слышал только что звук, похожий на хлопок одной ладони? 02.06.2009
  • Я думаю, что уместная цитата - это просто черепахи до самого конца. 04.08.2009
  • Ах, рекурсивный TDD - темная сторона ... 17.05.2010
  • Не думаю, что кто-то еще указал на это, но я считаю, что в то время, когда Роб делал этот скринкаст, он сам изучал TDD и поэтому явно заставлял себя тестировать все приземленные вещи. Это был экзамен на то, как научиться тестировать, а не на то, как тестировать. 29.08.2010
  • Я не уверен, что у вас должен быть тест, который утверждает, что 100 - 80 = 20. Однако для DiscountPrice вы обязательно должны проверить, что он никогда не становится отрицательным. 21.12.2010

Ответы:


1

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

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

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

28.10.2008
  • Когда я играю в адвоката дьявола, я вижу дополнительные уровни как больше возможных точек отказа, что не прибавляет мне уверенности. На моей настоящей работе я работаю со многими командами в сильно распределенном SOA-предприятии. Каждая из этих команд может поставить под угрозу проект, если их уровень выйдет из строя. 28.10.2008
  • Вот почему вы используете фиктивные объекты для тестирования каждого слоя отдельно. 28.10.2008
  • Отлично, поэтому мой тест пройдет с использованием IMockedComplexObject, но когда я действительно использую ComplexObject в реальном мире, он терпит неудачу ... Я снова ничего не получил. 28.10.2008
  • @Jonathan - нет, вы обрели уверенность в том, что ваш код работает - при условии, что вы разработали интерфейс ComplexObject и соответствующим образом протестировали с этим интерфейсом. В худшем случае вы поймете, что ваше понимание ComplexObject не соответствует вашим ожиданиям. 28.10.2008
  • @Jonathan: Да, я понимаю вашу точку зрения, но не уверен, что считаю это проблемой. Тест, который не тестирует, эквивалентен отсутствию теста; это вероятно не вызывает проблем. Большинство тестов не подпадают под определенную вами категорию и, таким образом, вносят свой вклад. В целом это помогает, и в худшем случае неплохо. 28.10.2008
  • И, конечно, вы можете изобрести сценарии, в которых тесты действительно могут вызвать проблемы, но, конечно, вы согласны с тем, что их намного меньше, чем тестов, предотвращающих проблемы. 28.10.2008
  • @Jonathan, вам не нужно использовать модульные тесты. Это инструмент, отличный инструмент. Но если вам это не нравится, продолжайте и делайте по-своему. 28.10.2008
  • @Jonathan - Если вы пишете тест, который использует IMockedComplexObject, это не ComplexObject, который вы тестируете, это клиент ComplexObject, который проходит тестирование, и мы не хотим затрат на создание экземпляра ComplexObject. После этого вам все равно нужно протестировать ComplexObject в отдельном тесте. 29.10.2008
  • Каждый уровень вашего SOA-решения должен иметь свои собственные тесты для изолированного тестирования. Затем тот, кто отвечает за предоставление интегрированного решения (уровни существуют не только для развлечения!) Какой-либо другой внешней стороне, должен протестировать интегрированное решение, а также свой собственный код изолированно. 25.02.2009
  • Что касается вашего первого пункта - вы не можете доказать отсутствие ошибок. Конвергентная валидность помогает, но единый тест должен быть независимым и самостоятельным. Вы можете протестировать эти тесты, взломав код или, как вы упомянули, только введя код, который написан для прохождения теста. 02.06.2009
  • +1 для написания подпрограммы модульного тестирования, модульного теста, а затем написания набора тестов, которые затем просто вызывают эту подпрограмму тестирования с другими параметрами. Я все время это делаю. 04.08.2009
  • @FlySwat: В ответ на ваш комментарий о IMockedComplexObject я цитирую комментарий Cwash по другому ответу: вы не издеваетесь над тем, что пытаетесь протестировать, вы издеваетесь над тем, что вы не пытаетесь тестировать. 23.09.2009
  • @FlySwat Вот почему у вас есть интеграционные тесты, которые проверяют взаимодействие с реальным ComplexObject. 13.10.2009

  • 2

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

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

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

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

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

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

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

  • 3

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

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

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

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

    28.10.2008
  • Вызовите метод с конкретным входом и сравните его с ожидаемым результатом. но что, если выходные данные представляют собой сложный тип ... как XML-документ. Вы не можете просто ==, вам нужно будет написать конкретный код сравнения, и тогда, возможно, ваш метод сравнения может быть ошибочным ?? 12.04.2010
  • @andy: Вы должны протестировать свой метод сравнения отдельно. После того, как вы его тщательно протестировали, вы можете положиться на его работу в других тестах. 12.04.2010
  • круто, спасибо Билл. Я начал работать на новом месте, и это мой первый раз с модульным тестированием. Я думаю, что в принципе это работает, и мы используем круиз-контроль там, где он действительно полезен, но большие наборы тестов, похоже, постигает та же участь, что и унаследованный код ... Я просто не уверен в этом ... 12.04.2010

  • 4

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

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

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

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

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

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

  • 5

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

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

    08.01.2009
  • +1 интересная концепция, о которой я еще не слышал 11.05.2009

  • 6

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

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

    Assert.IsEqual(p.DiscountPrice,90);
    

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

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


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

    Красный обозначает красную полосу JUnit в случае сбоя теста.

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

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


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

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

    30.10.2008

    7

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    03.06.2009

    8

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

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

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

    9

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

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

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

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

    28.10.2008

    10

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

    28.10.2008
  • Это не касается ни одной из моих мыслей. Я понимаю основную мантру TDD ... Я не вижу пользы. 28.10.2008

  • 11

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

    17.05.2010

    12

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

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

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

    28.10.2008

    13

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

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

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

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

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

    02.07.2009

    14

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

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

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

    16.03.2009

    15

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

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

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

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

    02.07.2009

    16

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

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

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

    17.05.2010

    17

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

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

    04.08.2009
    Новые материалы

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

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

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

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

    «Раскрытие математических рассуждений с помощью Microsoft MathPrompter и моделей больших языков»
    TL;DR: MathPrompter от Microsoft показывает, как использовать математические рассуждения с большими языковыми моделями; 4-этапный процесс для улучшения доверия и рассуждений в математических..

    Раскройте свой потенциал в области разработки мобильных приложений: Абсолютная бесплатная серия
    Глава 6: Работа в сети и выборка данных Глава 1: Введение в React Native Глава 2: Основы React Native Глава 3: Создание пользовательского интерфейса с помощью React Native Глава 4:..

    Все о кейсах: Camel, Snake, Kebab & Pascal
    В программировании вы сталкивались с ними при именовании переменной, класса или функции. Поддержание согласованности типов и стилей случаев делает ваш код более читабельным и облегчает совместную..


    © 2024 cyberbuff.ru, От новичка до гуру: Курсы программирования на CyberDuff