5. Тестирование и отладка

Учебный кейс: «Система аренды спортивного инвентаря»

5.1. Стратегия тестирования

Цель: подтвердить корректность расчётов, статусов, целостность данных (JSON), устойчивость к ошибочному вводу и соответствие ТЗ.

Объекты тестирования: TariffCalculator, RentalService, DataStorage, модели (InventoryItem, Rental), консольный UI.

Вид тестовПокрытие
Модульныерасчёт тарифов, изменение статусов, закрытие аренды
Интеграционныецепочка: UI → Service → Storage
Границы/классыинтервалы времени (rounding), эквивалентные классы ввода
Негативныеошибки/исключения (недоступный инвентарь, битый JSON)
Регрессионныеповторный прогон после исправлений
Простейшая производительностьотклик на наборе до 1000 записей
Mermaid: жизненный цикл дефекта (опционально)
flowchart LR
  Found[Найден дефект] --> Logged[Заведён BUG]
  Logged --> Dev[Исправление]
  Dev --> Test[Проверка/регресс]
  Test -->|OK| Closed[Закрыт]
  Test -->|Fail| Reopen[Переоткрыт] --> Dev
        

5.2. Эквивалентные классы и граничные значения

5.2.1. Ввод времени (start/end)

5.2.2. Статусы инвентаря

5.2.3. Тарифы

5.3. Решающие таблицы (decision tables)

5.3.1. Округление для hour при правиле ceil_30min

МинутыОжидаемый биллинговый час
0–29hours
30–59hours + 1
Минимум 1 час независимо от длительности > 0 мин.

5.3.2. Суточный тариф day

ДлительностьОжидаемые дни к оплате
1–24 ч1
24 ч + 1 мин2
N суток ровноN

5.4. Таблица тестовых сценариев (key test cases)

IDЧто тестируемВходные данныеОжидаемый результат
TC-CALC-01Часовой: 15 минstart=10:00 end=10:15 rate=3001 * 300 = 300
TC-CALC-02Часовой: 1ч29мstart=10:00 end=11:29 rate=3001 * 300 = 300
TC-CALC-03Часовой: 1ч30мstart=10:00 end=11:30 rate=3002 * 300 = 600
TC-CALC-04Часовой: 1ч35мstart=10:00 end=11:35 rate=3002 * 300 = 600
TC-CALC-05Переход сутокstart=23:30 end=00:20 rate=3001 * 300 = 300
TC-CALC-06Суточный: 25 чmode=day rate=12002 * 1200 = 2400
TC-STATUS-01Открытие арендыitem.status=availablerental open, item=rented
TC-STATUS-02Двойная выдачаitem.status=rentedисключение «недоступна для выдачи»
TC-RENT-01Закрытие арендыopen → close (1ч35м)total = 600, item=available
TC-DATA-01JSON записьSaveAll()файлы обновлены, валидный JSON
TC-NEG-01Неверный статусChangeStatus("bad")исключение OutOfRange
TC-NEG-02end < startCalculateсумма 0 (или исключение по политике)
TC-PERF-011000 записейоперации поискаотклик ≤ 1 c (локально)

5.5. Таблица входных/выходных данных (фрагмент)

5.5.1. Расчёт по часовому тарифу (rate = 300)

startendМинут сумм.Биллинговые часыОжид. сумма
10:0010:15151300
10:0010:59591300
10:0011:00601300
10:0011:30902600
10:0011:35952600

5.5.2. Суточный (rate = 1200)

ДлительностьОжид. дниСумма
12 ч11200
24 ч11200
25 ч22400

5.6. Примеры модульных тестов (NUnit)

Если потребуется, можно вынести в отдельный проект RentalApp.Tests и подключить NUnit.

// Install-Package NUnit
// Install-Package NUnit3TestAdapter
// Install-Package Microsoft.NET.Test.Sdk
using NUnit.Framework;
using RentalApp.Services;
using RentalApp.Domain;

[TestFixture]
public class TariffCalculatorTests
{
    [Test]
    public void Hour_1h30m_RoundsUp()
    {
        var t = new Tariff { Mode = "hour", Rate = 300, RoundRule = "ceil_30min" };
        var calc = new TariffCalculator();
        var sum = calc.Calculate(t, new DateTime(2025,1,1,10,0,0), new DateTime(2025,1,1,11,30,0));
        Assert.AreEqual(600m, sum);
    }

    [Test]
    public void Day_25h_TwoDays()
    {
        var t = new Tariff { Mode = "day", Rate = 1200 };
        var calc = new TariffCalculator();
        var sum = calc.Calculate(t, new DateTime(2025,1,1,10,0,0), new DateTime(2025,1,2,11,0,0));
        Assert.AreEqual(2400m, sum);
    }
}

5.7. Негативные сценарии (обязательные проверки)

СценарийДействиеОжидаемый результат
Пустые файлы данныхLoadAll()списки инициализируются пустыми, приложение не падает
Отсутствует каталог dataзапусккаталог создаётся, файлы появляются при SaveAll()
Повреждённый JSONLoadAll()информативная ошибка в UI, предложение восстановить/пересоздать
Попытка закрыть закрытую арендуCloseRental()исключение «уже закрыт»
Выдача единицы на ТОstatus=maintenanceотказ в операции

5.8. Дефект-лист (образец)

IDВерсияОписание дефектаШаги воспроизведенияФакт. результатОжид. результатСтатусИсправление
BUG-001v1.0Округление 1ч30м даёт 300start=10:00 end=11:30300600Fixedисправлен расчёт minutes >= 30
BUG-002v1.0Выдача предмета со статусом maintenanceOpenRental на item=maintenanceаренда созданаотказFixedпроверка статуса в OpenRental
BUG-003v1.0Повреждённый JSON падает без сообщенияЗапуск с битым items.jsonисключение в консолипонятное сообщениеFixedtry/catch в Load, текст в UI

5.9. Отладка: рекомендации

5.10. Критерии приёмки блока тестирования (соответствие ТЗ)