Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Java Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
 Тестирование private методов  [new]
da17
Member

Откуда:
Сообщений: 448
Добрый день, подскажите, если у класса есть private метод, как его можно протестировать при помощи JUnit. Можно наверное его сделать public, состояние класса он не меняет и ничего страшного, но вот нигде кроме этого класса этот метод не нужен и хочется как-то иначе.
21 май 21, 12:17    [22325219]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
kolchanov
Member

Откуда: Питер
Сообщений: 202
Если кратко - не надо тестировать private методы.

Подробнее написано в куче мест, например:
https://anthonysciamanna.com/2016/02/14/should-private-methods-be-tested.html
21 май 21, 12:28    [22325224]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
Stanislav Bashkyrtsev
Member

Откуда: СПб
Сообщений: 137
Но если все-таки захочется открыть метод, то его не обязательно делать public. Он может остаться package private ибо тесты обычно помещаются в тот же пакет что и тестируемые классы.

Ну еще есть вариант Reflection конечно, но выглядеть такой тест будет так себе :)

Сообщение было отредактировано: 21 май 21, 15:34
21 май 21, 15:41    [22325341]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
mayton
Member

Откуда: loopback
Сообщений: 51389
Конечно не надо тестировать private-методы. Если вы - owner кода - то сделайте его хотя-бы видимым
в области пакета.

Если код не ваш и чужой то тем более не стоит тестировать. Его владалец может в новой версии удалить этот
метод и что вы будете с этим фактом делать.

Я думаю что тема технически перекликается с модульностью (java9-modules) и обсуждать ее надо именно
в таком ключе. Не ломать и хачить приватное, а разбираться почему вообще этот метод приватный и что за
функционал от него нам понадобилось тестировать, и компетентны ли МЫ вообще брать информацию из
чего-то внутреннего и закрытого от спецификаций.
21 май 21, 16:22    [22325372]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
asv79
Member

Откуда: Тверь
Сообщений: 3319
если хочешь тестировать private методы- самое верное решение сделать из package private
то есть в сигнатуре метода просто убрать модификатор доступа
далее просто сгенерировать тесты на нужный класс- автоматом создаться пакет - в котором эти методы будут видны
ну и извне эти методы не буду видны,как и private- тоесть безопасность не пострадает
22 май 21, 19:40    [22325745]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
asv79
Member

Откуда: Тверь
Сообщений: 3319
mayton
Конечно не надо тестировать private-методы.

тут ты не прав- по факту все методы в коде private- кроме тех,что торчат на контроллерах- и все это нужно тестировать
поэтому такие ситуации обыгрываются как package-private
а тестировать надо обязательно иначе на прод будет уезжать то,чего вы не ждали
22 май 21, 19:48    [22325748]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
mayton
Member

Откуда: loopback
Сообщений: 51389
asv79
mayton
Конечно не надо тестировать private-методы.

тут ты не прав- по факту все методы в коде private- кроме тех,что торчат на контроллерах- и все это нужно тестировать
поэтому такие ситуации обыгрываются как package-private
а тестировать надо обязательно иначе на прод будет уезжать то,чего вы не ждали

Приведи пример кода где тебе очень-очень нужно тестировать что-то приватное.
22 май 21, 20:21    [22325757]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
asv79
Member

Откуда: Тверь
Сообщений: 3319
mayton,
легко- те же самые маперы
22 май 21, 22:00    [22325769]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
mayton
Member

Откуда: loopback
Сообщений: 51389
Все равно непонятно.
22 май 21, 23:47    [22325783]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
da17
Member

Откуда:
Сообщений: 448
Вот решил попробовать Junit 5 и там уже кстати вроде разрешили тестить private методы. Хотя на своем примеры сам натолкнулся на то, что это не ОК, когда передал на вход ф-ии некорректные данные.
26 май 21, 12:18    [22327359]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
mayton
Member

Откуда: loopback
Сообщений: 51389
Должен быть принцип тестирования ящика. Подал а вход что-то. Проверил на выходе нечто.

А если тебе надо взломать ящик - то тут... вроде как декомпозиция была сделана неверно.
Тоесть тут уже либо SingleResp/OpenClosed либо взламывай private но тогда не жалуйся
что плохое ООП.

Абсурд получается. С одной стороны на каждом собесе тебя спросят зачем нужно сокрытие
и с другой стороны ты сам-же пытаешся его нарушить в тестах. А тесты - это иммитация
эксплуатации системы.
26 май 21, 12:29    [22327372]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 8254
da17,
Дай пример метода и пример кода.
Ведь он никому больше в ИС не нужен кроме этого класса?
26 май 21, 12:48    [22327387]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
da17
Member

