Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 07.08.15 05:04
Оценка: 10 (3) +1
Я считаю тестирование приватных методов плохой практикой. В данный момент, для меня это однозначное зло, но я не хочу быть "зашоренным". Поэтому, хочу задать вопрос....

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

И вопрос в том, какие у вас есть подходы к тестированию именно приватных методов? Придерживаетесь ли вы правила тестировать только public-методы, или это от чего-то зависит?
Re: Тестирование приватных методов класса - за/против?
От: xy012111  
Дата: 07.08.15 07:07
Оценка:
Здравствуйте, another_coder, Вы писали:

_>Я считаю тестирование приватных методов плохой практикой. В данный момент, для меня это однозначное зло, но я не хочу быть "зашоренным". Поэтому, хочу задать вопрос....


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

Потому что, допустим, есть у вас собственный метод какой-то сортировки. Он используется в публичных методах, но через них нет возможности как следует протестировать сортировку. Как быть? Делать сортировку публичной? А ну как завтра придётся изменить как-то её или вообще отказаться от сортировки? Удаление метода из публичного АПИ не самая простая операция. Сложнее удаления приватного.

Приватность или публичность методов — это вопрос инкапсуляции, который, вообще говоря, никак не пересекается с необходимостьючто либо протестировать. Можно искусственно завести правидло — тестировать только открытое АПИ, но при этом могут возникнуть различные проблемы. И придётся или отходить от правила, или выносит в открытое АПИ, то чему там, может быть, и не место.

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

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

  1. Попробовать через этот единственный метод протестировать всё что только можно
  2. Потестрировать какие-то приватные методы, отрабьотав большую часть кейсов на них более конкретно

Путь a) теоритически более верный, но на практике обычно оказываетсядостаточно сложным. Много кейсов нужно продумать и в случае упавшего теста не так просто бывает определить, что же конкретно не раюотает — где в реализации что пошло не так.

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

Просто посомтрите и в каждом конкретном случае решайте по-своему, каким путём пойти в зависимости от тяжести последствий, например. От имеющегося времени. Так же не забывайте, что сегодня сделав б), завтра ничто не мешает сделать a)
Re[2]: Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 07.08.15 08:23
Оценка: +3
Здравствуйте, xy012111.

Хорошо, рассмотрим случай из первого Вашего примера, где есть некоторый приватный метод сортировки внутри другого класса. В этом случае, я вижу два момента, которые следует принимать во внимание.
  1. У Вас 100% есть представление о том, что ожидается от работы метода сортировки. Например, Вы можете точно хотеть, чтобы он сортировал определенным образом данные, а в каких-то конкретных случаях делал исключения.
  2. Этот метод сортировки может быть изменен или заменен другим в любой момент.
Я правильно понял указанные Вами условия?
Если все так, то метод сортировки необходимо вытащить в отдельный модуль (класс с экстеншенами, или класс сортирвки — это зависит от Вашего случая, как удобнее). И тестировать отдельно модуль с сортировкой, проверяя, что он удовлетворяет требованиям. Его затем использовать внутри класса API. Если высока вероятность динамической компановки, использовать DI.
Вот и все: не надо тестирвоать приватные и по коду понятно, что эта штука может быть изменена, удалена. В случае необходимости, от него можно будет изолироваться.

По второй части.

Предположим у нас есть класс с двумя public-методами и очень сложной их внутренней реализацией, завязанной на 50 приватных методов. Как выглядят тесты в случае, когда тестируются приватные методы в том числе? Каких-ниьудь пара тестов на паблик, и куча кейзов на приватные методы. Сами кейзы не понятно как связаны. При этом возникает ситуация. Что приватные методы вроде как работают (тесты зеленые) и паблик методы работают (зеленые), но система нет (тестер говорит). Начинаем выяснять, и оказывается, что не покрыто одно условие, которое мы запиливаем в тесте для приватного метода.
Смотрим дальше: приходит другой девелопер, меняет приватные методы. Паблик как были зеленые, так и остались. А вот приватные он, как бы, починил. ОТдает тестеру, а он ему возвращает снова, говоря что не работает. (Опять тот же баг, что был раньше).

