Методы вспомогательных тестов? - PullRequest
15 голосов
/ 07 декабря 2009

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

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

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

Ответы [ 9 ]

14 голосов
/ 07 декабря 2009

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

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

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

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

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

12 голосов
/ 07 декабря 2009

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

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

8 голосов
/ 12 января 2010

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

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

4 голосов
/ 07 декабря 2009

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

По сути, некоторые люди говорят: «Не тестируйте закрытый код, потому что это нарушает парадигму TDD»

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

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

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

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

3 голосов
/ 07 декабря 2009

Если вы хотите протестировать вспомогательные методы, вы можете изменить их на приватные, но вы можете рассмотреть это.

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

1 голос
/ 07 декабря 2009

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

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

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

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

0 голосов
/ 07 декабря 2009

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

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

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

0 голосов
/ 07 декабря 2009

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

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

0 голосов
/ 07 декабря 2009

У вас есть 2 варианта:

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

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

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

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

...