Откуда:
Сообщений: 448
PetroNotC Sharp, а я подумал и понял идею о том, что не надо тестировать private методы. Если еще смогу придумать зачем это надо, пока все понял.
26 май 21, 12:54    [22327393]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
andreykaT
Member

Откуда: =||==
Сообщений: 3402
mayton
asv79
пропущено...

тут ты не прав- по факту все методы в коде private- кроме тех,что торчат на контроллерах- и все это нужно тестировать
поэтому такие ситуации обыгрываются как package-private
а тестировать надо обязательно иначе на прод будет уезжать то,чего вы не ждали

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

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

я иногда так делаю и основной класс чище получается и потестить что то этакое можно. опять же оставляем хотя бы пакадж прайват.
26 май 21, 16:40    [22327560]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
andreykaT
Member

Откуда: =||==
Сообщений: 3402
asv79
mayton
Конечно не надо тестировать private-методы.

тут ты не прав- по факту все методы в коде private- кроме тех,что торчат на контроллерах- и все это нужно тестировать
поэтому такие ситуации обыгрываются как package-private
а тестировать надо обязательно иначе на прод будет уезжать то,чего вы не ждали

так тестируй публичный метод который эти прайваты использует. или ты хочешь тестировать прайват методы в классе где никаких других кроме прайватов нет? :) и конструктар тоже прайват?
26 май 21, 16:41    [22327562]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
gmugar
Member

Откуда:
Сообщений: 23
da17
PetroNotC Sharp, а я подумал и понял идею о том, что не надо тестировать private методы. Если еще смогу придумать зачем это надо, пока все понял.

Это ни зачем и никогда не надо.
Eсли класс нельзя на 100% покрыть тестами через его не приватный интерфейс - у тебя плохой дизайн класса. всегда. без исключений.
Cледствия:
1. если без PowerMock никак, то что не так
2. если в классе надо ослаблять видимость (например с private на package-private) только ради тестирования, то что-то не так
3. да, именно поэтому, Dependency Injection всегда и только - через конструктор
4. да, именно поэтому, private @PostConstruct/@PostLoad и т.п. - отвратительный anti-pattern которого надо избегать любой ценой
5. вообще любой вид инъекции в приватные поля и или методы - фу таким быть. И то что так можно даже в родных API (JPA, JAXB и т.д.) не оправдание
27 май 21, 14:40    [22328003]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
mayton
Member

Откуда: loopback
Сообщений: 51389
Да и есть хорошее правило что код должен быть - testable by design изначально.

Mockito/PowerMock - играют на особенностях ООП в Java но в то-же время противоречат идеям ООП в принципе.
Поэтому их нельзя считать "честным" тестированием. Тоже самое что если-бы С++ делали reinterpret_cast или что-то
подобное по отношению к инкапсулируемым полям.
27 май 21, 15:17    [22328045]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
Stanislav Bashkyrtsev
Member

Откуда: СПб
Сообщений: 137
gmugar
Eсли класс нельзя на 100% покрыть тестами через его не приватный интерфейс - у тебя плохой дизайн класса. всегда. без исключений.
Логику очень часть неудобно покрывать через public интерфейс. Потому как наружу класс может отдавать только конечные результаты вычислений, а нам удобней протестировать сначала промежуточные результаты. В итоге нам приходится идти на поводу у тестов ухудшая дизайн: разбивать логику на доп классы или же открывать какие-то методы.

Реальный пример: есть робот который умеет переливать жидкость из пробирок в другие пробирки. Одна из команд представленна в виде: ВсосатьЖидкость(сколько, откуда, еще доп параметры). Робот принимает на вход CSV, соответственно классу нужен только один публичный метод: toCsv(). Но в тестах парсить CSV для проверки расчетов очень не удобно из-за чего приходится открывать кой-какие внутренности.

А некоторые вещи тестировать через public API в принципе невозможно. Например, мы не можем протестировать в какой момент HashMap делает rehashing, хотя это обязательная составляющая алгоритма без которой весь класс превращается в тыкву.

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

Сообщение было отредактировано: 27 май 21, 17:16
27 май 21, 17:23    [22328125]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
mayton
Member

Откуда: loopback
Сообщений: 51389
В данном топике речь идет о тестах на correctness. Здесь мы проверяем бизнес сценарии использования компонентов.

Тесты перформанса (в т.ч) с использованием JMH - это отдельная и сложная тема. Они настолько не похожи
на тесты корректности что я-бы их даже не объединял. В проектах для них создают отдельные группы тестирования
и заводят отдельные фазы CI.