Теперь рассмотрим вариант с тестирование только паблик методов API.
У нас есть требования к тому, как он должен работать. Последовательно каждый из случаев имплементируется. Теперь, если поменяются внутренности, но не поменяются требования, гораздо легче понять где и что упало и поправить это.
Я допускаю, что реинкарнация тоже будет, но значительно меньше. Так же, можно упустить тесты на вспомогательные классы, если они специализированы для этого модуля. Не надо писать тесты на приватные методы. Покрывается только то, что реально надо.
Отредактировано 07.08.2015 8:40 another_coder . Предыдущая версия .
Re[3]: Тестирование приватных методов класса - за/против?
От: xy012111  
Дата: 07.08.15 10:32
Оценка:
Здравствуйте, another_coder, Вы писали:

_>Хорошо, рассмотрим случай из первого Вашего примера, где есть некоторый приватный метод сортировки внутри другого класса. В этом случае, я вижу два момента, которые следует принимать во внимание.

_>[*]У Вас 100% есть представление о том, что ожидается от работы метода сортировки. Например, Вы можете точно хотеть, чтобы он сортировал определенным образом данные, а в каких-то конкретных случаях делал исключения.

Нет. Обычная сортировка. ничего особенного. Допустим, квиксорт, но с какими-то особенностями и микрооптимизациями.

_>[*]Этот метод сортировки может быть изменен или заменен другим в любой момент.


Это да.

_>Если все так, то метод сортировки необходимо вытащить в отдельный модуль (класс с экстеншенами, или класс сортирвки — это зависит от Вашего случая, как удобнее). И тестировать отдельно модуль с сортировкой, проверяя, что он удовлетворяет требованиям. Его затем использовать внутри класса API. Если высока вероятность динамической компановки, использовать DI.


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

_>Вот и все: не надо тестирвоать приватные и по коду понятно, что эта штука может быть изменена, удалена. В случае необходимости, от него можно будет изолироваться.


Вы кажется не поняли, о чём я вам написал. Суть в том, что тестирование приватных методов не является чем-то необходимым, в том смысле, что всегда можно бехз этого обойтись (а вы убеждаете меня именно в этом, не нужно). Но зачастую, в реальной жизни, гораздо удобнее покрыть тестами какие-то приватные методы и тем самым облегчить тестирование открытого функционала. Ведь тесты должны служить для удобства рзработки и не стоит удобством/скоростью разработки жертвовать ради тестов всегда и бесприкословно. На каких-то этапах жизненного цикла это может быть оправдано.

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

Помните: разница между теорией и практикой в том, что в теории разницы нетю, а на практике есть. Так вот тут именно тот случай.
Re[4]: Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 07.08.15 10:50
Оценка:
Здравствуйте, xy012111.

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

Только предположение.
Возможно, в вашей практике было мало "новых" проектов с большой кодовой базой. Мне кажется, когда долго сидишь на одном проекте, где все становится знакомо, такие вещи, как "вынести в отдельный класс", "изолироваться" не являются очень актуальными.
Re[5]: Тестирование приватных методов класса - за/против?
От: xy012111  
Дата: 07.08.15 12:05
Оценка:
Здравствуйте, another_coder, Вы писали:

_>Да все понятно о чем Вы. Смотрите, сами пишете "один небольшой метод" и "с какими-то особенностями и микрооптимизациями". Зачем его тестировать вообще? А если действительно надо, то почему не вытащить в класс-хелпер, в котором и протестировать эти самые особенности и микрооптимизации? Это же не составляет труда сделать. А польза при этом в более наглядном коде и тестах, показывающем, что от чего зависит и как с этим вообще жить.


Хм. Странная формулировка. А зачем всё остальное тестируется? Что бы при изменении кода быть уверенным, что всё работает правильно. Для этого выносить что-то куда нет нужды.

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

Более того, в моём примере сортировки сортируются приватные (nested) типы. Вынос куда-то метода потребует, что бы утекли и ещё кой-какие абстракции.
Re[3]: Тестирование приватных методов класса - за/против?
От: Pavel Dvorkin Россия  
Дата: 07.08.15 16:13
Оценка:
Здравствуйте, another_coder, Вы писали:

