Удобные в сопровождении модульные тесты

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

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

Так есть ли какие-либо хиты / подсказки для написания удобного в сопровождении кода TDD? Я в настоящее время читаю Roy Osherove Искусство Поблочного тестирования, есть ли какие-либо другие ресурсы, которые могли выручить меня?

Спасибо

25
задан Carl Manaster 11 February 2010 в 17:22
поделиться

10 ответов

Практика

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

Уже рекомендованная книга xUnit Test Patterns хороша, и я слышал хорошие отзывы о книге, которую вы сейчас читаете.

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

Некоторые советы, по которым я живу, следуют правилу AAA .

Устраивайте, действуйте и утверждайте. Каждый тест должен следовать этой формуле. Это делает тест удобочитаемым и легким в обслуживании, если и когда они сломаются.

Дизайн по-прежнему важен

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

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

Загляните в блог Google Testing - это был поворотный момент для меня, когда я начинал TDD. Статьи Misko (и сайт - особенно Guide to Testable ) превосходны и должны указать вам правильное направление.

17
ответ дан 28 November 2019 в 21:15
поделиться

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

Сначала я изучу схему базы данных и воспользуюсь страницами MSDN.

-121--3702177-

Если вы можете решить проблему с помощью ode15s Matlab, вы должны иметь возможность решить ее с помощью vode решателя scipy. Чтобы смоделировать ode15s , я использую следующие настройки:

ode15s = scipy.integrate.ode(f)
ode15s.set_integrator('vode', method='bdf', order=15, nsteps=3000)
ode15s.set_initial_value(u0, t0)

, а затем вы можете с радостью решить проблему с помощью ode15s.integrate (t_final) . Это должно работать довольно хорошо над жесткой проблемой.

(См. также http://www.scipy.org/NumPy_for_Matlab_Users )

-121--2258388-

Да, существует целая книга под названием xUnit Test Patterns , в которой рассматривается эта проблема.

Это книга подписей Мартина Фаулера, поэтому в ней есть все следы классической книги узоров. Нравится вам это или нет - вопрос личного вкуса, но я, с одной стороны, счел его безмерно бесценным.

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

2
ответ дан 28 November 2019 в 21:15
поделиться

Широко ли вы используете интерфейсы, Dependancy Injection и mocking?

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

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

2
ответ дан 28 November 2019 в 21:15
поделиться

Похоже, ваши модульные тесты хрупкие и пересекаются. В идеале одно изменение кода должно повлиять только на один модульный тест - при однозначном сопоставлении тестов с функциями другие тесты не зависят от данной функции. Это может быть слишком идеалистично; на практике многие из наших тестов повторно выполняют один и тот же код, но об этом следует помнить. Когда одно изменение кода влияет на множество тестов, это запах. Также, что касается вашего конкретного примера переименования: найдите инструмент, который автоматизирует эти рефакторинги за вас. Я считаю, что и Resharper, и CodeRush поддерживают такой автоматический рефакторинг; это гораздо более быстрый, простой и надежный способ рефакторинга, чем ручной подход.

Чтобы лучше изучить вашу IDE, ничто не сравнится с объединением в пару с кем-то другим. Вы оба узнаете; вы оба разовьете новые навыки - и это не займет много времени. Несколько часов значительно увеличат ваш комфорт с инструментом.

3
ответ дан 28 November 2019 в 21:15
поделиться

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

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

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

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

5
ответ дан 28 November 2019 в 21:15
поделиться

"Как только требования начали меняться и я начал делать рефакторинг, я обнаружил, что трачу больше времени на переписывание / исправление юнит-тестов"

И что? Почему это проблема?

Ваши требования изменились. Это означает, что ваш дизайн должен был измениться. Это значит, что ваши тесты должны были измениться.

"Я потратил больше времени на переписывание / исправление юнит-тестов, чем на написание кода, гораздо больше времени."

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

Так и должно быть.

Идите домой счастливым. Вы выполнили работу должным образом.

7
ответ дан 28 November 2019 в 21:15
поделиться

Я думаю, вы можете найти достойный баланс между тестированием и кодированием.

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

В какой-то момент вы чувствуете , что ваш проект обретает форму. Это момент, когда пригодится тяжелое модульное тестирование. Я пишу как можно больше.

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

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

2
ответ дан 28 November 2019 в 21:15
поделиться

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

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

1
ответ дан 28 November 2019 в 21:15
поделиться

Вы используете хорошую IDE? Я задавал себе тот же вопрос, что и вы, несколько лет назад, когда впервые применил модульное тестирование. Тогда я использовал комбинацию Emacs , find и grep для выполнения рефакторинга. Это было больно.

К счастью, коллега ударил меня по голове и убедил попробовать использовать «современные инструменты», что на его просторечии означало Intellij IDEA . IDEA - мое личное предпочтение, но Netbeans или Eclipse также справятся с основами. Трудно переоценить прирост производительности, который это мне дало; легко на порядок, особенно для больших проектов с большим количеством тестов.

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

0
ответ дан 28 November 2019 в 21:15
поделиться

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

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

0
ответ дан 28 November 2019 в 21:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: