Ради эксперимента поставил заметочник affine.pro. Однако у него довольно плохая мобильная версия, поэтому для быстрых записей я захотел написать телеграм-бота. А уже об этом - моя новая статья :)
вАЙТИ
Автоматизируем сервис без API
DIY-медиа для ИТ-специалистов. Практические истории про решение самых разных задач из ИТ и смежных областей.
Behaviour Driven Development && Dotnet
Так получилось, что в рамках своего опыта работы я не встречал проектов с хорошими юнит-тестами и большим покрытием ими проектов.
Зато на всех проектах использовался подход Behaviour Driven Development, в рамках которого писались интеграционные тесты.
Behaviour Driven Development - это подход к разработке, при котором вы пишете интеграционные тесты на основе User Story, используя язык Gherkin как со стороны бизнеса, так и со стороны разработки. Чем-то похоже на ATDD
Каждый тест состоит из трех этапов:
- Given (дано) - подготовка окружения (может быть несколько)
- When (когда) - выполнение действия, которое как-то это окружение меняет (желательно, чтобы этот шаг был только один)
- Then (тогда) - проверка того, что окружение изменилось так как надо (тоже может быть несколько)
Например
- Дано: созданный аккаунт пользователя с ролью администратор
- Когда пользователь авторизуется в системе
- Тогда пользователь видит страницу администратора
Такие тесты более сложны в сопровождении, дольше пишутся и дольше прогоняются, однако имеют очень важное преимущество - они не просто тестируют изолированный кусок логики, как юнит-тесты, а фактически подтверждают выполнение бизнес-требований.
В дотнете есть много популярных фреймворков для написания таких тестов - LightBDD, SpecFlow, MSpec. Однако наиболее популярны первые два - о них и поговорим в следующих постах
Flexible Coding
Так получилось, что в рамках своего опыта работы я не встречал проектов с хорошими юнит-тестами и большим покрытием ими проектов.
Зато на всех проектах использовался подход Behaviour Driven Development, в рамках которого писались интеграционные тесты.
Behaviour Driven Development - это подход к разработке, при котором вы пишете интеграционные тесты на основе User Story, используя язык Gherkin как со стороны бизнеса, так и со стороны разработки. Чем-то похоже на ATDD
Каждый тест состоит из трех этапов:
- Given (дано) - подготовка окружения (может быть несколько)
- When (когда) - выполнение действия, которое как-то это окружение меняет (желательно, чтобы этот шаг был только один)
- Then (тогда) - проверка того, что окружение изменилось так как надо (тоже может быть несколько)
Например
- Дано: созданный аккаунт пользователя с ролью администратор
- Когда пользователь авторизуется в системе
- Тогда пользователь видит страницу администратора
Такие тесты более сложны в сопровождении, дольше пишутся и дольше прогоняются, однако имеют очень важное преимущество - они не просто тестируют изолированный кусок логики, как юнит-тесты, а фактически подтверждают выполнение бизнес-требований.
В дотнете есть много популярных фреймворков для написания таких тестов - LightBDD, SpecFlow, MSpec. Однако наиболее популярны первые два - о них и поговорим в следующих постах
Flexible Coding
SLNX-формат или как Microsoft меня расстроили
Всем привет! Сегодня поговорим про "решения" проектов на .NET.
Как мы знаем, приложение на дотнете - это некоторое решение (Solution) с набором проектов. В одном из проектов может быть слой бизнес-логики, в другом - инфраструктурный, ну и так далее. Всё это может быть и в одном проекте, но это редкость.
Так вот, проекты объединяются в решение через sln-файлы - файлы решений. Внутри этого файла находится страшный сплошной текст с информацией о проектах, их расположением в Solution Folders и прочими метаданными. И его довольно трудно читать - там довольно странные GUID-ы, куча каких-то маппингов, повторов...
А проблемы начинаются, когда разработчики параллельно в разных ветках добавляют много проектов, а потом надо решать merge-конфликты. И после очередного разбора конфликтов на работе, итогом которого стала отвязка части проектов и ручная их перепривязка к решению, стало понятно, что так дальше продолжаться не может.
В .NET8 был представлен новый формат файлов решений - slnx. Данные в нём уже структурированы и довольно удобно читаются - xml-формат, там нет GUID-ов и прочего мусора, который мешает пониманию содержимого файла - то, что надо!
И вот мы уже перешли на новый формат решений, счастливы - конфликты в этом файле решаются просто, коллизий нет... и тут выясняется, что dotnet cli этот формат полностью не поддерживает. То есть dotnet restore, dotnet build в нашем dockerfile тупо не отрабатывает и мы не можем задеплоиться!
Собственно, благодаря тому, что xml удобно парсить, не составило труда написать скрипт, который парсит список проектов в решении и выполняет dotnet restore для них по отдельности, но это не так удобно. Вместо
> Да, я написал F#-скрипт для парсинга slnx-файла
А ещё забавно, что даже последняя версия Visual Studio 2022 отказалась открывать этот файл :)
Какой же статус работы по slnx?
- Для dotnet cli - выйдет в .net9.0.2
- Для vs code - есть открытый issue
- Для Visual Studio - да вроде уже работает, но у меня не работает :(
- И только JetBrains Rider стабильно открывает и понимает новый формат солюшнов
Морали не будет, просто будьте внимательнее при переходе на что-то новое и крутое :)
Flexible Coding
Всем привет! Сегодня поговорим про "решения" проектов на .NET.
Как мы знаем, приложение на дотнете - это некоторое решение (Solution) с набором проектов. В одном из проектов может быть слой бизнес-логики, в другом - инфраструктурный, ну и так далее. Всё это может быть и в одном проекте, но это редкость.
Так вот, проекты объединяются в решение через sln-файлы - файлы решений. Внутри этого файла находится страшный сплошной текст с информацией о проектах, их расположением в Solution Folders и прочими метаданными. И его довольно трудно читать - там довольно странные GUID-ы, куча каких-то маппингов, повторов...
А проблемы начинаются, когда разработчики параллельно в разных ветках добавляют много проектов, а потом надо решать merge-конфликты. И после очередного разбора конфликтов на работе, итогом которого стала отвязка части проектов и ручная их перепривязка к решению, стало понятно, что так дальше продолжаться не может.
В .NET8 был представлен новый формат файлов решений - slnx. Данные в нём уже структурированы и довольно удобно читаются - xml-формат, там нет GUID-ов и прочего мусора, который мешает пониманию содержимого файла - то, что надо!
И вот мы уже перешли на новый формат решений, счастливы - конфликты в этом файле решаются просто, коллизий нет... и тут выясняется, что dotnet cli этот формат полностью не поддерживает. То есть dotnet restore, dotnet build в нашем dockerfile тупо не отрабатывает и мы не можем задеплоиться!
Собственно, благодаря тому, что xml удобно парсить, не составило труда написать скрипт, который парсит список проектов в решении и выполняет dotnet restore для них по отдельности, но это не так удобно. Вместо
dotnet restore
мы выполнеяем команду
dotnet fsi list-projects.fsx | sed 's|\\|/|g' | xargs -I {} sh -c 'if [ -f "{}" ]; then dotnet restore "{}"; fi'
> Да, я написал F#-скрипт для парсинга slnx-файла
А ещё забавно, что даже последняя версия Visual Studio 2022 отказалась открывать этот файл :)
Какой же статус работы по slnx?
- Для dotnet cli - выйдет в .net9.0.2
- Для vs code - есть открытый issue
- Для Visual Studio - да вроде уже работает, но у меня не работает :(
- И только JetBrains Rider стабильно открывает и понимает новый формат солюшнов
Морали не будет, просто будьте внимательнее при переходе на что-то новое и крутое :)
Flexible Coding
Итак, 2025 год (с наступившим!), автор вышел из цепочки событий разной степени безумия и готов с вами познакомиться!
Меня зовут Дмитрий Бахтенков, уже несколько лет я занимаюсь коммерческой разработкой на .NET, а также увлекаюсь различными аспектами саморазвития - очень много времени уделяю тому, как быть продуктивным, организованным, эффективным и т.д.
Этот канал я создал, чтобы делиться с вами своими мыслями, идеями и личным опытом, непосредственно связанным с программированием и IT в целом.
Что здесь есть?
- Статьи. Последнее время я публикую их на портале вАЙТИ
- Обзоры книг. Я много читаю, в том числе техническую литературу. Об интересных книгах я пишу отзывы, и думаю о том, чтобы делать более развёрнутые конспекты
- Интересные технические кейсы. Что-то непонятное, занятное и странное
- Обучающие посты
- Личный опыт, публичные выступления, советы по организации и многое другое
А ещё я завёл бусти. Он пока пустой, но в ближайшее время я буду его наполнять по чуть чуть. Подписывайтесь, если хотите меня поддержать, я буду рад!
Меня зовут Дмитрий Бахтенков, уже несколько лет я занимаюсь коммерческой разработкой на .NET, а также увлекаюсь различными аспектами саморазвития - очень много времени уделяю тому, как быть продуктивным, организованным, эффективным и т.д.
Этот канал я создал, чтобы делиться с вами своими мыслями, идеями и личным опытом, непосредственно связанным с программированием и IT в целом.
Что здесь есть?
- Статьи. Последнее время я публикую их на портале вАЙТИ
- Обзоры книг. Я много читаю, в том числе техническую литературу. Об интересных книгах я пишу отзывы, и думаю о том, чтобы делать более развёрнутые конспекты
- Интересные технические кейсы. Что-то непонятное, занятное и странное
- Обучающие посты
- Личный опыт, публичные выступления, советы по организации и многое другое
А ещё я завёл бусти. Он пока пустой, но в ближайшее время я буду его наполнять по чуть чуть. Подписывайтесь, если хотите меня поддержать, я буду рад!
Всем привет!
Начал писать цикл статей про многопоточность на разных уровнях абстракции. И представляю вам первую статью из этой серии - про процессор!
Начал писать цикл статей про многопоточность на разных уровнях абстракции. И представляю вам первую статью из этой серии - про процессор!
вАЙТИ
Многопоточность. Снизу вверх. Процессор
DIY-медиа для ИТ-специалистов. Практические истории про решение самых разных задач из ИТ и смежных областей.
Интеграционное тестирование MongoDB. Точки отказа
Всем привет! Сегодня рассмотрим тему настроек MongoDB для интгерационного тестирования и узнаем, что такое FailPoint и как он может помочь проверить нашу логику в нестандартных ситуациях.
Часто нам приходится писать интеграционные тесты. Интеграционные тесты — это тесты, которые проверяют взаимодействие нашего кода с внешними системами (БД, внешние API и т. д.) в как можно более приближённых к реальности условиях.
Зачем нужны такие тесты? Ну, например, чтобы убедиться, что наша логика корректно обрабатывает ситуации, когда база данных возвращает ошибку создания индекса или отказывает в записи. Юнит-тесты здесь уже не справятся, ведь они не покрывают фактическое взаимодействие с “живой” MongoDB.
Test Commands в MongoDB
MongoDB поддерживает набор специальных команд для тестирования (testCommands), которые обычно отключены в продакшене. Среди них есть конфигурация FailPoint — «точка отказа», позволяющая искусственно вызывать сбои и ошибки в различных операциях.
Чтобы включить testCommands, достаточно при запуске MongoDB задать параметр enableTestCommands=1. Вот пример docker-compose для этой задачи:
Для запуска команд нужно выбрать базу данных (для
Определение
1.
2.
3.
Пример использования для команды
А когда тесты будут завершены, точку отказа можно отключить:
В следующем посте мы рассмотрим пример интеграционного теста, который использует данную функциональность, а пока что можете погрузиться в вики-страничку про данный механизм.
Всем спасибо, с вами был Flexible Coding!
Всем привет! Сегодня рассмотрим тему настроек MongoDB для интгерационного тестирования и узнаем, что такое FailPoint и как он может помочь проверить нашу логику в нестандартных ситуациях.
Часто нам приходится писать интеграционные тесты. Интеграционные тесты — это тесты, которые проверяют взаимодействие нашего кода с внешними системами (БД, внешние API и т. д.) в как можно более приближённых к реальности условиях.
Зачем нужны такие тесты? Ну, например, чтобы убедиться, что наша логика корректно обрабатывает ситуации, когда база данных возвращает ошибку создания индекса или отказывает в записи. Юнит-тесты здесь уже не справятся, ведь они не покрывают фактическое взаимодействие с “живой” MongoDB.
Test Commands в MongoDB
MongoDB поддерживает набор специальных команд для тестирования (testCommands), которые обычно отключены в продакшене. Среди них есть конфигурация FailPoint — «точка отказа», позволяющая искусственно вызывать сбои и ошибки в различных операциях.
Чтобы включить testCommands, достаточно при запуске MongoDB задать параметр enableTestCommands=1. Вот пример docker-compose для этой задачи:
services:
mongo:
image: mongo:6.0
command: mongod --setParameter enableTestCommands=1
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
Для запуска команд нужно выбрать базу данных (для
ConfigureFailPoint
это база данных admin) и вызвать метод db.runCommand({})
.Определение
ConfigureFailPoint
состоит из следующих полей:1.
configureFailPoint
- название точки отказа, которую мы настраиваем. Чаще всего встречается значение failCommand
для настройки отказа конкретной команды2.
mode
: определяет режим срабатывания точки отказа: alwaysOn
, off
, {times: n}
и другие3.
data
- является вложенным объектом, в котором указываются детали и условия сбояПример использования для команды
createIndexes
:
use admin;
db.runCommand({
configureFailPoint: "failCommand",
mode: { times: 1 },
data: {
failCommands: ["createIndexes"],
errorCode: 100,
closeConnection: false
}
});
А когда тесты будут завершены, точку отказа можно отключить:
use admin;
db.runCommand({
configureFailPoint: "failCommand",
mode: "off"
});
В следующем посте мы рассмотрим пример интеграционного теста, который использует данную функциональность, а пока что можете погрузиться в вики-страничку про данный механизм.
Всем спасибо, с вами был Flexible Coding!
Flexible Coding
Всем привет! Начал писать цикл статей про многопоточность на разных уровнях абстракции. И представляю вам первую статью из этой серии - про процессор!
Тем временем готова следующая статья из цикла про многопоточность - сегодня залезем на уровень операционной системы
вАЙТИ
Многопоточность. Снизу вверх. ОС
DIY-медиа для ИТ-специалистов. Практические истории про решение самых разных задач из ИТ и смежных областей.
Интеграционное тестирование MongoDB. Точки отказа. .NET
Всем привет! Продолжаем тему точек отказа у MongoDb. С основами разобрались, а теперь приступим к написанию тестов на .NET.
Тесты разделяются на три этапа: Given (Arrange), When (Act) и Then (Assert). Так же в рамках теста может происходит подготовка окружения -
В рамках конкретного теста точку отказа удобнее всего настраивать на этапе Setup. В NUnit это будет выглядеть следующим образом:
Далее - сама логика теста:
А затем возвращаем MongoDB в исходное состояние:
Таким образом можно настраивать необходимое поведение БД в рамках теста.
Flexible Coding
Всем привет! Продолжаем тему точек отказа у MongoDb. С основами разобрались, а теперь приступим к написанию тестов на .NET.
Тесты разделяются на три этапа: Given (Arrange), When (Act) и Then (Assert). Так же в рамках теста может происходит подготовка окружения -
Setup
и очистка - TearDown
.В рамках конкретного теста точку отказа удобнее всего настраивать на этапе Setup. В NUnit это будет выглядеть следующим образом:
[SetUp]
public void Setup()
{
// Подключаемся к локальной монге, где включены testCommands
var client = new MongoClient("mongodb://root:password@localhost:27017");
_database = client.GetDatabase("testDb");
_collection = _database.GetCollection<BsonDocument>("testCollection");
_adminDatabase = client.GetDatabase("admin");
// Включаем FailPoint для команды createIndexes
var enableFailPoint = new BsonDocument
{
{ "configureFailPoint", "failCommand" },
{ "mode", new BsonDocument("times", 1) },
{
"data", new BsonDocument
{
{ "failCommands", new BsonArray { "createIndexes" } },
{ "errorCode", 100 }, // код ошибки (для проверки)
{ "closeConnection", false } // соединение не рвём
}
}
};
_adminDatabase.RunCommand<BsonDocument>(enableFailPoint);
}
Далее - сама логика теста:
[Test]
public void CreateIndexes_ShouldThrowException_WhenFailPointEnabled()
{
var ex = Assert.Throws<MongoCommandException>(() =>
{
_collection.Indexes.CreateOne(
new CreateIndexModel<BsonDocument>(
Builders<BsonDocument>.IndexKeys.Ascending("someField")));
});
Assert.That(ex.Code, Is.EqualTo(100));
}
А затем возвращаем MongoDB в исходное состояние:
[TearDown]
public void TearDown()
{
// Выключаем FailPoint, чтобы вернуть MongoDb в исходное состояние
var disableFailPoint = new BsonDocument
{
{ "configureFailPoint", "failCommand" },
{ "mode", "off" }
};
_adminDatabase.RunCommand<BsonDocument>(disableFailPoint);
}
Таким образом можно настраивать необходимое поведение БД в рамках теста.
Flexible Coding
Flexible Coding
Тем временем готова следующая статья из цикла про многопоточность - сегодня залезем на уровень операционной системы
Слегка прошёлся по Thread в дотнете в новой статье из цикла про многопоточность. Приятного чтения!
Flexible Coding
Flexible Coding
вАЙТИ
Многопоточность. Снизу вверх. Потоки в языке C#
DIY-медиа для ИТ-специалистов. Практические истории про решение самых разных задач из ИТ и смежных областей.
Flexible Coding
Слегка прошёлся по Thread в дотнете в новой статье из цикла про многопоточность. Приятного чтения! Flexible Coding
Перебираемся ещё на уровень выше в теме многопоточности - в новой статье затронем пул потоков и асинхронность
Flexible Coding
Flexible Coding
вАЙТИ
Многопоточность. Снизу вверх. Асинхронность и пул потоков
DIY-медиа для ИТ-специалистов. Практические истории про решение самых разных задач из ИТ и смежных областей.
var functions = new List<Func<int, int>>();
for (int i = 0; i < 10; i++)
{
Func<int, int> function = x => i * x;
if (!functions.Contains(function))
{
functions.Add(function);
}
}
Console.WriteLine(functions.Count);