_>Если все так, то метод сортировки необходимо вытащить в отдельный модуль (класс с экстеншенами, или класс сортирвки — это зависит от Вашего случая, как удобнее). И тестировать отдельно модуль с сортировкой, проверяя, что он удовлетворяет требованиям. Его затем использовать внутри класса API. Если высока вероятность динамической компановки, использовать DI.


Ради тестирования нарушать структуру классов ? Метод сортировки должен быть там, где ему по логике положено быть, а не по соображениям удобства тестирования. Если ему по логике действительно нужно быть в отдельном классе — туда ему и дорога. Но не по соображениям тестирования.
With best regards
Pavel Dvorkin
Re[4]: Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 07.08.15 16:34
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, another_coder, Вы писали:


_>>Если все так, то метод сортировки необходимо вытащить в отдельный модуль (класс с экстеншенами, или класс сортирвки — это зависит от Вашего случая, как удобнее). И тестировать отдельно модуль с сортировкой, проверяя, что он удовлетворяет требованиям. Его затем использовать внутри класса API. Если высока вероятность динамической компановки, использовать DI.


PD>Ради тестирования нарушать структуру классов ? Метод сортировки должен быть там, где ему по логике положено быть, а не по соображениям удобства тестирования. Если ему по логике действительно нужно быть в отдельном классе — туда ему и дорога. Но не по соображениям тестирования.


Все логично. Либо он является частью внутренней логики и неявно тестируется через публичные классы. Либо он является отдельным модулем и должен тестирвоаться отдельно. Случай, когда тестируется приватный метод, это признак нескольких проблем:
1) методу не место внутри класса из-за более сложной логики, чем требуется
2) какие-то случаи являются лишними и написаны лишние тесты
3) публичные методы недостаточно качественно протестированны

Тут ваша мысль абсолютна понятна. Зачем выделять в какой-то класс, когда можно написать вызов приватного метода через рефлексию и посмотреть как оно работает. Тут больше речь идет о том, чтобы держать свои инструменты, рабочий стол, код, документацию и пр. в порядке. Да, можно и так, как говорите вы, но вероятность проблем будет ниже, если держать все в чистоте. Все очень банально. Если рефакторить раз в неделю и писать сразу нормально, то это не сложно. Если рефакторить раз в месяц, а в остальное время костыли — то легко не получится. С этим никто не спорит.
Отредактировано 07.08.2015 16:35 another_coder . Предыдущая версия .
Re[6]: Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 07.08.15 16:35
Оценка:
Здравствуйте, xy012111, Вы писали:

X>Здравствуйте, another_coder, Вы писали:


_>>Да все понятно о чем Вы. Смотрите, сами пишете "один небольшой метод" и "с какими-то особенностями и микрооптимизациями". Зачем его тестировать вообще? А если действительно надо, то почему не вытащить в класс-хелпер, в котором и протестировать эти самые особенности и микрооптимизации? Это же не составляет труда сделать. А польза при этом в более наглядном коде и тестах, показывающем, что от чего зависит и как с этим вообще жить.


X>Хм. Странная формулировка. А зачем всё остальное тестируется? Что бы при изменении кода быть уверенным, что всё работает правильно. Для этого выносить что-то куда нет нужды.


X>Даже в приватном методе, который меняет данные в двух переменных есть что тестировать, потому что там есть чему не работать. Но выносить куда-от в отдельный класс его смысла нет. Смысл может быть, если вы этот метод хотите из многих мест использовать. Но если не хотите — то выносить может быть и не нужно.


X>Более того, в моём примере сортировки сортируются приватные (nested) типы. Вынос куда-то метода потребует, что бы утекли и ещё кой-какие абстракции.


Все предельно понятно. Я почти на такой же пост ответил в соседнем.
Re[5]: Тестирование приватных методов класса - за/против?
От: Pavel Dvorkin Россия  
Дата: 08.08.15 04:08
Оценка: +1
Здравствуйте, another_coder, Вы писали:

