Тестирование кода в целом не так просто. Если бы это было так, мы бы делали это все давным-давно, и не делали бы ничего подобного только в последние 10-15 лет. Одна из самых больших трудностей всегда заключалась в определении того, как тестировать код, который был написан слаженно, хорошо продуманно и тестируемо, не нарушая инкапсуляцию. Принцип BDD предполагает, что мы почти полностью фокусируемся на поведении, и в некотором смысле, кажется, говорит о том, что вам действительно не нужно беспокоиться о внутренних деталях в такой большой степени, но это часто может усложнить тестирование, если есть множество частных методов, которые делают «вещи» очень скрытно, так как это может увеличить общую сложность вашего теста, чтобы иметь дело со всеми возможными результатами на более открытом уровне.
Насмешка может до некоторой степени помочь, но опять же она довольно внешне сфокусирована. Внедрение зависимостей также может работать довольно хорошо, опять-таки с ложными или тестовыми двойниками, но для этого также может потребоваться, чтобы вы выставляли элементы либо через интерфейс, либо напрямую, чтобы вы могли предпочесть оставаться скрытыми - это особенно верно, если вы хотите иметь хороший параноидальный уровень безопасности для определенных классов в вашей системе.
Для меня до сих пор не решено, следует ли разрабатывать ваши уроки, чтобы их было легче тестировать. Это может создать проблемы, если вам понадобится предоставить новые тесты при сохранении устаревшего кода. Я согласен с тем, что вы должны иметь возможность тестировать абсолютно все в системе, но мне не нравится идея разоблачать - даже косвенно - частные внутренние данные класса, просто чтобы я мог написать для них тест.
Для меня решение всегда заключалось в том, чтобы придерживаться довольно прагматичного подхода и сочетать несколько приемов для удовлетворения каждой конкретной ситуации. Я использую много унаследованных двойников теста, чтобы раскрыть внутренние свойства и поведение моих тестов. Я высмеиваю все, что можно прикрепить к моим классам, и там, где это не поставит под угрозу безопасность моих классов, я предоставлю средства для переопределения или введения поведения в целях тестирования. Я даже рассмотрю возможность предоставления более ориентированного на события интерфейса, если это поможет улучшить способность тестировать код
Там, где я нахожу «непроверяемый» код, я смотрю, смогу ли я сделать рефакторинг, чтобы сделать его более тестируемым. Там, где у вас есть много закрытого кода, выполняющего скрытые закулисные вещи, часто вы обнаружите новые классы, ожидающие выхода из строя. Эти классы могут использоваться для внутренних целей, но часто могут тестироваться независимо с менее частным поведением, а зачастую и с меньшим количеством уровней доступа и сложности. Однако одну вещь, которую я стараюсь избегать, - это написание производственного кода со встроенным тестовым кодом. Может возникнуть соблазн создать « тестовые бобышки », которые приводят к таким ужасам if testing then ...
, которые указывают на то, что проблема тестирования не полностью деконструирована и не полностью решена.
Возможно, вам будет полезно прочитать книгу Джерарда Месароса « Тестовые шаблоны xUnit» , которая охватывает все эти вещи гораздо более подробно, чем я могу здесь рассказать. Я, вероятно, не делаю все, что он предлагает, но это помогает прояснить некоторые из более сложных тестовых ситуаций, с которыми приходится иметь дело. В конце концов, вы хотите быть в состоянии удовлетворить ваши требования к тестированию, в то же время применяя ваши предпочтительные проекты, и это помогает лучше понять все варианты, чтобы лучше решить, где вам может потребоваться компромисс.