Я знаю, что вы не должны тестировать закрытые методы, и если вам кажется, что вам нужно, там может быть класс, ожидающий выхода.
Но я не хочу иметь классы gazillion только для того, чтобы я мог тестировать их публичные интерфейсы, и я обнаружил, что для многих классов, если я просто тестирую публичные методы, мне в конечном итоге приходится имитировать множество зависимостей, а модульные тесты огромный и трудно следовать.
Я предпочитаю высмеивать приватные методы при тестировании общедоступных, а также проверять внешние зависимости при тестировании приватных.
Я сумасшедший?
unit-testing
mocking
Фран Севильано
источник
источник
Ответы:
Вы частично правы - вы не должны напрямую тестировать частные методы. Закрытые методы класса должны вызываться одним или несколькими открытыми методами (возможно, косвенно - закрытый метод, вызываемый открытым методом, может вызывать другие частные методы). Поэтому при тестировании ваших общедоступных методов вы также будете проверять и ваши закрытые методы. Если у вас есть частные методы, которые остаются непроверенными, либо ваши тестовые примеры недостаточны, либо частные методы не используются и могут быть удалены.
Если вы выбираете метод белого ящика, вы должны учитывать детали реализации ваших частных методов при построении модульных тестов вокруг ваших открытых методов. Если вы используете подход «черного ящика», вам не следует проверять какие-либо подробности реализации в общедоступных или частных методах, а против ожидаемого поведения.
Лично я предпочитаю подход белого ящика к юнит-тестам. Я могу создать тесты, чтобы тестировать методы и классы в разных состояниях, которые вызывают интересное поведение в моих публичных и частных методах, и затем утверждать, что результаты - это то, чего я ожидаю.
Так что - не издевайтесь над вашими личными методами. Используйте их, чтобы понять, что вам нужно проверить, чтобы обеспечить хороший охват функциональности, которую вы предоставляете. Это особенно верно на уровне юнит-тестов.
источник
Я думаю, что это очень плохая идея.
Проблема с созданием модульных тестов частных участников заключается в том, что они плохо вписываются в жизненный цикл продукта.
Причина, по которой вы выбрали сделать эти методы закрытыми, заключается в том, что они не имеют решающего значения для того, что пытаются делать ваши классы, - просто помогают в том, как вы в настоящее время реализуете эту функциональность. При рефакторинге эти личные данные, скорее всего, изменятся, что приведет к трениям при рефакторинге.
Кроме того, ключевое различие между публичными и частными участниками заключается в том, что вы должны тщательно продумывать свой публичный API, хорошо документировать его и тщательно проверять (утверждения и т. Д.). Но с частным API было бы бессмысленно тщательно обдумывать это (потраченные впустую усилия, поскольку его использование настолько локализовано). Внедрение частных методов в модульные тесты означает создание внешних зависимостей от этих методов. Это означает, что API должен быть стабильным и хорошо документированным (поскольку кто-то должен выяснить, почему эти модульные тесты не пройдены, если / когда они это делают).
Я предлагаю тебе:
Благодарим вас за желание протестировать эту функциональность и за то, что ее сложно протестировать через ваш текущий общедоступный API. Но я лично ценю модульность больше, чем тестовое покрытие.
источник
UnitTests проверяет общедоступное наблюдаемое поведение , а не код, где «публичный» означает: возвращаемые значения и связь с зависимостями.
«Единица» - это любой код, который решает ту же проблему (или, точнее, имеет ту же причину для изменения). Это может быть один метод или группа классов.
Основная причина, по которой вы не хотите тестировать
private methods
: они являются деталями реализации, и вы можете изменить их во время рефакторинга (улучшите свой код, применяя OO-принципы без изменения функциональности). Это как раз тогда, когда вы не хотите, чтобы ваши юнит-тесты изменились, чтобы они могли гарантировать, что поведение вашего CuT не изменилось во время рефакторинга.Я обычно испытываю обратное: чем меньше классов (чем меньше у них ответственности), тем меньше у них зависимостей, и тем легче юнит-тесты и для написания, и для чтения.
В идеале вы применяете один и тот же уровень абстракции к своим классам. Это означает, что ваши классы либо предоставляют некоторую бизнес-логику (предпочтительно как «чистые функции», работающие только с их параметрами без сохранения собственного состояния) (x), либо вызывают методы для других объектов, но не для обоих одновременно.
Таким образом, юнит-тестирование бизнес-поведения является простым делом, и объекты «делегирования» обычно слишком просты, чтобы их можно было потерпеть неудачей (без ветвления, без изменения состояния), так что нет необходимости в юнит-тестировании, и их тестирование можно оставить для интеграции или тестов модулей.
источник
Модульное тестирование имеет определенную ценность, когда вы являетесь единственным программистом, работающим над кодом, особенно если приложение очень большое или очень сложное. Когда модульное тестирование становится необходимым, когда у вас есть большое количество программистов, работающих над одной и той же кодовой базой. Концепция модульного тестирования была введена для решения некоторых трудностей работы в этих больших командах.
Причина, по которой юнит-тесты помогают крупным командам, заключается в контрактах. Если мой код выполняет вызовы кода, написанного кем-то другим, я делаю предположения о том, что будет делать код другого человека в различных ситуациях. При условии, что эти предположения все еще верны, мой код все еще будет работать, но как мне узнать, какие предположения являются действительными и как я узнаю, когда эти предположения изменились?
Вот где приходят модульные тесты. Автор класса создает модульные тесты для документирования ожидаемого поведения своего класса. Модульный тест определяет все допустимые способы использования класса, и запуск модульного теста проверяет, работают ли эти сценарии использования как ожидалось. Другой программист, который хочет использовать ваш класс, может прочитать ваши модульные тесты, чтобы понять поведение, которое они могут ожидать от вашего класса, и использовать это в качестве основы для своих предположений о том, как работает ваш класс.
Таким образом, подписи открытого метода класса и модульные тесты вместе образуют договор между автором класса и другими программистами, которые используют этот класс в своем коде.
В этом случае, что произойдет, если вы включите тестирование частных методов? Понятно, что это не имеет смысла.
Если вы являетесь единственным программистом, работающим над вашим кодом, и вы хотите использовать модульное тестирование как способ отладки вашего кода, то я не вижу в этом никакого вреда, это всего лишь инструмент, и вы можете использовать его любым способом, который работает для Вы, но это не было причиной, по которой было введено модульное тестирование, и не дает основных преимуществ модульного тестирования.
источник
Прежде чем ответить на такой вопрос, вам нужно решить, чего вы на самом деле хотите достичь.
Вы пишете код. Вы надеетесь, что он выполнит свой контракт (другими словами, он делает то, что должен делать. Записать, что он должен делать, для некоторых людей - огромный шаг вперед).
Чтобы быть уверенным в том, что код выполняет то, что он должен делать, вы либо пристально смотрите на него, либо пишете тестовый код, который проверяет достаточно случаев, чтобы убедить вас, «если код пройдет все эти тесты, тогда он верен».
Часто вас интересует только публично определенный интерфейс какого-то кода. Если я использую свою библиотеку, я не волнует , как вы сделали это правильно работать, только то , что он делает работу правильно. Я проверяю правильность вашей библиотеки, выполняя модульные тесты.
Но вы создаете библиотеку. Заставить его работать правильно может быть трудно достичь. Допустим, меня заботит только то, что библиотека выполняет операцию X правильно, поэтому у меня есть модульный тест для X. Вы, разработчик, отвечающий за создание библиотеки, реализуете X, комбинируя шаги A, B и C, каждый из которых абсолютно нетривиален. Чтобы ваша библиотека работала, вы добавляете тесты, чтобы убедиться, что A, B и C работают правильно. Вы хотите эти тесты. Говорить «у вас не должно быть юнит-тестов для частных методов» - совершенно бессмысленно. Вы хотите тесты для этих частных методов. Может быть, кто-то скажет вам, что юнит-тестирование приватных методов неверно. Но это только означает, что вы можете называть их не «модульными тестами», а «частными тестами» или как вы их называете.
Язык Swift решает проблему, заключающуюся в том, что вы не хотите выставлять A, B, C как публичные методы только потому, что вы хотите протестировать его, предоставив функциям атрибут «testable». Компилятор позволяет вызывать закрытые тестируемые методы из модульных тестов, но не из не тестового кода.
источник
Да, ты сумасшедший .... как лиса!
Есть несколько способов тестирования приватных методов, некоторые из которых зависят от языка.
В целом, хотя, если вы хотите протестировать приватные методы, вы, вероятно, захотите переместить их в публичные методы на зависимости и протестировать / внедрить их.
источник
Оставайтесь прагматичными. Тестирование особых случаев в частных методах путем установки состояния экземпляра и параметров для открытого метода таким образом, чтобы эти случаи происходили там, часто слишком сложное.
Я добавляю дополнительный
internal
аксессор (вместе с флагомInternalsVisibleTo
тестовой сборки) с четким именемDoSomethingForTesting(parameters)
, чтобы протестировать эти «приватные» методы.Конечно, реализация может измениться, и эти тесты, включая тестовые методы доступа, устаревают. Это все же лучше, чем непроверенные случаи или нечитаемые тесты.
источник