_>Все логично. Либо он является частью внутренней логики и неявно тестируется через публичные классы. Либо он является отдельным модулем и должен тестирвоаться отдельно. Случай, когда тестируется приватный метод, это признак нескольких проблем:


С этим можно было бы согласиться, если бы не одно "но". Тестирование через публичные методы включает в себя тестирование этого приватного метода плюс того, что есть в публичном методе. А публичные методы делаются не из соображений тестирования, а опять-таки из соображений логики класса.
В результате получаются 2 альтернативы, и обе хуже
1. Сделать публичные методы специально для тестирования. Тут, я думаю, комментарии излишни.
2. Тестировать те публичные методы, которые действительно должны быть в классе. Но они содержат вызов приватного и что-то свое (если своего нет, то сделать этот приватный метод публичным, а публичный выкинуть, и все дела). Значит, мы тестируем и приватный метод, и что-то еще. А это что-то еще, возможно, накладывает ограничения на вызов приватного метода. Например, не допускает его вызов с нулевым аргументом. В этом случае мы так никогда и не узнаем, корректно ли отработает этот приватный метод, если ему передать null. Да, можно возразить — раз его вызывают только из публичного, блокирующего передачу null, значит это не так уж важно. Возражение, однако , снимается простым соображением. А если этот приватный метод будет потом вызван еще одним публичным методом, который эту блокировку передачи null не производит ? Обнаружится ошибка довольно быстро, так как для нового публичного метода, будем полагать, тут же будет написан "исчерпывающий" набор тестов. Но когда это будет ? Вполне возможно, что через пару лет, и совсем другим разработчиком в процессе поддержки. И выскажется этот разработчик в адрес первого разработчика весьма нелестно. Непередаваемое удовольствие — получить NullPointerException где-то в кишках библиотеки. Обычно после такого очень хочется эту библиотеку тут же немедленно выкинуть.

Вот так как-то.
With best regards
Pavel Dvorkin
Отредактировано 08.08.2015 4:19 Pavel Dvorkin . Предыдущая версия . Еще …
Отредактировано 08.08.2015 4:09 Pavel Dvorkin . Предыдущая версия .
Re: Тестирование приватных методов класса - за/против?
От: · Великобритания  
Дата: 08.08.15 11:12
Оценка:
Здравствуйте, another_coder, Вы писали:

a> И вопрос в том, какие у вас есть подходы к тестированию именно приватных методов? Придерживаетесь ли вы правила тестировать только public-методы, или это от чего-то зависит?

Кстати, недавно тоже с одной ситуацией столкнулся.
Есть класс, у него внутрях есть некий sequence, 4-байтное число, инициализируемое нулём. Каждый раз, когда дёргается публичный метод, делается инкремент sequence.
Как протестировать поведение объекта, в случае переполнения sequence?
Неужели ради тестов делать публичный метод для произвольного изменения sequence?
avalon/1.0.432
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[2]: Тестирование приватных методов класса - за/против?
От: vsb Казахстан  
Дата: 08.08.15 11:28
Оценка: 2 (1)
Здравствуйте, ·, Вы писали:

·>Неужели ради тестов делать публичный метод для произвольного изменения sequence?


1. reflection.
2. Сделать метод с default visibility, пометить его аннотацией "для тестов". Для этой аннотации желательно сделать статический анализатор, который будет проверять, что этот метод никто кроме тестов не использует, получится аналог private, доступный для тестов и явно задокументированный.

Это я про Java, но в других языках по идее можно подобное сделать, может не так удобно.
Re[6]: Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 08.08.15 11:45
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>С этим можно было бы согласиться, если бы не одно "но". Тестирование через публичные методы включает в себя тестирование этого приватного метода плюс того, что есть в публичном методе. А публичные методы делаются не из соображений тестирования, а опять-таки из соображений логики класса.

