Написание кода, проверяемого модулем?

Какие методы вы используете, чтобы сделать ваш код более дружественным к юнит-тестированию?

Ответы на вопрос(17)

чтобы сделать его тестируемым. Напишите тесты и получите 95% охват. Это научило меня всему, что мне нужно знать о написании тестируемого кода. Я не против TDD, но изучение специфики того, что делает код тестируемым или непроверяемым, помогает вам думать о тестируемости во время разработки.

Проверьте этот разговорАвтоматизированные тестовые шаблоны и запахи. One of the main take aways for me, was to make sure that the UnitTest code is in high quality. If the code is well documented and well written, everyone will be motivated to keep this up.

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

1.Using a framework/pattern like MVC to separate your UI from you
business logic will help a lot. 
2. Use dependency injection so you can create mock test objects.
3. Use interfaces.
 17 июн. 2009 г., 20:47
Я согласен отделить интерфейс от логики.
Решение Вопроса

you to think about testability and helps write the code that is actually needed, not what you think you may need

Refactoring to interfaces -- makes mocking easier

Public methods virtual if not using interfaces -- makes mocking easier

Dependency injection -- makes mocking easier

Smaller, more targeted methods -- tests are more focused, easier to write

Avoidance of static classes

Avoid singletons, except where necessary

Avoid sealed classes

 19 июн. 2009 г., 11:30
да это о покрывает это
 01 июн. 2014 г., 11:59
"Избегайте одиночных игр, кроме случаев, когда это необходимо" - Не встречал ни одного случая, когда это было необходимо в мои 10 лет программирования.

что вы изучаете первым делом в ООП, но многие, кажется, забывают:Code Against Interfaces, Not Implementations.

 17 июн. 2009 г., 22:22
@ dss539: Я согласен, но "интерфейс против реализации" дихотомия предполагает что-то другое или другое
 17 июн. 2009 г., 19:06
Это зависит от того, что он подразумевает под «интерфейсом». Если он имеет в виду & quot; используйте C #interface много ключевых слов & quot; тогда нет, это не так полезно. Если он имеет в виду «относиться к другим объектам как к черным ящикам, которые принимают предопределенный набор сообщений»; тогда да чтоis полезным
 17 июн. 2009 г., 17:05
Я думаю, это зависит от того, когда вы узнали. Это нигде не находится в верхней части моего списка ООП.

если вы не проверяете его с помощью тестов.

Я не большой поклонник написания тестов первым. Но я очень сильно верю в то, что код должен быть проверенwith тесты. Даже час или около того,togther, Я думаю, что порядок, в котором они написаны, менее важен, если они входят вместе.

 17 июн. 2009 г., 17:02
@JaredPar: нет, тесты в первую очередь проваливаются. Код написан только для прохождения тестов. Таким образом, тесты доказывают, что они тестируют то, что имеет значение. @ dss539: Я имел в виду, что если вы сначала не будете писать тесты, вы будете зависеть от того, как ваши блестящие разработчики делают обзоры кода или смотрят на собственный код, чтобы убедиться, что тесты, которые они проверяют, действительно проверяют правильность. Без неудачного теста сначала код не может доказать это, поэтому должен зависеть от людей.
 17 июн. 2009 г., 16:53
@John - Вы в любом случае зависите от блестящих разработчиков. Не существует идеального процесса, который превратил бы полного идиота в гения. Глупость ВСЕГДА находит способ процветать в процессе.
 17 июн. 2009 г., 16:46
@JaredPar: причина написания тестов до написания кода заключается в том, что при проверке тестов вы будете знать, что они тестируют код, который вы проверяете. В противном случае вы просто зависите от блестящих разработчиков, чтобы убедиться, что тесты на самом деле проверяют то, что имеет значение.
 17 июн. 2009 г., 17:08
@John - У вас есть сильные стороны в том, что тестирование в первую очередь дает хорошее освещение, но глупый / злой разработчик все еще может писать плохие тесты. Неудача сначала, а затем прохождение теста не обязательно является хорошим показателем того, что тест работает более чем в одном случае. Тем не менее, это может помочь умным разработчикам подумать о лучшем способе тестирования. Так что я не говорю, что у вас совершенно плохая идея. Скорее, я просто думаю, что это не панацея.
 17 июн. 2009 г., 16:56
@ Джон, я не согласен. Написание тестов в первую очередь позволяет вам гарантировать, какие методы вызываются, а не какой код выполняется. Это две совершенно разные проблемы, и последняя является гораздо более важной. Моя группа не полагается на блестящих разработчиков для обеспечения надлежащего тестирования кода, мы полагаемся на профилировщиков, чтобы сделать этот вызов.
 29 июн. 2009 г., 11:16
+1 за это. Содержание также доступно в текстовом виде:misko.hevery.com/code-reviewers-guide

тестирования".

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

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

 17 июн. 2009 г., 19:11
+1 большинство разработчиков считают, что «это просто тестовый код, кого это волнует, если он дерьмовый?» что печально, потому что код, который они обычно пишут, уже достаточно хреновый!

)

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

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

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

 17 июн. 2009 г., 19:28
Если вы пишете тонну шаблонного кода, возможно, пришло время найти новый язык.
 17 июн. 2009 г., 19:13
+1 для здравого смысла, -1 потому что по самой природе тестируемого кода код становится более изменчивым и поддерживаемым
 17 июн. 2009 г., 19:18
+1 для некоторого здравомыслия! Модульные тесты - это хорошо, но TDD - большой шаг к быстрому выполнению задач, если тесты используются дляeverything, Если у вас есть тесты для тривиального или стандартного кода, такие как геттеры / сеттеры, более вероятно, что вы получите неудачные тесты из-за изменений интерфейса, а не из-за реальных ошибок. Смарт-юнит-тестирование это хорошо. Ревностное модульное тестирование приводит к хрупкому коду и медленной разработке.
 02 янв. 2014 г., 17:46
