Подтвердить что ты не робот

Unit test вспомогательные методы?

У меня есть классы, которые ранее имели массивные методы, поэтому я разделил работу этого метода на "вспомогательные" методы.

Эти вспомогательные методы объявляются private для принудительной инкапсуляции, но я хочу unit test использовать большие публичные методы. Хорошо ли unit test вспомогательные методы, так же как если бы один из них выходил из строя из-за общедоступного метода, который вызывает его, он также терпит неудачу, и таким образом мы сможем определить, почему это не удалось?

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

4b9b3361

Ответ 1

Один из способов - опустить private и поместить тесты в один и тот же пакет. Затем тесты могут вызывать внутренние методы, но никто другой (= вне пакета) не может.

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

Ответ 2

Это пахнет, что у вас есть неправильная проблема. То, что вы описали, сродни созданию суб- "unit test", что заставляет меня думать, что ваши модульные тесты действительно тестируют блок в конце концов.

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

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

Обратите внимание, что этот подход изолирует вас от рефакторинга: вы можете изменить реализацию, не изменяя свой тестовый набор (поскольку модульные тесты для вспомогательного объекта продолжают проходить, даже если вспомогательный объект больше не является частью вашей производственной реализации) и вы получаете чистую упаковку реализации и тесты для нее (usecase: вы решили, что bozo-sort является неправильной реализацией и больше не должен использоваться. Если реализация bozo-sort изолирована, вы просто удаляете ее и его тесты. Но когда тесты реализации bozo-sort запутались со всеми другими тестами, там больше мышления).

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

Ответ 3

Если ваш класс действительно такой большой, то кажется, что вы должны разрывать вспомогательные объекты, а не только вспомогательные методы (хотя методы извлечения часто являются шагом на этом пути). Как только вы это сделаете, ваш старый класс станет проще и проще протестировать (возможно, с помощью mocks, возможно, нет), и вы можете напрямую протестировать методы в новых поддерживающих классах.

Мое предпочтение заключается в проверке публичного API объекта. Если это слишком сложно, тогда это намек на то, что объект должен быть разбит.

Ответ 4

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

Вы не должны unit test личную информацию о своей реализации в основном потому, что она может измениться из-за рефакторинга и "перерыва" вашего теста.

Ответ 5

Я довольно шокирован некоторыми ответами здесь.

В сущности, некоторые люди говорят: "Не проверяйте личный код, потому что это нарушает парадигму TDD"

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

Лично я делал бы методы защищенными или дефолтными, записывал тесты, запускал тесты и, при успешном завершении, возвращался к частным. На этом этапе я бы прокомментировал соответствующие тесты и оставил над ними блок инструкций:

/** Извините, но я унаследовал беспорядок... * если вам нужно протестировать эти методы, выставить их в исходном тексте и не комментировать следующие строки * */

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

Ответ 6

Это один из тех случаев, когда я бы сказал, продолжайте и нарушайте правила.

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

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

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

Ответ 7

В основном у вас есть 2 варианта:

  • Увеличить масштаб вспомогательных методов от частного до стандартного. Затем вы можете проверить эти методы (при условии, что тестовые классы находятся в том же пакете, что и объект теста). Это улучшает тестируемость класса, но вы жертвуете некоторой инкапсуляцией

  • Оставьте все так, как есть. Это не позволит вам писать очень мелкозернистые тесты, но не требует, чтобы вы жертвовали какой-либо инкапсуляцией.

Лично я бы выбрал (2), потому что вам не нужно испытывать частные методы. Класс должен быть протестирован через него публичным интерфейсом (который, в свою очередь, вызовет частные методы. Тестирование частных методов может привести к хрупким испытаниям, т.е. Те тесты, которые терпят неудачу, когда изменяется только внутреннее поведение класса.

Существует третий вариант (который я не хочу упоминать): используйте отражение (или какое-то другое voodoo) для вызова частных методов в вашем тестовом классе. Это имеет недостатки (1), а также недостатки, присущие отражающему коду (например, обходит проверку типов и трудно читать)

Ответ 8

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

Лично я бы пошел на более прагматичное решение: держите их в секрете и не пишете модульные тесты. Если вы дойдете до случая, когда открытый метод выходит из строя, и вы не можете понять, почему, но вы считаете, что это может быть проблемой в одном из ваших личных методов, а затем временно сделать их общедоступными, напишите unit test, debug и когда вы закончили, сделайте их приватными и закомментируйте unit test.

Ответ 9

Вы unit test те вспомогательные методы, написав модульные тесты, которые выполняют те части вашего кода.

Вы определили публичный API в этом классе по какой-то причине, не так ли? Проверьте это. Если он работает, класс работает.

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