Вообще занятие задачами перформанса - последовательно "калечит код". Это фраза Шипилева. Он даже рисовал
кривую качества кода / перформанса и эта гривая имеля ярко выраженный экстремум. Тоесть была точка где
и код красив и перформанс - более-менее и дальше чтоб хоть немножко (на 2-3%) поднять speed-up нужно
было сломать 50% кода и сделать его нечитабельным и неудобным к использованию. Появляются работы
с byte[], char[], c пакетом unsafe e.t.c.

Яркий пример - BlockingQueue и Disruptor. Если их сравнивать по способу использования то видно что первый - удобен
а второй нет.
27 май 21, 17:49    [22328146]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
gmugar
Member

Откуда:
Сообщений: 23
Stanislav Bashkyrtsev
Логику очень часть неудобно покрывать через public интерфейс. Потому как наружу класс может отдавать только конечные результаты вычислений, а нам удобней протестировать сначала промежуточные результаты. В итоге нам приходится идти на поводу у тестов ухудшая дизайн: разбивать логику на доп классы или же открывать какие-то методы.

Реальный пример: есть робот который умеет переливать жидкость из пробирок в другие пробирки. Одна из команд представленна в виде: ВсосатьЖидкость(сколько, откуда, еще доп параметры). Робот принимает на вход CSV, соответственно классу нужен только один публичный метод: toCsv(). Но в тестах парсить CSV для проверки расчетов очень не удобно из-за чего приходится открывать кой-какие внутренности.

Это вот как раз и есть то, как делать нельзя. Никогда.
Вы тут фактически сказали "мне не удобно тестировать через честное паблик API класса, поэтому я буду срезать углы".
Тем самым закладываются сразу две мины:
1. вы протестировали класс не так как он будет реально использоваться.
2. вы подставили людей, которые при рефакторинге private кишок класса, напорятся на какие-то странные тесты.

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

Но тестировать приваты - это не номральный путь. В нормальном проекте такое никогда не пройдет code review.
27 май 21, 19:46    [22328184]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
Stanislav Bashkyrtsev
Member

Откуда: СПб
Сообщений: 137
mayton
Тесты перформанса (в т.ч) с использованием JMH - это отдельная и сложная тема.
Я ничего не говорил про JMH и пр. Я не хочу сравнивать две реализации хеш таблиц, я хочу убедиться что свою хеш таблицу с external chaining'ом я реализовал правильно. Т.е. что сам алгоритм написан by the book. И это было бы легко сделать, если бы бакеты были доступны в тестах. Однако это нарушение инкапсуляции.
gmugar
Это вот как раз и есть то, как делать нельзя. Никогда.
Сразу видно что веду дискуссию с опытным человеком :)
gmugar
1. вы протестировали класс не так как он будет реально использоваться.
Я протестирую его и через public API тоже. Но таких тестов я напишу меньше потому как мне останется проверить лишь то что в строку все собирается верно. А саму математику я смогу протестировать нарушив инкапсуляцию.
gmugar
2. вы подставили людей, которые при рефакторинге private кишок класса, напорятся на какие-то странные тесты.
В сложность создания и поддержки проекта входит как написание prod, так и тестового кода. Если мне при рефакторинге прийдется порефакторить так же тесты и я потрачу на это дополнительных 10 мин, я не буду сильно переживать. А если моему коллеге прийдется потратить доп день на написание сложных тестов в которых еще попробуй разберись потом, то не уверен что оценю этот труд. В какой-то момент эти тесты тоже прийдется рефакторить, а т.к. они будут сложными, то этот рефакторинг опять же усложнится.
gmugar
И наконец, если написать тест реально сдожно, это, опять же, яркий сигнал, что что-то не так с дизаном класса.
Это уже какое-то новое правило, я тут идею не совсем понял. Почему сложные тесты - это сигнал плохого дизайна? Я видел много простых тестов в ужасных проектах. И там же видел много сложных тестов. И в хороших проектах видел и те, и другие. В общем не замечал пока никакой корреляции.

Сообщение было отредактировано: 27 май 21, 23:04
27 май 21, 23:10    [22328263]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
mayton
Member

Откуда: loopback
Сообщений: 51389
Stanislav Bashkyrtsev
mayton
Тесты перформанса (в т.ч) с использованием JMH - это отдельная и сложная тема.
Я ничего не говорил про JMH и пр. Я не хочу сравнивать две реализации хеш таблиц, я хочу убедиться что свою хеш таблицу с external chaining'ом я реализовал правильно. Т.е. что сам алгоритм написан by the book. И это было бы легко сделать, если бы бакеты были доступны в тестах. Однако это нарушение инкапсуляции.

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

То о чем рассказываете вы насколько далекО от тестинга качества бизнес-логики что его можно просто выделить в одельную
категорию и отменить для нее законы ООП. В самом деле. Зачем вам ООП когда вы создаете свою структуру данных.
Вот создайте ее. Доработайте до конца. И после этого уже займитесь инкапсуляцией. Это будет в духе SingleResp/OpenClosed.

