Я довольно новичок в тестировании кода и assert
раньше был шлюхой. В модульном тестировании меня беспокоит то, что от вас часто требуется создавать public
(или, по крайней мере internal
) поля, которые были бы в private
противном случае, отменять readonly
их, создавать вместо них private
методы protected virtual
и т. Д.
Недавно я обнаружил, что вы можете избежать этого, используя такие вещи, как класс PrivateObject, чтобы получить доступ к чему-либо в объекте с помощью отражения. Но это делает ваши тесты менее удобными для сопровождения (что-то не получится во время выполнения, а не во время компиляции, оно будет сломано простым переименованием, сложнее отладить ...). Каково ваше мнение по этому поводу? Каковы лучшие практики в модульном тестировании относительно ограничения доступа?
edit: учтите, например, что у вас есть класс с кешем в файле на диске, и в ваших тестах вы хотите вместо этого записывать в память.
источник
Ответы:
Вы никогда не должны
Особенно отсутствие чтения поля может сделать неизменный объект изменчивым, и это было бы катастрофой.
Ваши тесты должны рассматривать ваши объекты как черные ящики ( Википедия ), это означает, что они должны иметь дело только с открытым интерфейсом объектов, а не с деталями их реализации.
Если объект не может быть в достаточной степени протестирован с использованием его открытого интерфейса, вам необходимо найти способы предоставить формальные и полезные расширения его интерфейса, которые облегчили бы тестирование. Например, система регистрации, имеющая только пару методов Register / Deregister, возможно, выиграет от использования метода IsRegistered, даже если в этом нет необходимости для данного приложения; тем не менее, это формальное и полезное расширение интерфейса, и оно, кстати, подойдет для тестирования.
Важно то, что изменение реализации объекта не должно требовать изменения юнит-теста. Теоретически вы должны быть в состоянии написать модульный тест один раз, а затем попросить нескольких программистов написать несколько совершенно разных реализаций тестируемого объекта для работы с модульным тестом.
источник
private
методов,protected virtual
помогающих с насмешками в тестах, считается плохой практикой?В C # вы можете использовать,
InternalsVisibleToAttribute
чтобы позволить вашей тестовой сборке видетьinternal
классы в тестируемой сборке . Похоже, вы уже знаете это.В большинстве случаев меня интересует только тестирование публичного API моей сборки. В случае, когда я хочу выполнить тестирование белого модуля некоторого модуля, я перемещаю код в
internal
класс и делаю егоpublic
методом этого класса. Затем я могу написать модульный тест для этого класса.Это хорошо поддается внедрению зависимости и модели стратегии. Вы можете абстрагировать метод в интерфейс, вставить интерфейс в конструктор вашего родительского объекта и просто проверить, что родительский делегат соответствующим образом. Затем вы можете проверить, что дочерний объект ведет себя соответствующим образом. Это делает все более модульным.
источник
По моему опыту, лучше всего не выставлять внутренности вашего класса специально для теста. Несмотря на то, что это может облегчить написание теста. Тест является первым клиентом вашего класса, поэтому, если вам сложно протестировать ваш класс через его открытый интерфейс, вам, вероятно, будет трудно использовать ваш класс и в других местах.
То, как легко классу протестировать через его общедоступный API, говорит о том, насколько легко будет использовать класс. Думайте о тестах частично как о способе прототипирования использования вашего класса.
Постарайтесь понять, почему в вашем тесте нужно что-то понимать в классе, который недоступен через публичный API. Возможно, ваш класс делает слишком много, и вместо этого его нужно разложить на группу взаимодействующих классов? Затем вы можете высмеять некоторые сотрудничающие классы, чтобы почувствовать, что делает тестируемый класс.
Попробуйте применить принцип инверсии зависимостей и ввести интерфейсы между вашими классами, которые вы можете смоделировать в своих тестах. Вы можете предоставить соавторам свой тест, используя инверсию управления .
Также рассмотрите возможность применения принципа «скажи, не спрашивай», чтобы помочь структурировать интерфейс вашего класса надежным, слабо связанным способом, где правильная информация предоставляется, а остальная часть скрыта.
источник
Лично я предпочитаю оставлять код, который я тестирую, настолько чистым, насколько я могу, и если тестируемый код нуждается во взломах (и в неприятных указателях C ++ и т.д.), я счастлив сделать это
источник
Видимость вашего кода не имеет ничего общего с вашими модульными тестами!
Вы делаете свои методы приватными, не для того, чтобы скрыть их от тестирования, и вы не делаете их открытыми для тестирования, верно? Здесь важна ваша реализация, а не тесты - эти серверы служат доказательством вашего кода, но они не являются вашим кодом .
Существует множество способов разрешить доступ к скрытым (частным или внутренним) методам и свойствам. Многие тестовые фреймворки и IDE (например, Visual Studio) поддерживают вас здесь, генерируя все необходимое для доступа, вам нужно только создать свои тестовые случаи. Так зачем волноваться? Лучше держать ваш код в чистоте и порядке.
источник