This commit is contained in:
226
UncoveredCode_Analysis.md
Normal file
226
UncoveredCode_Analysis.md
Normal file
@@ -0,0 +1,226 @@
|
||||
# Анализ непокрытого кода (36% от общего)
|
||||
|
||||
## Категории непокрытого кода
|
||||
|
||||
### 1. Exception Handlers (основная причина) - ~15%
|
||||
|
||||
#### Program.cs
|
||||
**Строки 174-177**: Глобальный Fatal exception handler
|
||||
```csharp
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.ForContext<Program>().Fatal(ex, "Application terminated unexpectedly");
|
||||
}
|
||||
```
|
||||
**Проблема**: Тяжело симулировать Fatal exception при запуске
|
||||
|
||||
#### DatabaseInitializationService.cs
|
||||
**Строки 50-64**: Два exception блока
|
||||
1. `catch when (ex.Message.Contains("database does not exist"))` - специфичный сценарий
|
||||
2. `catch (Exception ex)` - общая ошибка инициализации
|
||||
|
||||
#### HistoryCompressionService.cs (3 блока)
|
||||
- **Строка 99**: Fallback при ошибке сжатия
|
||||
- **Строка 282**: Ошибка суммаризации
|
||||
- **Строка 315**: Generic exception handling с retry логикой
|
||||
|
||||
#### DatabaseSessionStorage.cs (5 блоков!)
|
||||
**Строки 44, 61, 74, 87, 100, 145** - все методы имеют try-catch, но тесты могут не покрывать exception paths
|
||||
|
||||
#### Telegram Services
|
||||
- **TelegramMessageSender**: retry логика (строка 58)
|
||||
- **TelegramBotService**: GetMe fallback (строка 80)
|
||||
- **BotInfoService**: Stale cache fallback (строка 65)
|
||||
- **TelegramMessageHandler**: Error logging (строка 100)
|
||||
- **TelegramCommandProcessor**: Message processing errors (строка 124)
|
||||
|
||||
#### Health Checks
|
||||
- **OllamaHealthCheck** (строка 63)
|
||||
- **TelegramBotHealthCheck** (строка 64)
|
||||
|
||||
**Рекомендация**: Добавить тесты, которые намеренно вызывают exceptions:
|
||||
```csharp
|
||||
[Fact]
|
||||
public async Task GetBotInfoAsync_WhenApiThrowsException_ShouldReturnStaleCacheIfAvailable()
|
||||
{
|
||||
// Mock API to throw exception after successful first call
|
||||
// Verify stale cache is returned (lines 69-79)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Миграции и автогенерация - ~10%
|
||||
|
||||
**Файлы**:
|
||||
- `Migrations/20251016214154_InitialCreate.cs` (137 строк)
|
||||
- `Migrations/20251016214154_InitialCreate.Designer.cs` (88 строк)
|
||||
- `Migrations/ChatBotDbContextModelSnapshot.cs` (~100 строк)
|
||||
|
||||
**Решение**: Исключить из coverage
|
||||
```xml
|
||||
<!-- В ChatBot.csproj -->
|
||||
<PropertyGroup>
|
||||
<ExcludeFromCodeCoverage>Migrations/**/*.cs</ExcludeFromCodeCoverage>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
Или через атрибут:
|
||||
```csharp
|
||||
[ExcludeFromCodeCoverage]
|
||||
public partial class InitialCreate : Migration
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. Program.cs - конфигурация и DI - ~8%
|
||||
|
||||
**Непокрытые строки**:
|
||||
- **18-19**: `Env.Load()` - выполняется на file-level
|
||||
- **27**: `Log.Logger = new LoggerConfiguration()...` - Serilog setup
|
||||
- **54-77**: Environment variable overrides (частично покрыты)
|
||||
- **164-172**: Host building и запуск
|
||||
- **178-180**: `finally { await Log.CloseAndFlushAsync(); }`
|
||||
|
||||
**Проблема**: Интеграционные тесты покрывают только часть логики
|
||||
|
||||
---
|
||||
|
||||
### 4. Редкие ветки и edge cases - ~5%
|
||||
|
||||
#### Async semaphore race conditions
|
||||
**BotInfoService.cs строки 42-49**: Double-check locking
|
||||
```csharp
|
||||
// Double-check после получения блокировки
|
||||
if (_cachedBotInfo != null && _cacheExpirationTime.HasValue && DateTime.UtcNow < _cacheExpirationTime.Value)
|
||||
{
|
||||
return _cachedBotInfo;
|
||||
}
|
||||
```
|
||||
|
||||
#### Retry логика
|
||||
**HistoryCompressionService строки 312-318**: Nested exception handling
|
||||
```csharp
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
await HandleHttpExceptionAsync(attempt, maxRetries, ex, cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (HandleGenericExceptionAsync(attempt, maxRetries, ex))
|
||||
return string.Empty;
|
||||
}
|
||||
```
|
||||
|
||||
#### Validators edge cases
|
||||
**Валидаторы** в `Models/Configuration/Validators/` - некоторые проверки могут не покрываться:
|
||||
- Null references
|
||||
- Extremely long strings
|
||||
- Invalid URL formats
|
||||
|
||||
---
|
||||
|
||||
### 5. Fallback логика - ~3%
|
||||
|
||||
**SystemPromptService.cs строки 60-71**: Fallback to default prompt
|
||||
```csharp
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error loading system prompt, using default");
|
||||
return _cachedPrompt = "You are a helpful assistant.";
|
||||
}
|
||||
```
|
||||
|
||||
**StatusCommand.cs строки 134-143**: Multiple fallback scenarios
|
||||
```csharp
|
||||
catch (Exception ex)
|
||||
{
|
||||
statusBuilder.AppendLine($"• Статус: ❌ Ошибка: {ex.Message}");
|
||||
}
|
||||
// ...
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"❌ Ошибка при получении статуса: {ex.Message}";
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Конкретные рекомендации по приоритетам
|
||||
|
||||
### Высокий приоритет (даст +8-10%)
|
||||
1. ✅ **Исключить миграции из coverage** (5 минут)
|
||||
2. 🔧 **Добавить тесты для exception paths в BotInfoService** (30 минут)
|
||||
3. 🔧 **Протестировать DatabaseSessionStorage exception scenarios** (1 час)
|
||||
4. 🔧 **Добавить тесты для HistoryCompressionService fallbacks** (45 минут)
|
||||
|
||||
### Средний приоритет (даст +3-5%)
|
||||
1. 🔧 **Протестировать Health Checks с failures** (30 минут)
|
||||
2. 🔧 **Добавить тесты для Telegram error handlers** (45 минут)
|
||||
3. 🔧 **Покрыть Program.cs finally block** (сложно, 1-2 часа)
|
||||
|
||||
### Низкий приоритет (даст +1-2%)
|
||||
1. 📝 **Double-check locking scenarios в BotInfoService**
|
||||
2. 📝 **Retry логика edge cases**
|
||||
3. 📝 **Validator extreme inputs**
|
||||
|
||||
---
|
||||
|
||||
## Команды для анализа
|
||||
|
||||
### Запуск coverage с детальным отчетом
|
||||
```powershell
|
||||
# Установить reportgenerator (если еще не установлен)
|
||||
dotnet tool install -g dotnet-reportgenerator-globaltool
|
||||
|
||||
# Собрать coverage
|
||||
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=./TestResults/coverage.cobertura.xml
|
||||
|
||||
# Сгенерировать HTML отчет
|
||||
reportgenerator -reports:./TestResults/coverage.cobertura.xml -targetdir:./TestResults/CoverageReport -reporttypes:Html
|
||||
|
||||
# Открыть в браузере
|
||||
start ./TestResults/CoverageReport/index.html
|
||||
```
|
||||
|
||||
### Найти непокрытые строки конкретного файла
|
||||
```powershell
|
||||
# После запуска reportgenerator откройте:
|
||||
# TestResults/CoverageReport/index.html
|
||||
# Перейдите к нужному файлу и увидите красные/желтые/зеленые строки
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Итоговая таблица
|
||||
|
||||
| Категория | % от общего кода | Причина | Сложность исправления |
|
||||
|-----------------------------|------------------|-----------------------|-----------------------|
|
||||
| Exception handlers | ~15% | Нет negative tests | Средняя (2-4 часа) |
|
||||
| Миграции (autogen) | ~10% | Не нужно покрывать | Легко (5 минут) |
|
||||
| Program.cs setup | ~8% | Интеграционный код | Сложная (2-3 часа) |
|
||||
| Edge cases & race conditions| ~5% | Сложные сценарии | Сложная (3-5 часов) |
|
||||
| Fallback логика | ~3% | Редкие пути | Средняя (1-2 часа) |
|
||||
| **ИТОГО** | **~41%** | (с запасом) | |
|
||||
|
||||
*Примечание: Реальный % непокрытого кода = 36%, но категории могут пересекаться*
|
||||
|
||||
---
|
||||
|
||||
## Заключение
|
||||
|
||||
**64% - это хороший показатель** для production проекта такого размера (1385 тестов).
|
||||
|
||||
**Быстрый путь к 75%** (2-3 часа работы):
|
||||
1. ✅ Исключить миграции (+4-5%)
|
||||
2. 🔧 Добавить 10-15 тестов на exception paths (+6-7%)
|
||||
|
||||
**Путь к 80%** (1-2 дня работы):
|
||||
- + Все вышеперечисленное
|
||||
- + Покрыть редкие edge cases
|
||||
- + Улучшить integration тесты для Program.cs
|
||||
|
||||
**Реалистичный максимум: 82-85%** (некоторые пути просто слишком сложны для тестирования)
|
||||
Reference in New Issue
Block a user