PD>В результате получаются 2 альтернативы, и обе хуже
PD>1. Сделать публичные методы специально для тестирования. Тут, я думаю, комментарии излишни.
PD>2. Тестировать те публичные методы, которые действительно должны быть в классе. Но они содержат вызов приватного и что-то свое (если своего нет, то сделать этот приватный метод публичным, а публичный выкинуть, и все дела). Значит, мы тестируем и приватный метод, и что-то еще. А это что-то еще, возможно, накладывает ограничения на вызов приватного метода. Например, не допускает его вызов с нулевым аргументом. В этом случае мы так никогда и не узнаем, корректно ли отработает этот приватный метод, если ему передать null. Да, можно возразить — раз его вызывают только из публичного, блокирующего передачу null, значит это не так уж важно. Возражение, однако , снимается простым соображением. А если этот приватный метод будет потом вызван еще одним публичным методом, который эту блокировку передачи null не производит ? Обнаружится ошибка довольно быстро, так как для нового публичного метода, будем полагать, тут же будет написан "исчерпывающий" набор тестов. Но когда это будет ? Вполне возможно, что через пару лет, и совсем другим разработчиком в процессе поддержки. И выскажется этот разработчик в адрес первого разработчика весьма нелестно. Непередаваемое удовольствие — получить NullPointerException где-то в кишках библиотеки. Обычно после такого очень хочется эту библиотеку тут же немедленно выкинуть.

На практике слово "если" может завести в такие дебри и наломать столько дров, что лучше не оперировать возможностями. Я придерживался бы реальных потребностей. "Благими намерениями вымощена дорога в АД" (с)

Тестировать что-либо ради тестирования — это нонсенс. Задачи юнит-тестов, на мой взгляд, сводятся к тому, чтобы снизить несколько распространенных проблем: реинкарнацию багов, возникновение багов в связанных модулях и пр. При этом в фокус помещается то, как используется модуль другими, а не то, как он устроен внутри. Написание тестов на private-методы, это, на мой взгляд, именно тесты ради тестов, без понимания зачем они нужны. Рассмотрим...

Возьмем Ваш пример: есть public-метод API использующий private-метод. Скорее всего, есть некоторые требования к API, которые говорят, например, что этот public-метод должен возвращать сортированный список элементов, а сортировка может быть разной в зависимости от некоторых условий. Клиенты модуля ожидают именно такое поведение при вызове этого метода. Даже если нет никаких требований, есть определенные ожидания у разработчика к поведению такого метода, еще до момента написания реализации. (Иначе, как писать вообще?)

Совершенно логично, если мы заботимся о стабильности системы, что у нас должен быть ряд тестов, проверяющих правильное поведение public-метода, согласно требованиями. Мы будем его вызывать с набором параметров, соответствующих описанным в требованиях, и проверять результат. Важно ли тут писать еще и тест на private-метод, который тут используется? Допустим, мы решаем, что важно. А что именно, в этом случае тест будет тестировать? Ок, те же самые случаи не будем, чтобы не дублировать, но вот проверку на NULL сделаем. А зачем? Этот случай не возникает вообще при нормальной работе системы. Мы сами его придумали и решили просто потратить время занимаясь перфекционизмом. Такой тест может быть полезен только в случае, когда не все варианты использования public-метода покрыты. Но тогда мы попадаем в ситуацию, о которой я писал в соседней ветке: все тесты зеленые, но система не работает, и баг повторяется.

Смотрим дальше: приходит другой человек и пишет еще один public-метод API. Требования к нему говорят, что он тоже должен возвращать сортированный список. Ок, у нас есть требования и уже понятна сигнатура метода для вызова. В целом сортировка такая же, но с небольшими отличиями. Решаем использовать тот же private-метод и видим, что не все вызовы второго public-метода работают как надо. Найдя причину в private мы можем решить написать собственный метод сортировки, или "усовершенствовать" имеющийся. Если пойдем вторым путём, мы можем сломать первый public, но у нас есть тесты, которые это покажут. И снова вопрос: надо ли писать тест на private-метод? Совершенно нет.

В итоге получается, что тестируя private-методы, мы получаем преимущества только кажущееся. Нам кажется, что мы покрыли все случаи, что система стабильнее, но на практике, это приводит к потере времени и уводит фокус разраба от собственно поставки функционала в необходимом объеме.
Re[2]: Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 08.08.15 11:52
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, another_coder, Вы писали:


