А почему не применить следующий подход : методы являются private, если нет
#define TEST
иначе они public ?
Тесты могут спокойно их тестировать, вызвать их в production, где не положено, не удастся.
// TEST определен в свойствах проектаclass C {
#if( TEST)
public
#else
private
#endif
static void f() { }
}
class Program
{
static void Main(string[] args)
{
C.f();
}
}
В С++ можно и элегантнее написать
#ifdef TEST
#define ACCESS_LEVEL public
#else
#define ACCESS_LEVEL private
#endif
class C {
ACCESS_LEVEL :
static void f() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
C::f();
return 0;
}
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Don Reba, Вы писали:
PD>>>Ради тестирования нарушать структуру классов?
DR>>А почему нет? Улучшение архитектуры обычно приводится как один из главных аргументов в пользу юнит тестов.
PD>Несомненно, если как результат тестирования выяснится, что надо переработать архитектуру — бога ради. PD>Тут же речь о другом — о создании специальных public методов, которые вообще-то не нужны для работы, а нужны только для тестирования. Поди потом объясни кому-то, что эти public методы ни в коем случае нельзя вызывать в работающем коде, а только для тестов.
О создании методов только для тестов речи не идет. Вы что-то напутали.
Re[7]: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
_>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Здравствуйте, Don Reba, Вы писали:
PD>>>>Ради тестирования нарушать структуру классов?
DR>>>А почему нет? Улучшение архитектуры обычно приводится как один из главных аргументов в пользу юнит тестов.
PD>>Несомненно, если как результат тестирования выяснится, что надо переработать архитектуру — бога ради. PD>>Тут же речь о другом — о создании специальных public методов, которые вообще-то не нужны для работы, а нужны только для тестирования. Поди потом объясни кому-то, что эти public методы ни в коем случае нельзя вызывать в работающем коде, а только для тестов.
_>О создании методов только для тестов речи не идет. Вы что-то напутали.
Да, об этом я писал в другой ветке. Сорри. Но и нарушать структуру класса ради тестирования иным способом — тоже не дело.
With best regards
Pavel Dvorkin
Re[5]: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
_>Поэтому Ваш тест должен честно вызвать метод INT32_MAX-1 раз, а после этого проверять выброс Exception.
Это очевидно, а так же очевидно что оно будет выполняться несколько часов, а то и дней. Разве не очевидно что такой юнит-тест бесполезен, а даже вреден?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Тестирование приватных методов класса - за/против?
Здравствуйте, ·, Вы писали:
·>Здравствуйте, another_coder, Вы писали:
_>>Поэтому Ваш тест должен честно вызвать метод INT32_MAX-1 раз, а после этого проверять выброс Exception. ·>Это очевидно, а так же очевидно что оно будет выполняться несколько часов, а то и дней. Разве не очевидно что такой юнит-тест бесполезен, а даже вреден?
Если рассматривать этот конкретный пример, как реальный, то я бы принял исключение. Все же, нам нужны эффективные решения. Но в большинстве случаев, на моей практике, можно сделать нормально.
Re[8]: Тестирование приватных методов класса - за/против?
Не всё так просто. Предлагаю последовательно расписать требования к методам. Получается следующее:
1) есть метод A(array), принимающий список для сортировки и выбрасывающий IllegalArgumentException, если этот список == null
На основе этих требований мы можем написать тест, который будет проверять, предположим, два случая: нормальную работу и реакцию на null.
2) Теперь хотим написать метод B(array), который, судя по тексту, должен вести себя так же, как A(...)
На основе этих требований пишем аналогичные тесты, которые покажут, что B не работает, как требуется.
Теперь надо разбираться, это безусловно. Но тут есть у разраба возможности: #1 либо поменять sort, #2 либо написать собственный, не меняя то, что работало нормально до этого момента.
Давайте рассмотрим вариант, когда мы меняем sort (#1, Ваш вариант). Тут может возникнуть проблема с тем, что в 3м месте может требоваться именно NullPointerException возвращаемый им. Будем править еще и то место? Ок, давайте поменяем то место и в добавок еще тесты для 3го места поменяем и в добавок еще надо будет делать регрессию всех связанных с 3м мест в системе. И (тада!) проблема разрослась на ровном месте.
Если при этом мы будем писать тесты на private методы, мы будем обречены постоянно подправлять их и актуализировать, не выигрывая ровным счетом ничего.
Контрвариант #2
Мы не трогаем тот код, который работает нормально. Пишем собственный sort, возможно, поверх текущего, и используем его в методе B(). Изменения коснулись только нового метода и связанного с ним функционала.
Как итог
Конечно, это все идеалистические примеры. На практике гораздо больше нюансов следует принимать во внимание. В какие-то моменты #1 будет выгоднее. Но стратегия на то и стратегия, что описывает общий подход, позволяющий добиться хорошего результата. И именно об этом речь.
Re[9]: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
_>Давайте рассмотрим вариант, когда мы меняем sort (#1, Ваш вариант). Тут может возникнуть проблема с тем, что в 3м месте может требоваться именно NullPointerException возвращаемый им.
Вот в этом и вопрос. NPE в sort при null — это так и задумано или ошибка ? Если так и задумано — то, скорее всего, плохо задумано (просто по характеру NPE, его не стоит допускать вообще ), но так и быть, и примем это как часть контракта. Но мы-то полагаем, что NPE — это просто ошибка программиста, которую тест приватного метода должен был устранить, но из-за того, что этого теста нет, ошибка осталась.
А ситуация, когда во 2 и 3 месте нужен именно NPE, уж больно напоминает пресловутое "перекуем баги в фичи"
>Будем править еще и то место? Ок, давайте поменяем то место и в добавок еще тесты для 3го места поменяем и в добавок еще надо будет делать регрессию всех связанных с 3м мест в системе. И (тада!) проблема разрослась на ровном месте.
Именно если бы мы в свое время как следует оттестировали sort, то недопустили бы NPE и ничего не пришлось бы править во 2 и 3 месте.
With best regards
Pavel Dvorkin
Re[10]: Тестирование приватных методов класса - за/против?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, another_coder, Вы писали:
_>>Давайте рассмотрим вариант, когда мы меняем sort (#1, Ваш вариант). Тут может возникнуть проблема с тем, что в 3м месте может требоваться именно NullPointerException возвращаемый им.
PD>Вот в этом и вопрос. NPE в sort при null — это так и задумано или ошибка ? Если так и задумано — то, скорее всего, плохо задумано (просто по характеру NPE, его не стоит допускать вообще ), но так и быть, и примем это как часть контракта. Но мы-то полагаем, что NPE — это просто ошибка программиста, которую тест приватного метода должен был устранить, но из-за того, что этого теста нет, ошибка осталась.
Если public-метод из контракта работает согласно требованиям, то вариант private-метода ДО нового функционала правильный. И все остальные домыслы, всего лишь домыслы. Исходите из требований.
PD>А ситуация, когда во 2 и 3 месте нужен именно NPE, уж больно напоминает пресловутое "перекуем баги в фичи".
>>Будем править еще и то место? Ок, давайте поменяем то место и в добавок еще тесты для 3го места поменяем и в добавок еще надо будет делать регрессию всех связанных с 3м мест в системе. И (тада!) проблема разрослась на ровном месте.
PD>Именно если бы мы в свое время как следует оттестировали sort, то недопустили бы NPE и ничего не пришлось бы править во 2 и 3 месте.
Но если вы исходите из требований, то проблемы с sort нет и можно сделать минимальные изменения, добившись тех же результатов. Что, собственно, в большинстве случаев и требуется.
Re[11]: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
PD>>Вот в этом и вопрос. NPE в sort при null — это так и задумано или ошибка ? Если так и задумано — то, скорее всего, плохо задумано (просто по характеру NPE, его не стоит допускать вообще ), но так и быть, и примем это как часть контракта. Но мы-то полагаем, что NPE — это просто ошибка программиста, которую тест приватного метода должен был устранить, но из-за того, что этого теста нет, ошибка осталась.
_>Если public-метод из контракта работает согласно требованиям, то вариант private-метода ДО нового функционала правильный. И все остальные домыслы, всего лишь домыслы. Исходите из требований.
Так мы далеко пойдем. Ваше утверждение фактически означает индульгенцию на любые ошибки в коде до тех пор, пока публичный контракт не замечает этих ошибок.
Всегда же можно сказать — что Вы ко мне пристали с очевидными ошибками, которые я допустил ? Работает же ? Работает. Ну и отстаньте. Вот когда работаеть не будет — тогда и поговорим.
Я не могу с этим согласиться.
With best regards
Pavel Dvorkin
Re[12]: Тестирование приватных методов класса - за/против?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, another_coder, Вы писали:
PD>>>Вот в этом и вопрос. NPE в sort при null — это так и задумано или ошибка ? Если так и задумано — то, скорее всего, плохо задумано (просто по характеру NPE, его не стоит допускать вообще ), но так и быть, и примем это как часть контракта. Но мы-то полагаем, что NPE — это просто ошибка программиста, которую тест приватного метода должен был устранить, но из-за того, что этого теста нет, ошибка осталась.
_>>Если public-метод из контракта работает согласно требованиям, то вариант private-метода ДО нового функционала правильный. И все остальные домыслы, всего лишь домыслы. Исходите из требований.
PD>Так мы далеко пойдем. Ваше утверждение фактически означает индульгенцию на любые ошибки в коде до тех пор, пока публичный контракт не замечает этих ошибок. PD>Всегда же можно сказать — что Вы ко мне пристали с очевидными ошибками, которые я допустил ? Работает же ? Работает. Ну и отстаньте. Вот когда работаеть не будет — тогда и поговорим. PD>Я не могу с этим согласиться.
По-моему, Вы тут говорите о Вашем личном восприятии того, как должен работать код. Я считаю, что это решается внутри команд и зависит от их стратегии развития кода. Но есть общие правила, о которых я и говорю.
В описанном случае, исходя только лишь из описанных условий, писать тест на private-метод не требуется. Возможно, в других условиях, этот метод надо будет протестировать. Но, скорее всего, в этом случае, его надо будет так же и вытащить в отдельный модуль, т.к. он становится не просто "каким-то методом", а вполне критичным модулем системы.
Re[13]: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
_>По-моему, Вы тут говорите о Вашем личном восприятии того, как должен работать код. Я считаю, что это решается внутри команд и зависит от их стратегии развития кода. Но есть общие правила, о которых я и говорю.
Решается он, я думаю, по-разному, от компаний и команд зависит. Впрочем, не думаю, что код, содержащий явные ошибки, пройдет Code review в нормальной компании. Если ревьюер заметит, то вряд ли удастся отмазаться аргументом "тесты работают, тесты исчерпывающие, отстаньте".
_>В описанном случае, исходя только лишь из описанных условий, писать тест на private-метод не требуется. Возможно, в других условиях, этот метод надо будет протестировать. Но, скорее всего, в этом случае, его надо будет так же и вытащить в отдельный модуль, т.к. он становится не просто "каким-то методом", а вполне критичным модулем системы.
Ладно, предлагаю дискуссию закончить. Стороны обменялись мнениями, к согласию не пришли, что, впрочем, на RSDN скорее правило, чем исключение.
Спасибо за обсуждение.
With best regards
Pavel Dvorkin
Re[14]: Тестирование приватных методов класса - за/против?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD> Решается он, я думаю, по-разному, от компаний и команд зависит. Впрочем, не думаю, что код, содержащий явные ошибки, пройдет Code review в нормальной компании. Если ревьюер заметит, то вряд ли удастся отмазаться аргументом "тесты работают, тесты исчерпывающие, отстаньте".
Что, в общем-то, правильно. Если ревьювер так уверен, что тут ошибка — пусть напишет тест её воспроизводящий, это будет объективное мнение, а не субъективное "я так вижу, это баг".
Здравствуйте, another_coder, Вы писали:
_>Я считаю тестирование приватных методов плохой практикой. В данный момент, для меня это однозначное зло, но я не хочу быть "зашоренным". Поэтому, хочу задать вопрос....
_>Есть несколько источников, где хорошо объясняется почему. Коротко можно суммировать так: _>
_>тесты становятся слишком хрупкими _>тесты не показывают все варианты работы с public-методами _>тесты приватных методов тестируют то, КАК реализован внутри некий модель, вместо тестирования его поведения (требований) _>появляются избыточные тесты на неиспользуемые приватные методы _>_>Тут сразу отмечу, что если вдруг возникает реальная необходимость тестировать приватный метод, из-за его сложности, то этой явный знак того, что ему не место внутри этого класса. Надо вынести во внешний и тестировать как отдельный модуль.
_>И вопрос в том, какие у вас есть подходы к тестированию именно приватных методов? Придерживаетесь ли вы правила тестировать только public-методы, или это от чего-то зависит?
Я думаю, может статься, что, тестируя приватное, бывает проще добиться основной цели, то есть написать работающий код.
К сожалению, не всегда интерфейсы прибиты гвоздями навеки, поэтому тесты публичных методов тоже могут быть хрупкими, особенно для классов внутренней реализации, не видных "клиенту".
Re: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
_>Я считаю тестирование приватных методов плохой практикой. В данный момент, для меня это однозначное зло, но я не хочу быть "зашоренным". Поэтому, хочу задать вопрос....
_>Есть несколько источников, где хорошо объясняется почему. Коротко можно суммировать так: _>
_>тесты становятся слишком хрупкими _>тесты не показывают все варианты работы с public-методами _>тесты приватных методов тестируют то, КАК реализован внутри некий модель, вместо тестирования его поведения (требований) _>появляются избыточные тесты на неиспользуемые приватные методы _>_>Тут сразу отмечу, что если вдруг возникает реальная необходимость тестировать приватный метод, из-за его сложности, то этой явный знак того, что ему не место внутри этого класса. Надо вынести во внешний и тестировать как отдельный модуль.
_>И вопрос в том, какие у вас есть подходы к тестированию именно приватных методов? Придерживаетесь ли вы правила тестировать только public-методы, или это от чего-то зависит?
Если нужно тестировать методы, то значит объект ненормален и представляет собой структуру данных и процедуры по рабо с ними.
Re: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
_>Придерживаетесь ли вы правила тестировать только public-методы, или это от чего-то зависит?
Неправильно говорить о тестировании методов (хоть паблик, хоть не паблик). Говорить нужно о тестировании решения задачи. Решение обычно обладает интерфейсом. Через этот самый интерфейс и нужно смотреть, получаются ли ожидаемые результаты в интересующих сценариях.
Сомнения про паблик-непаблик говорят о том, что задача была сравнительно большая и вы предпочли думать, что она состоит из под-задач. В этом случае просто не говорите "1 задача", говорите "5 задач" из которых одна — та главная, а остальные 4 — это то, что у неё внутри. При таком взгляде на вещи у вас будет 5 задач, 5 решений и 5 интерфейсов.
"5 решений и 5 интерфейсов" обычно соответствуют чему-то типа 5 классов или может быть 1 классу с 5 методами — это не очень важно. Важно что есть решения и эти решения можно использовать через их интерфейсы.
Re: Тестирование приватных методов класса - за/против?
Здравствуйте, another_coder, Вы писали:
_>Я считаю тестирование приватных методов плохой практикой. В данный момент, для меня это однозначное зло, но я не хочу быть "зашоренным". Поэтому, хочу задать вопрос....
_>Есть несколько источников, где хорошо объясняется почему. Коротко можно суммировать так: _>
_>тесты становятся слишком хрупкими _>тесты не показывают все варианты работы с public-методами _>тесты приватных методов тестируют то, КАК реализован внутри некий модель, вместо тестирования его поведения (требований) _>появляются избыточные тесты на неиспользуемые приватные методы _>_>Тут сразу отмечу, что если вдруг возникает реальная необходимость тестировать приватный метод, из-за его сложности, то этой явный знак того, что ему не место внутри этого класса. Надо вынести во внешний и тестировать как отдельный модуль.
_>И вопрос в том, какие у вас есть подходы к тестированию именно приватных методов? Придерживаетесь ли вы правила тестировать только public-методы, или это от чего-то зависит?
Есть разные подходы к тестированию, имеющие разную трудоемкость.
1. тестирование по требованиям
У нас есть API, у нас есть ряд требований к этому API, мы проверяем эти требования. Из плюсов — понятность скоупа тестирования, гарантии обратной совместимости в рамках написанных тестов, из минусов — много работы при написании тестов, много работы при изменении API (т.к. тестов много и их надо править)
2. прагматичное тестирование
Если мы написали тест и он ни разу не упал, то его можно было бы и не писать, верно? При этом подходе тесты пишутся на функционал, который либо легко сломать (сложные алгоритмы, хрупкие участки приложения), либо на критичный функционал (без которого приложение невозможно использовать). Плюсы — меньше трудоемкость, минусы — решение о написании тестов принимается на основе опыта/интуиции, меньше надежность результата (может компенсироваться приемочными тестами)
Я думаю, это отвечает на вопрос о тестировании приватных методов.