227 lines
8.5 KiB
Markdown
227 lines
8.5 KiB
Markdown
# Анализ непокрытого кода (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%** (некоторые пути просто слишком сложны для тестирования)
|