a>> И вопрос в том, какие у вас есть подходы к тестированию именно приватных методов? Придерживаетесь ли вы правила тестировать только public-методы, или это от чего-то зависит?

·>Кстати, недавно тоже с одной ситуацией столкнулся.
·>Есть класс, у него внутрях есть некий sequence, 4-байтное число, инициализируемое нулём. Каждый раз, когда дёргается публичный метод, делается инкремент sequence.
·>Как протестировать поведение объекта, в случае переполнения sequence?
·>Неужели ради тестов делать публичный метод для произвольного изменения sequence?

Для того, чтобы ответить, надо знать зачем этот sequence, как он используется в вашей системе и что должно происходить в случае переполнения. Расскажите и посмотрим?
Re[3]: Тестирование приватных методов класса - за/против?
От: · Великобритания  
Дата: 08.08.15 13:11
Оценка:
Здравствуйте, another_coder, Вы писали:

a> Для того, чтобы ответить, надо знать зачем этот sequence, как он используется в вашей системе и что должно происходить в случае переполнения. Расскажите и посмотрим?

Да не важно что, но что-то определённое должно произойти. Например, бросить исключение .
class
{
  private int32 sequence = 0;
  public Message createNewMessage()
  {
     if(sequence  == INT32_MAX) throw Overflow();
     ++sequence;
     return new Message(sequence, ...data...);
  }
}

или сделать что-то специальное
class
{
  private int32 sequence = 0;
  public Message createNewMessage()
  {
     if(sequence  == INT32_MAX)
     {
         sequence = 0;
         return new RequestResetMessage();
     }
     ++sequence;
     return new Message(sequence, ...data...);
  }
}
avalon/1.0.432
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Тестирование приватных методов класса - за/против?
От: · Великобритания  
Дата: 08.08.15 13:11
Оценка:
Здравствуйте, vsb, Вы писали:

vsb> ·>Неужели ради тестов делать публичный метод для произвольного изменения sequence?

vsb> Это я про Java, но в других языках по идее можно подобное сделать, может не так удобно.
да... в java чуть проще... в тестовых фреймворках есть даже готовые утилитные методы изменения приватных полей. У меня c++.
avalon/1.0.432
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Тестирование приватных методов класса - за/против?
От: another_coder Россия  
Дата: 08.08.15 13:42
Оценка:
Здравствуйте, ·.

Вам не надо писать специальный метод. Например, в первом случае метод кинет эксепшн когда кол-во вызовов будет == INT32_MAX. Почувствуйте разницу: именно кол-во вызовов метода, а не потому, что sequence == INT32_MAX. Поэтому Ваш тест должен честно вызвать метод INT32_MAX-1 раз, а после этого проверять выброс Exception. А то, что вы хотите sequence сделать равным INT32_MAX-1 и потом вызвать один раз в тесте неправильно. В таком виде тест ваш будет заточен под реализацию, а не под требования.
Понимаете?

Во втором случае надо проверять, что вернется RequestResetMessage(). Но принцип тот же: seqence не трогаем.
Отредактировано 08.08.2015 13:44 another_coder . Предыдущая версия .
Re[7]: Тестирование приватных методов класса - за/против?
От: Pavel Dvorkin Россия  
Дата: 08.08.15 15:46
Оценка:
Здравствуйте, another_coder, Вы писали:

_>На практике слово "если" может завести в такие дебри и наломать столько дров, что лучше не оперировать возможностями. Я придерживался бы реальных потребностей. "Благими намерениями вымощена дорога в АД" (с)


Давай все же попробуем дрова не ломать, в дебри не заходить и в ад тоже

_>Возьмем Ваш пример: есть public-метод API использующий private-метод. Скорее всего, есть некоторые требования к API, которые говорят, например, что этот public-метод должен возвращать сортированный список элементов, а сортировка может быть разной в зависимости от некоторых условий. Клиенты модуля ожидают именно такое поведение при вызове этого метода. Даже если нет никаких требований, есть определенные ожидания у разработчика к поведению такого метода, еще до момента написания реализации. (Иначе, как писать вообще?)


+1

