|
1 / 1 / 0
Регистрация: 29.10.2013
Сообщений: 9
|
|
Виртуальные методы и юнит-тесты29.10.2013, 15:00. Показов 3470. Ответов 7
Метки нет (Все метки)
В C# пришел недавно из Java, где все методы виртуальные. И сразу столкнулся с тем, что в C# по умолчанию методы невиртуальные, более того, обычно учебники по C# рекомендуют оставлять методы невиртуальными, поскольку это мол повышает их производительность.
Однако вот сейчас вычитал у Рихтера (Richter - CLR via C#, 4ed, pp. 163-164), что это вовсе не так, что нет никакого выигрыша в производительности. Разница в производительности достигается благодаря только тому, что не делается проверка объекта, на котором вызывается метод, на null. А это происходит только для статических методов. Для нестатических методов, неважно, виртуальных или невиртуальных, проверка на null производится, и производительность падает одинаково. Вопрос этот для меня непраздный, ибо еще будучи в Java, завел себе привычку во время юнит-тестов при тестировании метода А, который вызывает метод Б, перегружать метод Б, заменяя заглушкой. Чтобы тестировать только логику метода А. В Java это все делается без раздумий - все же методы виртуальные, а вот по поводу использования такой техники в C# до сего дня были сомнения. В общем, хотел спросить у опытного народа - как он относится к тому, чтобы делать в C# методы виртуальными только для того, чтобы использовать заглушки в тестах.
0
|
|
| 29.10.2013, 15:00 | |
|
Ответы с готовыми решениями:
7
Требуется написать юнит-тесты данного метода по прохождению
Виртуальные методы и наследование |
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||
| 29.10.2013, 15:17 | |||
|
Программы, скомпилированные входящим в состав .NET компилятором, всегда используют виртуальный вызов для нестатических методов, потому вопрос виртуальный/не виртуальный метод уже стоит в области архитектуры, а не производительности.
В результате вы тестируете не свое приложение, а что-то другое. А посему и результат теста не может вызывать доверия.
0
|
|||
|
1 / 1 / 0
Регистрация: 29.10.2013
Сообщений: 9
|
||||
| 29.10.2013, 15:43 [ТС] | ||||
|
Я думаю, что ваш подход оправдан для open-source приложений, где вы публикуете интерфейсы и не хотите открывать для перегрузки лишние методы. Но для приложений другого типа - какая разница, сколько методов можно перегрузить в подклассах? P.S. Надеюсь вы не считаете данный пост дерзостью, учитывая что вам пишет новичок как форума, так и платформы .NET. Просто хотелось бы понять ваши мотивы касательно данных практик программирования.
0
|
||||
|
52 / 45 / 4
Регистрация: 07.10.2010
Сообщений: 95
|
|
| 29.10.2013, 16:32 | |
|
virtual означает, что метод открыт для изменений. И тут возникает вопрос - мы тестируем класс, или отдельный метод? А имет ли смысл тестировать отдельный метод? Скорее нет, чем да. Все равно прийдется тестировать все классы в которых опредленны пергрузки.
Не проще ли сделать нормальную архитетуру, разбить на уровни и использовать DI?
0
|
|
|
1 / 1 / 0
Регистрация: 29.10.2013
Сообщений: 9
|
||||
| 29.10.2013, 17:11 [ТС] | ||||
|
P.S. Я понимаю, что у каждого свои привычки тестирования. В силу того, что я, как правило, пишу приложения, связанные с математическими и научными расчетами, я, как вы уже заметили, имею крен к подробному тестированию, стремясь иногда к 100% покрытию. Поэтому и тестирую поведение отдельных методов - чтобы убедиться, что они во-первых, корректно работают при заданном наборе входных параметров и результатов работы других методов. А потом уж тестирую методы в комплексе.
0
|
||||
|
52 / 45 / 4
Регистрация: 07.10.2010
Сообщений: 95
|
|
| 29.10.2013, 18:50 | |
|
А не перегруженные методы? У нас есть какие то данные и методы манипулирующие ими. Мы меняем один метод. Может ли поменятся поведение других - да, конечно, поэтому мы должны и их тестировать. Поэтому мы тестируем не отдельные методы, а весь класс, в котором были сделанны перегрузки.
DI позволяет перенести всю сложную логику в классы, вместо реальных использовать моки. И по сути оставить для тестирования только скелет. Опять же - тестировать ВСЕ методы не нужно. Можно обойтись пабликами. Ну в крайнем случае протектами.
0
|
|
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||||
| 29.10.2013, 19:24 | |||||||||||
|
Это же вся логика разом похериться может, не говоря о состоянии модуля. Ну отработает тест чуть дольше, делов-то. Куча методов — не проблема, а вот запрос к БД должен подменяться моком. Конечно, не исключено, что я чего-то не знаю. Я как-то не встречал, чтобы специально для тестирования юнита изменялась его же логика. Это ж буковки — в них интонацию и мимику не передашь. Неустранимый дефект общения по переписке. Я просто не люблю тупые аббревиатуры типа "ИМХО". У нас в академических кругах любой текст, не подкрепленный цитатой или ссылкой, считается личным мнением по-умолчанию. А вот если бы машины выпускали с квадратными колесами, потому что так их проще тестировать на предмет устойчивости на дорожном полотне — это совсем другое дело! Если что-то показалось или задело, то приношу извинения — такой цели не стояло.
0
|
|||||||||||
|
1 / 1 / 0
Регистрация: 29.10.2013
Сообщений: 9
|
|||||||||||||||||
| 29.10.2013, 21:43 [ТС] | |||||||||||||||||
|
Ну а если боитесь, что поменяются - так ведь для того и делаются регрессионные тесты, чтобы знать, что сломалось, если вы что-то меняете.
Я и сам не против DI, но пока осваиваю .NET и пока работаю над основами нового проекта, даже не заморачиваюсь освоением Spring.NET. Потому что на данном этапе простоты это не добавит. Хотя конечно, объекты все равно по привычке разрабатываю с прицелом на DI и с принципами POJO.
Тем более, что какой-нибудь там паблик, если его разобрать по ветвлениям кода, может легко дать несколько сотен вариантов исполнения кода. И как его тестировать? Создавать TestFixture с сотней-другой методов, отличающихся только входными и разными другими параметрами? Скорее всего вы создадите пару методов, которые описывают основные сценарии, а остальные баги будете ловить в продакшене. Для моего нынешнего приложения это не вариант. Добавлено через 19 минут Конечно, написание тестов для приватных методов иногда оказывается работой впустую. Потому что обычно есть контракт для паблик-метода, а как он реализован и какие приватные методы вызывает - дело разработчика. Так что если приватные методы меняются, то написанные для них тесты, естественно, устаревают. Поэтому в такой ситуации вы окажетесь правы - тесты для пабликов все еще действительны, тесты для приватных методов нужно писать заново. Естественно, тут нужно трезво оценивать - писать ли вообще для приватных методов тесты. В данном случае на помощь может придти арифметика с комбинаторикой. Предположим, что у меня есть цепочка из 5 методов, в каждом из которых есть 3 варианта развития событий (скажем, if-elseif-else). Сколько всего у вас вариантов развития событий? 3^5=243 - т.е. чтобы протестировать все варианты вам потребуется 243 теста. Если же вы будете их тестировать порознь - тогда вам потребуется по 3 варианта на каждый метод - итого 5*3 = 15 штук. Ну и плюс еще десяток-другой перегруженных методов. Так что вот в такой ситуации для меня очевидно, что лучше написать 30-40 простых методов, которые могут через месяц-другой отправиться в корзину, чем писать 243 "вечных" теста. Да и какие они вечные, если следующая версия может потребовать изменения самого паблик-метода? Добавлено через 58 минут В общем, если заглушка помогает подменить сложную и долгую логику простым кодом, то почему бы ее не применить в более простых случаях? Ведь полезный паттерн!
Но и в том, что когда методы неизолированы, один какой-нить баг может уронить изрядный процент тестов. А если их у вас не одна сотня или тысяча - как прикажете искать в них код с багом?
Зачем тесту для А падать оттого, что метод Д я писал впопыхах среди ночи?
Все что включает взаимодействие нескольких объектов, нескольких паблик-методов - уже интеграционные. Начиная от этой минимальной интеграции и вплоть до интеграции компонентов и подсистем - все интеграционные. Когда вы выходите на тестирование целых вариантов использования (use cases), там уже начинается еще более высокий уровень - функциональные тесты.
"Should you worry about introducing trapdoors to make your code easier to test? Here’s how Extreme Programming guru Ron Jeffries explains it: My car has a diagnostic port and an oil dipstick. There is an inspection port on the side of my furnace and on the front of my oven. My pen cartridges are transparent so I can see if there is ink left. And if I find it useful to add a method to a class to enable me to test it, I do so. It happens once in a while, for example in classes with easy interfaces and complex inner function (probably starting to want an Extract Class). I just give the class what I understand of what it wants, and keep an eye on it to see what it wants next." (Tahchiev - JUnit in Actiun, 2ed) Тестирование, конечно, своеобразная эксплуатация. Но ведь все-таки эксплуатация! И если вместо логов, она дает более точную информацию о работе системы - разве это плохо? Конечно, встает вопрос - так ли уж нужно знать и видеть, как программа работает изнутри? Есть два мнения на это счет: тестирование, когда вы полностью раскрываете реализацию, называется тестированием прозрачного ящика. Напротив, когда вы учитываете только внешние интерфейсы - тестированием черного ящика. К примеру, у Тахчиева (Tahchiev - JUnit in Actiun, 2ed, p.62): "Black box test—A black box test has no knowledge of the internal state or behavior of the system. The test relies solely on the external system interface to verify its correctness... At the other end of the spectrum is white box testing, sometimes called glass box testing. In contrast to black box testing, we use detailed knowledge of the implementation to create tests and drive the testing process. Not only is knowledge of a component’s implementation required, but also of how it interacts with other components. For these reasons, the implementers are the best candidates to create white box tests." Ну и дальше обсуждаются плюсы и минусы каждого подхода...
0
|
|||||||||||||||||
| 29.10.2013, 21:43 | |
|
Помогаю со студенческими работами здесь
8
Upcasting и виртуальные методы Виртуальные статические методы Позднее связывание и виртуальные методы Виртуальные методы,с комментариями пожалуйста Виртуальные методы vs. сокрытие имен Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма).
На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
|
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes.
А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения
развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
|
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ *
Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам
Кирхгофа, решает её и находит:
токи, напряжения и их 1 и 2 производные при t = 0;. . .
|
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым.
Но восстановить их можно так.
Для этого понадобится консольная утилита. . .
|
|
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
|
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
|
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11
— это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
|
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11
Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
|