|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
|||||||||||
Тест простого метода02.06.2025, 21:16. Показов 7990. Ответов 100
Метки нет (Все метки)
Решил попробовать написть тест для одного из методов, где без тестов реально иногда баги вылезают при доработках.
Метод простой - получает на вход подключение к БД, возвращает в виде многоуровневой структуры объектов информацию обо всей структуре БД (таблицы, колонки, индексы, связи, триггеры и т.п.). Общая структура теста в итоге получилась такая:
1. SQL-скрипты, которые делают выборку из 'information_schema' в методе 'Parse'. 2. Логику раскладывания данных из 'information_schema' в экземпляр 'Database'. Однако, если кто-то из разработчиков дополнит обозначенные два пункта новым функционалом, не затронув существующий, тест продолжит корректно продоходить, но при этом фактически не будет покрывать все возможные сценарии метода 'DatabaseParser.Parse'. Получается, что нужен ещё один тест, который будет контролировать, что структура типа 'Database' (и всех используемых в нём типов, состав всех енумов) строго соответствуют ожидаемому состоянию. Т.е. получается:
1. Дополнить метод 'PreapareTestDb' новыми сценариями. 2. Дописать в 'expectedDbStructure.Equals' логику сравнения для новых свойств/типов. P.S.: вопрос - как сделать это правильно ? Потому как сейчас это выглядит слишком громоздко (в плане написания всех вспомогательных методов и подготовки тестовых данных). И не слишком надёжно, т.к. по сути оставляет шанс, что первый тест попросту забудут доработать под новые сценарии, т.к. он просто пройдёт, и его просто не заметят.
0
|
|||||||||||
| 02.06.2025, 21:16 | |
|
Ответы с готовыми решениями:
100
Полиморфизм: вызов метода базового класса, переопределенного метода и нового метода Юнит-тест для метода Unit-тест для void метода |
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
|||||
| 03.06.2025, 12:20 [ТС] | |||||
|
У меня же тут надо тестировать именно SQL-запросы и интерпретацию их результатов, потому у меня вон тот вариант, как в Dapper-тестах.
0
|
|||||
|
|
||
| 03.06.2025, 12:26 | ||
0
|
||
|
|
||
| 03.06.2025, 13:14 | ||
|
Вам нужно проверить что метод отработал и вернул нужные данные -- проверяйте только это и ничего больше. Вам нужно проверить вызов select * from scheme? Пишем тест, проверит это и опять же -- ничего больше.Замечу что ваше "не хочеться усложнять код" как раз и мешает легко проверить этот вызов. Так бы вы протестировали непосредственный класс взаимодействия с БД, без включения логики сравнения фактическое схемы и описанной в json (причём можно вынести в отдельный проект, чтобы остальные тесты были атомарными). А верхний DatabaseParser не имел бы представления с чем он там работает, главное чтобы правильно выполнял сравнение и вызов изменений. "Разделяй и властвуй" в программировании очень удачно работает. Не по теме: P.S. отдельно замечу что тоже не уловил задум этого json, по которому приводят БД к какому-либо виду. Обычно работают через версии и миграции. Проблема в том что "убрать индекс" ещё можно без последствий, а вот убрать колонку в таблице -- это будь-те добры сначала проверьте что она нигде не используется в качестве FK. Или вообще типичная ситуация -- добавить таблицу и заполнить её на основе десятка других таблиц. Код который будет всё это учитывать должен быть немаленьким.
1
|
||
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
|||||||||||||||||
| 03.06.2025, 13:37 [ТС] | |||||||||||||||||
|
При этом, где-то внутри того же класса парсера, есть приватные методы, которые содержат в себе в т.ч. весь SQL и интерпретацию его результатов, которые выполняют какие-то маленькие задачи типа:
1. Сделать сборку с тестами "дружественной" к тестируемой сборке. Тогда она сможет видеть все 'class Some' и 'static class Other' из этой сборки (т.е. для тестирования не придётся рефлексию использовать). При этом все реальные проекты, которые эту библиотеку используют, не получат доступа к внутренним деталям реализации. 2. Все простые приватные методы сделать публичными, но разместить их во внутренних классах, ну т.е. что-то типа:
А метод парсера, который разбирает список колонок из БД и на основании этого реализует какую-то логику, будет работать поверх абстрации 'IColumnsProvider', а потому при его тестировании можно будет использовать заглушку реализации 'IColumnsProvider', работающую не напрямую с БД, а предоставляющую тестовые данные из какой-то статичной коллекции. Примерно такая суть?
0
|
|||||||||||||||||
|
|
|
| 03.06.2025, 19:53 | |
|
По идеи "да", но читал бегло. То что некоторые классы интёрнал это грустно, особенно если ваш проект имеет цифровую подпись. Без неё просто указываем в асембли дружественные асембл-нейм (самих тестов, и вроде ещё мок либы, там прям в ошибке подскажет чего не хватает). С подписью там нужно строгие имена указывать или что-то в этом духе (я так особо и не разобрался).
0
|
|
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
||||||||||||
| 03.06.2025, 20:17 [ТС] | ||||||||||||
|
Но его надо тестировать. Я попробовал через рефлексию, но это как-то очень уж утомительно Если описать класс как:
Или ещё какие-то варианты есть, как тестировать внутренний функционал, не раскрывая его наружу?
0
|
||||||||||||
|
|
||
| 03.06.2025, 21:22 | ||
|
Я лично писал так же через InternalsVisibleTo, но скрывать внутрянку доводилось только на личных проектах для баловства. На продакшен обычно все и всё фигачат public без задней мысли
1
|
||
|
|
||
| 03.06.2025, 21:48 | ||
|
kotelok, не не не! Понимаю ваш энтузиазм в познании тестирования, но вас повело не туда...
Sealed - запечатанные классы тестируются особым образом, причем для этого заранее предусматриваются интерфейсы с теми же членами, что и запечатанный класс. Создаются re-preventative объекты этих классов и они спокойно тестируются. Вложенная логика первичных original классов при этом не раскрывается. А вообще, лучше через моки. Добавлено через 1 минуту
1
|
||
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
||
| 03.06.2025, 21:52 [ТС] | ||
|
Вопрос в том, что внутри сборки есть некий класс, который реализует часть внутренней логики и, соответственно, он не имеет модификатора 'publiс', не реализует никакие интерфейсы. И этот класс не будет виден из сборки с тестами, т.к. оно не 'public'. Но его надо протестировать.
0
|
||
|
|
|
| 03.06.2025, 21:59 | |
|
Если внутренний класс не виден снаружи, то он так и остается невидимым, даже для тестов. Если его члены/методы вызывают элементы класса-"матки", то ничего страшного..
Добавлено через 3 минуты И вообще, классы внутри классов обычно и делают с тем расчетом, чтобы они были скрыты извне. Это абсолютно нормальный сценарий.
1
|
|
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
||||||
| 03.06.2025, 22:17 [ТС] | ||||||
|
wizard41,
Тогда опять всё запуталось ). Вот есть у меня библиотека. И в ней очень много сложной внутренней логики, размещённой в классах, которые за пределами сборки не видны (ибо они и не должны быть видны наружу). И весь внешний контрат этой библиотеки сводится к:
Получается, надо писать тесты исключительно на уровне этого метода 'Apply', прогоняя через него сотни сложных вариаций входных данных и тестируя результаты работы через парсинг базы данных, указанной в 'conn'? Судя по статьям, есть два холиварных подхода: 1. Тестируем только внешний контракт мега-запутанными комплексными тестами. В этом случае тесты усложняются и в разработке, и в поддержке. Но не надо лезть внутрь сборки. 2. Покрываем тестами вообще все детали внутренней реализации. В этом случае получаем огромное количество простых тестов, но для реализации такого подхода приходится немного поступаться инкапсуляцией.
0
|
||||||
|
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
|
|
| 03.06.2025, 22:31 | |
|
0
|
|
|
|
||
| 03.06.2025, 23:06 | ||
|
.delete
Добавлено через 6 минут Если второе, то на мой взгляд это не правильно. То что внутренняя логика скрывается от конечного пользователя, не означает что её нельзя шарить для внутреннего использования. Зачастую скрывают для того чтобы пользователи не путались в россыпи классов и методов, а чётко следовали контракту. ИМХО, для тестов расшарить internal через InternalsVisibleTo вполне нормальное решение.
2
|
||
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
|||||||
| 03.06.2025, 23:12 [ТС] | |||||||
Собственно, я сейчас именно так и расшариваю все детали внутренней реализации для тестов.
0
|
|||||||
|
|
||
| 03.06.2025, 23:30 | ||
|
Wolfdp, эмм, я об общем принципе. Имея в виду уровень подготовки автора вопроса.
Лично я не стал бы манипулировать InternalsVisibleTo перед тем, кто только начинает вникать в тесты. Добавлено через 8 минут Wolfdp, у меня есть класс FooClass и в нем публичный метод Foo, который, в свою очередь, взаимодействует с внутренними полями и скрытыми классами. Вы тестируете метод Foo. Вам не должно быть интересно каким образом он решает поставленную задачу: вам предоставлен только этот класс, экземпляр которого создает тест. Это может быть вообще закрытая библиотека с некорым кол-вом публичных членов - для тестирования ее вам не нужны скрытые реализации.. Добавлено через 4 минуты А если эти реализации создают несколько человек, то они должны быть открыты для тестирования на любой стороне. Прием с InternalsVisibleTo - это прям нечто... Про это знаю, но на практике не видел еще.. Похоже на такое: каждый скрывает от всех свое, но для тестов нате пожалуйста..
1
|
||
|
|
|||||||||||||||||
| 04.06.2025, 00:31 | |||||||||||||||||
|
Грубо говоря либа с внутренним классом (дабы избежать статики, делаем через internal конструктор проброс интерфейса)
2
|
|||||||||||||||||
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
|||||||||||||
| 04.06.2025, 07:32 [ТС] | |||||||||||||
Ну т.е., например, как мне (именно как разработчику библиотеки) протестировать вот этот метод?
0
|
|||||||||||||
|
|
||
| 04.06.2025, 12:18 | ||
|
kotelok, в целом можно сказать, что каждый пишет тесты для самого себя как пожелает. Тут нет каких=то четких правил, т.к. у каждого свой энвиронмент.
Что мешает, например, "вытащить" какой-то внутренний метод временно, протестировать, убедиться что он капец какой правильный и засунуть обратно внутрь чего-то? И больше про него не вспоминать..
1
|
||
|
1341 / 920 / 265
Регистрация: 08.08.2014
Сообщений: 2,775
|
|||
| 04.06.2025, 12:24 [ТС] | |||
|
0
|
|||
|
|
|||
| 04.06.2025, 12:35 | |||
|
Добавлено через 1 минуту И не уверен что Dapper является прям эталоном в тестировании, на который нужно равняться..
0
|
|||
| 04.06.2025, 12:35 | |
|
Unit тест для метода Юнит-тест для асинхронного метода Unit тест для метода Вызов переменной метода A из метода В Вызов метода, ожидающего завершение другого метода Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла:
Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
|
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет
Новости компьютерного мира и их обсуждение (4)
Салют, шампанское, овации!
:drink:
|
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр.
Дословно, отклонённая. . .
|
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы
Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
|
|
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
|
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2.
Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
|
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
|
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
|