Модульные тесты, приватные методы и скрытая абстракция - PullRequest
1 голос
/ 21 февраля 2020

Я читал о модульных тестах, чтобы узнать немного больше об этом.

Кажется, что частные методы тестов не должны быть общим правилом, только некоторые исключения. Я нашел эту статью, в которой объясняется, что: https://enterprisecraftsmanship.com/posts/unit-testing-private-methods/

Здесь говорится, что если закрытый метод сложный, один из вариантов - создать класс publi c и реализовать метод здесь, так что его можно протестировать.

Вот мое сомнение.

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

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

Но если для тестирования закрытого метода я создаю новый класс publi c, поместите туда метод, теперь publi c, не сообщаю ли я клиенту подробности о реализации? На практике вместо объявления publi c закрытого метода создается класс publi c для размещения там метода publi c.

Так что я предполагаю, что что-то неправильно понимаю, но я не понимаю не знаю, что.

В одном из ответов на этот вопрос: Как вы тестируете приватные методы юнитом? сказано, что один из вариантов - это передача приватного метода в публикацию. c класс тоже, но это не объясняет больше (я думаю, что ответ может быть намного длиннее).

Спасибо.

Ответы [ 2 ]

2 голосов
/ 21 февраля 2020

Но если для тестирования частного метода я создаю новый класс publi c, поместите туда метод, теперь publi c, я не сообщаю клиенту подробности о реализации?

Хитрость здесь в том, чтобы не на самом деле разоблачить это. Как именно это сделать, зависит от языка / экосистемы, но, вообще говоря, вы попытаетесь отправить свой код таким образом, чтобы детали реализации не были (легко) доступны конечным пользователям.

Например, в C ++ у вас могут быть приватные заголовки, показывающие функциональность, которую вы не поставляете с вашей библиотекой (не проблема, если они не включены в заголовки вашего интерфейса). Java имеет свою модульную систему Jigsaw. Но даже тогда, если он не может быть механически принудительным, вы все равно можете социально применять его, делая его очень понятным с такими вещами, как имена пакетов и классов, когда конечные пользователи не должны использовать вещи; Например, если вы не используете модульную систему Java, вы все равно можете хранить детали реализации для своего пакета lib.foo в пакете с именем lib.foo.implementation_details, аналогично тому, как в таких языках, как Smalltalk, где у вас вообще нет приватных методов. вы по-прежнему можете давать имена методов, такие как private_foo, чтобы было ясно, что они не предназначены для внешних пользователей.

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

1 голос
/ 22 февраля 2020

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

Многие люди объясняют " «цели юнит-тестирования, но на самом деле они описывают свои цели при проведении юнит-тестирования. Модульное тестирование применяется во многих различных областях и контекстах, начиная с игрушечных проектов, но заканчивая программным обеспечением для атомных станций, относящимся к безопасности, самолетами и т. Д. c.

Другими словами, разработано много программного обеспечения. где вышеупомянутая рекомендация может быть в порядке. Но вы можете применить модульное тестирование гораздо дальше. Если вы не хотите начинать с ограниченного представления о том, что такое модульное тестирование, вам лучше взглянуть на него следующим образом: Одна из основных целей тестирования в целом, а также для модульного тестирования - найти ошибки (см. Myers, Badgett, Sandler: Искусство тестирования программного обеспечения или Beizer: методы тестирования программного обеспечения, а также многие другие).

Полагая, что модульное тестирование связано с поиском ошибок, вы можете также проверить детали реализации: ошибки в реализации - разные реализации одной и той же функциональности имеют разные ошибки. Возьмем простую функцию Фибоначчи: ее можно реализовать как рекурсивную функцию, как итеративную функцию, как закрытое выражение (Moivre / B inet), используя рукописную таблицу поиска, используя автоматически сгенерированную таблицу поиска и др * * тысяча двадцать-одна. Для каждой из этих реализаций набор вероятных ошибок будет существенно отличаться.

Другой пример - сортировка: существует множество функций сортировки, которые с функциональной точки зрения делают одно и то же, а многие даже имеют одного и того же пользователя. интерфейс. Алгоритм IntroSort довольно интересен с точки зрения тестирования, потому что он реализует быструю сортировку, но когда он понимает, что сталкивается с вырожденной сортировкой, он возвращается к другому алгоритму (обычно кучи-сортировка). Тестирование IntroSort означает также создание такого вырожденного набора данных, который заставляет алгоритм войти в сортировку кучи, просто чтобы быть уверенным, что потенциальные ошибки в части сортировки кучи могут быть найдены. Глядя на один только интерфейс publi c, вы никогда бы не придумали такой тестовый случай (по крайней мере, это было бы совпадением).

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

Относительно возможностей сделать частные функции доступными для тестов, но все же не сделать их частью "официальной" публикации c interface: @ Cubi c хорошо объяснил разницу между а) тем, что public в техническом смысле правил видимости данного языка программирования, и б) принадлежностью к "официальному" и документированному API publi c .

...