Pull to refresh

Comments 24

Так и как же всё-таки сделать Unit-тестирование в .NET проще и интереснее?

Для нас так стало проще и интереснее, и веселее :)

В отдельной статье поделимся тем, как именно пишем тесты на бекенды, напсанные на .NET, на каких слоях пирамиды тестирования, используя какие инструменты и подходы.

Здесь хотели поделиться идеей, её плюсами и техническими деталями реализации.

Если слегка запарится с именем и сделать имя файлов тестов типо такого:

Для Func.cs

Тест - Func.cs.test.cs

То в среде разработки он будет отображаться как вложенный в Func.cs, более явная принадлежность

Это также работает например с razor

File.razor

File.razor.cs (отображается как вложенный)

Классный совет! Спасибо, мы попробуем :) 12 лет назад пользовались Razor и Web.config со всеми их скрытыми вложенностями, что-то не подумали, что такая фича всё ещё должна быть и прикольно работать.

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

Будем пробовать и смотреть, как пошло.

Можно сделать проще, просто добавить в csproj условие для сопоставления файлов

<ItemGroup>
	<Compile Update="**\*Tests.cs">
		<DependentUpon>$([System.String]::Copy(%(Filename)).Replace('Tests', '.cs'))</DependentUpon>
	</Compile>
</ItemGroup>

Но мы решили пойти дальше и обнаружили интересную фичу, которая скрывается в файле проекта .csproj. И это параметр Condition

Если у вас такие глубокие познания в MSBuild, что этот "параметр" для вас стал открытием, то, может вам сначала немного подучиться, там, типа, опыта поднабраться, перед тем какие-то свои уникальные подходы к project layout изобретать?

Вот странная претензия. Типа пока MSBuild не знаешь, то project layout не трогай?

А когда тогда можно трогать?

А когда тогда можно трогать?

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

А у нас достаточно опыта в .NET и насмотренности в других стеках, таких как Python, NodeJS, C/C++. Один из авторов, который вам сейчас пишет - Александр, начинал профессиональную карьеру на C# 13 лет назад, читал Рихтера, Фаулера, Мартина и т.д., делал проекты, ездил учиться на конференции DotNext, а сейчас и сам делится знаниями и видением.

Ещё ребята в Go так делают: https://go.dev/doc/tutorial/add-a-test и вот ещё интересное обсуждение такого подхода, https://www.reddit.com/r/golang/comments/157tsdj/where_do_you_place_your_tests_in_your_project/?rdt=51749.

Если что, мы ещё и не верим в автомаппер и медиатор в .NET проектах =ъ

Пыс: не очень понятно откуда и зачем такой негатив

читал Рихтера, Фаулера, Мартина и т.д., делал проекты

Я этим так впечатлён, что аж дыхание спёрло :)))

не очень понятно откуда и зачем такой негатив

А, вы знаете, а, ведь, на самом деле, абсолютно похер. Я работу работаю исключительно из-за денег, платят мне, фактически, за жопочасы, и потрачу я свой рабочий день на что-то полезное или же на то чтобы разбираться в чьих-то красноглазых галлюцинациях типа самодельного супералгоритма сортировки с использованием эрмитовых матриц и групп Ли - мне от этого ни
холодно, ни жарко, за свои Х часов я ровно те же деньги все равно получу. Поэтому, просто, удачи вам - ступайте с Богом в мир, делитесь дальше своими знаниями и видЕниями. :)

Настолько похер, что невозможно молчать :)

Интересный подход, но как по мне выглядит некрасиво. Мы у себя начали писать больше интеграционных тестов - они на самом деле покрывают бизнес логику так, как её видит бизнес, и дают хороший coverage. Unit тесты оставили только для каких-то часто используемых примитивов, типа своих observable collections или чего-то многопоточного, где на самом деле есть неочевидные граничные условия, которые необходимо покрывать. Вот после этого стало проще и интереснее.

Согласны про больше интеграционных. Мы тут под Unit подразумеваем не всегда самую маленькую и ни от чего независящую единицу. Мы сейчас тоже перешли к большему количеству интеграционных тестов + минимум E2E-тестов самого API, которые заменяют каноничные Unit-тесты..

Но ведь интеграционные тесты, пусть и покрывающие все кейсы, не гарантируют детерминированности, в отличии от юнитовых.

Тут есть нюансы. Во-первых, детерминированность чего? Во-вторых, ну замокаю я сервисы вью модели, проверю, что по нажатию кнопки что-то где-то вызвалось. Что на самом деле мне даёт такой тест? У нас в команде не идиоты работают, + qa, так что, вероятность того, что кто-то уберёт этот вызов по нажатию кнопки, крайне мала. Опять же, интеграционные тесты не пройдут после такого, так что qa даже билд не получит с такой проблемой. Зато, после рефакторинга, придётся ещё и этот бесполезный тест менять.

Во-первых, детерминированность чего?

Детерминированность тестов. Ты один раз endpoint дернул - будет хороший результат, второй раз дёрнул - случилась внутренния ошибка чтения из серверного кеша. Но второй-пятый-десятый раз мало кто дергает.

Юнитовый тест проверяет более мелкие кусочки, и такие вещи как чтение из кеша будет одним из обязательных шагов.

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

Ну вот. А если всё хорошенько покрыть юнитами, то интеграционные уже особо ничего не порешают. Уже нужен будут более верхние по пирамиде. ^^

Допустим, строим дом. Протестили все кирпичи, раствор, проводку, сантехнику и тд. Заходим смотреть - открыли дверь - крыша упала. Как же так, ведь все протестировано.

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

Я не против юнит тестов. Моё мнение такое, что всё подряд ими покрывать не только бесполезно, но ещё и вредно. Какие-то конкретные важные базовые компоненты - пожалуйста. Бизнес логику - не думаю. Юнит тест проверяет, что логика компонента работает так, как написано в юнит тесте, не больше, не меньше. Когда логика компонента часто меняется (рефакторинг вью моделей, например) - юнит тест придётся так же часто менять.

Именно бизнес-логику и надо тестировать. Уточню лишь, что "бизнес" подразумевается в контексте кода/приложения, а не заказчика.

А в случае с упавшей крышей это как раз и есть UI тест. Интеграционных, при хороших, правильных юнитах (а не "все подряд"), почти не требуется.

У меня такое чувство, что мы говорим о разных вещах. Взять те же UI тесты. По-хорошему, слой логики UI (view model) существует отдельно от самого UI (view) - т е лёгким движением руки мы можем вместо WPF натянуть ASP.NET MVC или консоль, и так далее. Соответственно, то, что будет происходить при нажатии кнопок и так далее - легко тестируется без самого UI (если грамотно подойти к архитектуре), интеграционными тестами. Главное, отрезать в правильных местах. А UI тесты - это уже про appearance, типа кнопки метки в правильных местах правильного цвета, сообщения об ошибках и тд. В любом случае, если ваш подход работает для вас - не смею вас переубеждать.

Также пишу тесты. Два года назад попробовал в го и сделал в дотнете github.com/colotiline/go-like-tests-in-csharp .

Sign up to leave a comment.

Articles