Вот такое вот IMHO.
28 май 21, 00:07    [22328270]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
gmugar
Member

Откуда:
Сообщений: 23
Stanislav Bashkyrtsev
Я протестирую его и через public API тоже. Но таких тестов я напишу меньше потому как мне останется проверить лишь то что в строку все собирается верно. А саму математику я смогу протестировать нарушив инкапсуляцию.

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

Вы, уже несколько раз написали, что (в вашем примере) так делается потому что через public API тестировать сложно.
Но с каких пор "сложно" стало аргументом в пользу нарушения инкапсуляции?
это аргумент ровно в пользу того, что надо что-то менять чтобы сложно не было.

Stanislav Bashkyrtsev
А если моему коллеге придется потратить доп день на написание сложных тестов в которых еще попробуй разберись потом

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

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

Stanislav Bashkyrtsev
Это уже какое-то новое правило, я тут идею не совсем понял. Почему сложные тесты - это сигнал плохого дизайна? Я видел много простых тестов в ужасных проектах. И там же видел много сложных тестов. И в хороших проектах видел и те, и другие. В общем не замечал пока никакой корреляции.

мой опыт как раз обычно четко показывал эту зависимость.
к самим unit test-ам обычно предъявляют ряд требований. как минимум: Stateless, Easy to write, Readable, Reliable, Fast, "unit, but not integration".
и логика дальше простая:
если тест не соответствуют требованиям - менять тест, чтобы соответсвовал
если привести в соответствие не удается из-за тестируемого кода - менять код, чтобы тест соответсвовал

отсюда появляется понятие Untestable Code и разные проистекающие из этого понятия anti-patters.

"Unit tests also aid the design" (c) Robert C. Martin (Uncle Bob)
28 май 21, 11:32    [22328387]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
Stanislav Bashkyrtsev
Member

Откуда: СПб
Сообщений: 137
gmugar
При всем уважении, я вашу аргументацию не понимаю и не принимаю.
Я не удивлен :)
gmugar
Если для вас нарушение инкапсуляции это нормально - то мы в разных мирах.
Инкапсуляция, как и другие принципы - они не просто из ниоткуда пришли. Если не следовать этим принципам слепо, а понимать зачем и почему, то появляется намного больше вариантов решения проблем. Потому как теперь мы можем взвешивать что хуже: соблюсти этот принцип, но сделать что-то другое сложней. Либо нарушить принцип, но сделать что-то другое проще. Когда встает такой вопрос - мы в любом случае отхватываем проблем, осталось только решить какая из проблем дешевле.
gmugar
но я бы это просто на два класса разбил:
1. класс который делает расчеты и возвращает их в виде какой-то "простотестируемой" структуры данных
2. класс который по этой структуре данных генерирует CSV
Я ждал когда будет предложен этот вариант. Ведь именно он якобы решает все проблемы: и тестировать проще, и инкапсуляцию можем соблюдать. Но:
1. Если этот доп класс будет public, то тут два варианта:
1.а Мы его предаем в конструктор тому кто создает CSV. В таком случае мы усложнили клиентский код. Т.е. ради тестов мы усложнили прод код.
1.б Мы его создаем внутри класса который в итоге генерит CSV. И если мы их тестируем отдельно, то мы предполагаем что CSV класс использует класс вычислениями и тем самым опять же нарушаем инкапсуляцию.
2. Если этот доп класс будет package private, то:
2.а Мы все равно тестируем не Public API. Т.е. по сути это то же самое что тестировать не public метод.
2.б То же что и в 1.б
gmugar
"Unit tests also aid the design" (c) Robert C. Martin (Uncle Bob)
Не верь всему что пишут на заборах.
28 май 21, 14:16    [22328444]     Ответить | Цитировать Сообщить модератору
 Re: Тестирование private методов  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 9651
Stanislav Bashkyrtsev,
+++

gmugar

Вы, уже несколько раз написали, что (в вашем примере) так делается потому что через public API тестировать сложно.
Но с каких пор "сложно" стало аргументом в пользу нарушения инкапсуляции?

А что есть инкапсуляция и что в ней настолько ценного, что ради нее нужно гланды череж ж... лечить?
Если инкапсуляция мешает разработке, тестированию, использованию в продуктиве - да ну нафиг такую инкапсуляцию.
Бизнес задачи писать/решать нужно, а не перед статуей инкапсуляции UML-диаграммы из распечатанных листингов выкладывать.

IMHO
28 май 21, 14:24    [22328450]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
Все форумы / Java Ответить