_>Совершенно логично, если мы заботимся о стабильности системы, что у нас должен быть ряд тестов, проверяющих правильное поведение public-метода, согласно требованиями. Мы будем его вызывать с набором параметров, соответствующих описанным в требованиях, и проверять результат. Важно ли тут писать еще и тест на private-метод, который тут используется? Допустим, мы решаем, что важно. А что именно, в этом случае тест будет тестировать? Ок, те же самые случаи не будем, чтобы не дублировать, но вот проверку на NULL сделаем. А зачем? Этот случай не возникает вообще при нормальной работе системы. Мы сами его придумали и решили просто потратить время занимаясь перфекционизмом. Такой тест может быть полезен только в случае, когда не все варианты использования public-метода покрыты. Но тогда мы попадаем в ситуацию, о которой я писал в соседней ветке: все тесты зеленые, но система не работает, и баг повторяется.


_>Смотрим дальше: приходит другой человек и пишет еще один public-метод API. Требования к нему говорят, что он тоже должен возвращать сортированный список. Ок, у нас есть требования и уже понятна сигнатура метода для вызова. В целом сортировка такая же, но с небольшими отличиями. Решаем использовать тот же private-метод и видим, что не все вызовы второго public-метода работают как надо. Найдя причину в private мы можем решить написать собственный метод сортировки, или "усовершенствовать" имеющийся. Если пойдем вторым путём, мы можем сломать первый public, но у нас есть тесты, которые это покажут. И снова вопрос: надо ли писать тест на private-метод? Совершенно нет.


Почему мы должны что-то ломать ?

Пусть метод a вызывает sort и делает проверку перед вызовом sort, а sort ее не делает. a при null выбрасывает IllegalArgumentException. Все работает.
Теперь делаем метод b, который тоже вызывает sort, но не проверяет. В итоге sort выбрасывает NullPointerException.
Вставляем в b такую же проверку с тем же выбросом IllegalArgumentException, и все опять хорошо.

Только вот для того, чтобы это сделать, нам придется сначала NullPointerException получить, stacktrace поисследовать, чего доброго, что-то рефлектором декомпилировать, понять, в чем причина и проверку свою сделать. И хорошо, если это в одном классе, а если a вызывает sort через несколько классов ?

А теперь контрвариант

Метод a вызывает sort и делает проверку перед вызовом sort, а sort тоже ее делает и тот же IllegalArgumentException выбрасывает. Что изменилось ? Да ничего, если не считать лишней проверки. Кстати, при null до второй проверки дело вообще не дойдет.
Теперь делаем метод b, который тоже вызывает sort, но не проверяет. В итоге sort выбрасывает IllegalArgumentException, который от нее и ожидается. Все ясно — недопустимый ей аргумент передан, не может она сортировать.
Ловим в b этот IllegalArgumentException и принимаем меры, и все опять хорошо.

И ведь в варианте 1 мы обречены помнить, что не дай бог когда-нибудь эту sort вызовем с null. Отныне, присно и вовеки веков. И все лишь потому, что sort не удосужились на null протестировать и код поправить.

А в варианте 2 все замечательно.
With best regards
Pavel Dvorkin
Re[4]: Тестирование приватных методов класса - за/против?
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 08.08.15 15:51
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Ради тестирования нарушать структуру классов?


А почему нет? Улучшение архитектуры обычно приводится как один из главных аргументов в пользу юнит тестов.
Ce n'est que pour vous dire ce que je vous dis.
Re[5]: Тестирование приватных методов класса - за/против?
От: Pavel Dvorkin Россия  
Дата: 08.08.15 15:58
Оценка:
Здравствуйте, Don Reba, Вы писали:

PD>>Ради тестирования нарушать структуру классов?


DR>А почему нет? Улучшение архитектуры обычно приводится как один из главных аргументов в пользу юнит тестов.


Несомненно, если как результат тестирования выяснится, что надо переработать архитектуру — бога ради.
Тут же речь о другом — о создании специальных public методов, которые вообще-то не нужны для работы, а нужны только для тестирования. Поди потом объясни кому-то, что эти public методы ни в коем случае нельзя вызывать в работающем коде, а только для тестов.
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.