Запись “единицы тестируемого” кода?

Я не уверен, что согласен с «иметь» в утверждении «Удаление возможности комментировать из языка программирования означало, что я ДОЛЖЕН писать грамотный код, без исключений», поскольку это не так, как если бы весь код был задокументирован. Я предполагаю, что большинство людей будут писать нечитаемый код.

Более того, я лично не верю в реальность самоочевидной программы или API в практическом мире.

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

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

37
задан Dana Holt 17 June 2009 в 18:20
поделиться

19 ответов

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

  • Рефакторинг интерфейсов - делает имитировать проще

  • Публичные методы виртуальны, если не используются интерфейсы - упрощает имитирование.

  • Внедрение зависимостей - делает насмешку проще

  • Меньшие, более целевые методы - тесты более сфокусированы, их легче пишите

  • Избегайте статических классов

  • Избегайте одиночных экземпляров, кроме случаев, когда необходимый

  • Избегайте запечатанных классов

53
ответ дан 27 November 2019 в 04:05
поделиться

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

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

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

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

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

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

1
ответ дан 27 November 2019 в 04:05
поделиться

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

2
ответ дан 27 November 2019 в 04:05
поделиться

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

3
ответ дан 27 November 2019 в 04:05
поделиться

I'm sure I'll be down voted for this, but I'm going to voice the opinion anyway :)

While many of the suggestions here have been good, I think it needs to be tempered a bit. The goal is to write more robust software that is changeable and maintainable.

The goal is not to have code that is unit testable. There's a lot of effort put into making code more "testable" despite the fact that testable code is not the goal. It sounds really nice and I'm sure it gives people the warm fuzzies, but the truth is all of those techniques, frameworks, tests, etc, come at a cost.

They cost time in training, maintenance, productivity overhead, etc. Sometimes it's worth it, sometimes it isn't, but you should never put the blinders on and charge ahead with making your code more "testable".

4
ответ дан 27 November 2019 в 04:05
поделиться

Не использовать git-log для написания сценариев: используйте либо git-rev-list , либо git-log с указанным настраиваемым форматом ( - format = * * option).

Есть дополнительная проблема с вашим вопросом: может существовать более одного таких корневых коммитов TAIL (без родителей) в репозитории (даже если мы не учитываем отключенные ветки, такие как 'html', 'man' и 'todo' в репозитории git.git). Обычно это результат объединения отдельных проектов в один или объединения поддеревьев отдельно разработанного подпроекта.

Например, в репозитории git есть 6 корневых коммитов: git-gui, gitk (объединено поддеревьев), gitweb (объединено, больше не разрабатывается отдельно), почтовые инструменты git (объединены очень рано в истории проекта) и p4-fast. -экспорт (возможно, случайно).

3
ответ дан 27 November 2019 в 04:05
поделиться

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

4
ответ дан 27 November 2019 в 04:05
поделиться
4
ответ дан 27 November 2019 в 04:05
поделиться

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

4
ответ дан 27 November 2019 в 04:05
поделиться

Самый простой способ - не проверять свой код, если вы не проверяете с ним тесты.

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

4
ответ дан 27 November 2019 в 04:05
поделиться

When writing tests (as with any other software task) Don't Repeat Yourself (DRY principle). If you have test data that is useful for more then one test then put it someplace where both tests can use it. Don't copy the code into both tests. I know this seems obvious but I see it happen all the time.

5
ответ дан 27 November 2019 в 04:05
поделиться

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

6
ответ дан 27 November 2019 в 04:05
поделиться
  1. Используйте TDD
  2. При написании кода используйте внедрение зависимостей везде, где это возможно
  3. Программа для интерфейсов, а не конкретных классов, чтобы вы могли заменять фиктивные реализации.
6
ответ дан 27 November 2019 в 04:05
поделиться

Сначала напишите тесты - так тесты будут определять ваш дизайн.

9
ответ дан 27 November 2019 в 04:05
поделиться

Внедрение зависимостей, похоже, помогает.

12
ответ дан 27 November 2019 в 04:05
поделиться

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

4
ответ дан 27 November 2019 в 04:05
поделиться

Вам не обязательно «делать ваш код более дружественным к модульному тестированию»

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

0
ответ дан 27 November 2019 в 04:05
поделиться

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

  • Обучите себя и свою команду разработчиков возможностям фреймворка модульного тестирования, имитирующих библиотек и инструментов тестирования, которые вы собираетесь использовать. Понимание того, что они могут и не могут делать, будет иметь важное значение, когда вы действительно начнете писать свои тесты.
  • Планируйте свои тесты, прежде чем вы начнете их писать. Определите крайние случаи, ограничения, предварительные условия, постусловия и исключения, которые вы хотите включить в свои тесты.
  • Исправляйте неработающие тесты как можно ближе к тому моменту, когда вы их обнаружите. Тесты помогают выявить дефекты и потенциальные проблемы в вашем коде. Если ваши тесты не работают, вы откроете дверь для того, чтобы позже исправить больше вещей.
  • Если вы следуете процессу проверки кода в своей команде, проверяйте код и свои модульные тесты.
1
ответ дан 27 November 2019 в 04:05
поделиться

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

  • Ознакомьте себя и свою команду разработчиков с возможностями среды модульного тестирования, имитирующих библиотек и инструментов тестирования, которые вы собираетесь использовать. Понимание того, что они могут, а что не могут, будет иметь важное значение, когда вы действительно начнете писать свои тесты.
  • Планируйте свои тесты, прежде чем вы начнете их писать. Определите крайние случаи, ограничения, предварительные условия, постусловия и исключения, которые вы хотите включить в свои тесты.
  • Исправляйте неработающие тесты как можно ближе к тому моменту, когда вы их обнаружите. Тесты помогают выявить дефекты и потенциальные проблемы в вашем коде. Если ваши тесты не работают, вы откроете дверь для исправления других вещей позже.
  • Если вы следуете процессу проверки кода в своей команде, проверяйте код и свои модульные тесты. Модульные тесты являются такой же частью вашей системы, как и любой другой код - обзоры помогают выявить слабые места в тестах так же, как и в системном коде.
1
ответ дан 27 November 2019 в 04:05
поделиться
Другие вопросы по тегам:

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