Вы правы, я понизил это. Написание модульных тестов ограничивает вас написанием кода объектно-ориентированным способом, в модулях, которые имеют четкие зависимости и могут выполняться изолированно. Это означает, что ваш код многократно используется, сообщает о том, что он делает правильно, и не накладывает ограничений на остальную часть системы. Кроме того, выare Если вы собираетесь в конечном итоге протестировать ваш код, то, к сожалению, вы сделаете это вручную, запустив все приложение вместо того, чтобы запускать код, который будет делать это снова и снова. Написание непроверяемого кода всегда усложняет поддержку вашей программы.
 26 окт. 2009 г., 11:40
+1 за здравый смысл. Всегда используйте свой мозг. Но я не пишу модульные тесты, так что я получаю теплые размышления и могу писать сложный код, чтобы заставить меня чувствовать себя умным, я делаю это, потому что это делает мой код более изменчивым и обслуживаемым, и я знаю, что он работает. Если бы мне не пришлось заставлять мой код работать, я мог бы делать вещи намного быстрее!

To prepare your code to be testable:

Avoid large complex classes that do more than one thing - keep the single responsibility principle in mind. When possible, use interfaces to decouple interactions and allow mock objects to be injected. When possible, make pubic method virtual to allow mock objects to emulate them. When possible, use composition rather than inheritance in your designs - this also encourages (and supports) encapsulation of behaviors into interfaces. When possible, use dependency injection libraries (or DI practices) to provide instances with their external dependencies.

To get the most out of your unit tests, consider the following:

Educate yourself and your development team about the capabilities of the unit testing framework, mocking libraries, and testing tools you intend to use. Understanding what they can and cannot do will be essential when you actually begin writing your tests. Plan out your tests before you begin writing them. Identify the edge cases, constraints, preconditions, postconditions, and exclusions that you want to include in your tests. Fix broken tests as near to when you discover them as possible. Tests help you uncover defects and potential problems in your code. If your tests are broken, you open the door to having to fix more things later. If you follow a code review process in your team, code review your unit tests as well. Unit tests are as much a part of your system as any other code - reviews help to identify weaknesses in the tests just as they would for system code.
 18 июн. 2009 г., 03:54
Мне нравится ссылка на Иран. Тем не менее, по-прежнему не голосую.
 17 июн. 2009 г., 19:08
 17 июн. 2009 г., 22:23
@ dss539: это то, что вы хотели опубликовать?

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

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

 17 июн. 2009 г., 17:00
Абсолютно для уровня доступа к БД. Я не верю, что концепция модульных тестов применима к пользовательскому интерфейсу.
 17 июн. 2009 г., 16:48
А как насчет кода пользовательского интерфейса? А уровень доступа к БД?

Также в Google есть инструмент, который будет измерять тестируемость вашего кода ...

 31 окт. 2009 г., 01:59
Вы можете использовать что-то вроде Groovy или JMockit.groovy.codehaus.org/Mocking+Static+Methods+using+Groovy  Если вам нужно. Иногда вы не можете контролировать дизайн или устаревший код.
 17 июн. 2009 г., 19:14
Вы можете добавить зависимости в свою статику. ;)
Use TDD When writing you code, utilise dependency injection wherever possible Program to interfaces, not concrete classes, so you can substitute mock implementations.
 17 июн. 2009 г., 17:03
@Visage: сначала я пишу провальные тесты. Нет написанного кода, если он не был написан для прохождения неудачных тестов. Таким образом, 90% -ное покрытие по определению - это 90%, которые требовали тестирования - его не было бы, если бы не тесты.
 17 июн. 2009 г., 16:53
Интересный вопрос Модульное тестирование IME без этих вещей становится очень трудным, и я полагаю, мне было бы интересно, если бы 90% охват был на 90%, который был способен протестировать, а не на 90%, которые требовали тестирования;)
 17 июн. 2009 г., 17:04
@ Майкл: нет ничего плохого в реализации DI, насмешек и т. Д. Для практического применения тестов и поддержания их в обслуживании. Я следую правилу красно-зеленого-рефакторинга, поэтому постоянно рефакторину как тесты, так и код; если DI улучшит некоторые тесты, тогда DI произойдет.
 17 июн. 2009 г., 16:57
Я в значительной степени то, что я делаю, и я бы сказал, что я все еще получаю большую выгоду в отношении качества - проблема в том, что написание тестов труднее, а поддержание их - больше работы.
 17 июн. 2009 г., 16:48
@Visage: из любопытства, что если бы вы могли использовать TDD, но не использовали повсеместное внедрение зависимостей, а использовали конкретные классы во многих местах и не использовали mocks все время; сделал все эти плохие вещи, но закончил с охватом кода 90% или более. Это сделало бы вас плохим человеком, или это означало бы, что не все эти другие вещи действительно были необходимы для качества?

в котором модульное тестирование - это не рутина, а то, что я на самом деле ХОЧУ делать. По моему опыту, довольно важным фактором являются ваши инструменты. Я много работаю над ActionScript, и, к сожалению, инструменты несколько ограничены, например, нет интеграции IDE и нет более продвинутых структур для насмешек (но хорошие вещи не за горами, так что здесь никаких претензий!). Ранее я занимался разработкой, основанной на тестировании, с более зрелыми средами тестирования, и это был определенно более приятный опыт, но он все еще казался чем-то вроде рутины.

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

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

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

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

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

Ваш ответ на вопрос