This commit is contained in:
@@ -0,0 +1,84 @@
|
|||||||
|
using ChatBot.Services.Telegram.Services;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Moq;
|
||||||
|
using Telegram.Bot;
|
||||||
|
|
||||||
|
namespace ChatBot.Tests.Services.Telegram;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Базовые тесты для TelegramBotService
|
||||||
|
/// Полное тестирование затруднено из-за extension методов Telegram.Bot
|
||||||
|
/// </summary>
|
||||||
|
public class TelegramBotServiceBasicTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_ShouldCreateInstance()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var loggerMock = new Mock<ILogger<TelegramBotService>>();
|
||||||
|
var botClientMock = new Mock<ITelegramBotClient>();
|
||||||
|
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var service = new TelegramBotService(
|
||||||
|
loggerMock.Object,
|
||||||
|
botClientMock.Object,
|
||||||
|
serviceProviderMock.Object
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
service.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task StopAsync_ShouldComplete()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var loggerMock = new Mock<ILogger<TelegramBotService>>();
|
||||||
|
var botClientMock = new Mock<ITelegramBotClient>();
|
||||||
|
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||||
|
|
||||||
|
var service = new TelegramBotService(
|
||||||
|
loggerMock.Object,
|
||||||
|
botClientMock.Object,
|
||||||
|
serviceProviderMock.Object
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var act = async () => await service.StopAsync(CancellationToken.None);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await act.Should().NotThrowAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task StopAsync_ShouldLog()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var loggerMock = new Mock<ILogger<TelegramBotService>>();
|
||||||
|
var botClientMock = new Mock<ITelegramBotClient>();
|
||||||
|
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||||
|
|
||||||
|
var service = new TelegramBotService(
|
||||||
|
loggerMock.Object,
|
||||||
|
botClientMock.Object,
|
||||||
|
serviceProviderMock.Object
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await service.StopAsync(CancellationToken.None);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
loggerMock.Verify(
|
||||||
|
x => x.Log(
|
||||||
|
LogLevel.Information,
|
||||||
|
It.IsAny<EventId>(),
|
||||||
|
It.Is<It.IsAnyType>((v, t) => v.ToString()!.Contains("Stopping Telegram bot service")),
|
||||||
|
It.IsAny<Exception>(),
|
||||||
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||||
|
),
|
||||||
|
Times.Once
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
154
SonarQube_70percent_Analysis.md
Normal file
154
SonarQube_70percent_Analysis.md
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
# Анализ: почему покрытие 70%, а не 86%?
|
||||||
|
|
||||||
|
## 🔍 Разница между локальным и SonarQube coverage
|
||||||
|
|
||||||
|
**Локально (coverlet)**: 86.59%
|
||||||
|
**SonarQube**: 70%
|
||||||
|
**Разница**: ~16%
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤔 Возможные причины
|
||||||
|
|
||||||
|
### 1. **"Coverage on New Code" vs "Overall Coverage"**
|
||||||
|
|
||||||
|
SonarQube разделяет:
|
||||||
|
- **Overall Coverage** - покрытие всего проекта
|
||||||
|
- **Coverage on New Code** - покрытие только изменений в текущей ветке
|
||||||
|
|
||||||
|
Вы смотрите на **Coverage on New Code** (70%), который:
|
||||||
|
- Считается только для файлов, измененных после определенной даты
|
||||||
|
- Не учитывает старый хорошо покрытый код
|
||||||
|
- Включает ВСЕ новые изменения (в том числе миграции, если они были изменены)
|
||||||
|
|
||||||
|
### 2. **SonarQube может по-другому считать исключения**
|
||||||
|
|
||||||
|
Даже с правильными настройками, SonarQube может:
|
||||||
|
- Не полностью применить exclusions к "New Code"
|
||||||
|
- Считать строки по-другому (комментарии, пустые строки)
|
||||||
|
- Учитывать partial classes иначе
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Решения
|
||||||
|
|
||||||
|
### Вариант 1: Проверить "Overall Coverage" в SonarQube
|
||||||
|
|
||||||
|
Откройте SonarQube dashboard и найдите:
|
||||||
|
- **Overall Coverage** (должно быть ~86%)
|
||||||
|
- **Coverage on New Code** (сейчас 70%)
|
||||||
|
|
||||||
|
Если **Overall Coverage** ~86%, то все в порядке! Просто нужно:
|
||||||
|
1. Дождаться merge в master
|
||||||
|
2. Или добавить больше тестов для нового кода
|
||||||
|
|
||||||
|
### Вариант 2: Сбросить "New Code Period"
|
||||||
|
|
||||||
|
В SonarQube можно изменить период "New Code":
|
||||||
|
1. Зайти в Project Settings → New Code
|
||||||
|
2. Изменить на "Previous version" или "Number of days"
|
||||||
|
3. Переанализировать проект
|
||||||
|
|
||||||
|
### Вариант 3: Добавить больше тестов для конкретных файлов
|
||||||
|
|
||||||
|
Давайте найдем, какие ИМЕННО файлы SonarQube считает недопокрытыми.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Действия прямо сейчас
|
||||||
|
|
||||||
|
### Шаг 1: Проверьте SonarQube dashboard
|
||||||
|
|
||||||
|
Найдите страницу "Coverage" в SonarQube и ответьте на вопросы:
|
||||||
|
|
||||||
|
1. **Какое "Overall Coverage"?** (не "New Code Coverage")
|
||||||
|
2. **Какие файлы показаны как недопокрытые?**
|
||||||
|
3. **Какой период установлен для "New Code"?**
|
||||||
|
|
||||||
|
### Шаг 2: Если нужно добавить тесты
|
||||||
|
|
||||||
|
Я могу создать дополнительные тесты для:
|
||||||
|
|
||||||
|
#### Сервисы без тестов:
|
||||||
|
- ❌ `TelegramBotService` - нет тестов (инфраструктурный код)
|
||||||
|
|
||||||
|
#### Сервисы с неполным покрытием (возможно):
|
||||||
|
- ⚠️ `ModelService` - может быть не все пути покрыты
|
||||||
|
- ⚠️ `ChatService` - могут быть непокрытые edge cases
|
||||||
|
- ⚠️ `AIService` - могут быть непокрытые exception paths
|
||||||
|
|
||||||
|
#### Команды с возможно неполным покрытием:
|
||||||
|
- ⚠️ `SettingsCommand` - могут быть edge cases
|
||||||
|
- ⚠️ `ClearCommand` - могут быть exception paths
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Рекомендации
|
||||||
|
|
||||||
|
### Если Overall Coverage ~86%:
|
||||||
|
|
||||||
|
**Ваш код отлично покрыт!** Проблема только в "New Code Coverage".
|
||||||
|
|
||||||
|
**Решение**:
|
||||||
|
1. Просто commit и push
|
||||||
|
2. После merge в master "New Code Coverage" станет "Overall Coverage"
|
||||||
|
3. Или добавьте comment в SonarQube, объясняющий ситуацию
|
||||||
|
|
||||||
|
### Если Overall Coverage тоже ~70%:
|
||||||
|
|
||||||
|
Тогда проблема в том, что SonarQube не применяет исключения корректно.
|
||||||
|
|
||||||
|
**Решение**:
|
||||||
|
1. Проверить логи SonarQube scanner в CI/CD
|
||||||
|
2. Убедиться, что `.opencover.xml` файл создается правильно
|
||||||
|
3. Возможно добавить `.globalconfig` для Roslyn analyzers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Ожидаемая метрика после исправления
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ Overall Coverage: 86.59%
|
||||||
|
⚠️ Coverage on New Code: 70-86% (зависит от периода)
|
||||||
|
✅ Quality Gate: SHOULD PASS (если смотрим на Overall)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Что делать СЕЙЧАС
|
||||||
|
|
||||||
|
### 1. Проверьте SonarQube
|
||||||
|
Откройте SonarQube и найдите:
|
||||||
|
- Overall Coverage (главная метрика)
|
||||||
|
- Список непокрытых файлов
|
||||||
|
- New Code Period настройки
|
||||||
|
|
||||||
|
### 2. Если Overall Coverage ~86%:
|
||||||
|
✅ **Все отлично! Push код как есть.**
|
||||||
|
|
||||||
|
### 3. Если Overall Coverage ~70%:
|
||||||
|
Скажите мне, какие КОНКРЕТНЫЕ файлы SonarQube показывает как недопокрытые, и я создам для них тесты.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Дополнительная информация
|
||||||
|
|
||||||
|
### Как увидеть Overall Coverage в SonarQube:
|
||||||
|
|
||||||
|
1. Откройте ваш проект в SonarQube
|
||||||
|
2. На главной странице проекта найдите блок "Coverage"
|
||||||
|
3. Там должны быть ДВЕ цифры:
|
||||||
|
- **Coverage** (Overall) - главная метрика
|
||||||
|
- **Coverage on New Code** - только новые изменения
|
||||||
|
|
||||||
|
### Как изменить New Code Period:
|
||||||
|
|
||||||
|
1. Project Settings → New Code
|
||||||
|
2. Выберите один из вариантов:
|
||||||
|
- **Previous version** (рекомендуется)
|
||||||
|
- **Number of days** (например, последние 30 дней)
|
||||||
|
- **Specific analysis** (конкретная дата)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Сообщите мне, какую цифру Overall Coverage вы видите в SonarQube, и я помогу дальше!**
|
||||||
Reference in New Issue
Block a user