Skip to content

Модульное и интеграционное тестирование ​

1. Архитектура и принципы тестирования платформы ​

В программном комплексе «UrFU HeatBalance» система автоматизированного тестирования выполняет критическую функцию обеспечения метрологической точности, термодинамической корректности и математической сходимости уравнений теплового и материального балансов.

Тестовый контур решает три ключевые инженерные задачи:

  1. Верификация законов сохранения энергии и массы: строгий контроль соблюдения балансового равенства:
    ∑Qподв=∑Qпол+∑Qпот+∑Qнев\sum Q_{\text{подв}} = \sum Q_{\text{пол}} + \sum Q_{\text{пот}} + \sum Q_{\text{нев}}
  2. Контроль допустимой невязки: подтверждение того, что численная невязка баланса ε\varepsilon не превышает регламентный порог 0.01%0.01\%.
  3. Quality Gate в конвейере CI/CD: автоматическая блокировка компиляции и выкатки контейнеров при выявлении регрессии в расчётных модулях.

2. Спецификация модульных тестов (HeatBalance.Math.Tests) ​

Все базовые физико-химические и теплотехнические алгоритмы изолированы в разделяемой библиотеке HeatBalance.Math и верифицируются набором тестов в проекте HeatBalance.Math.Tests/UnitTest1.cs на базе тестового фреймворка xUnit.

2.1. Сводная матрица модульных тестов ​

Имя теста в UnitTest1.csТип агрегатаПроверяемый физический сценарийКлючевые критерии приемки
ConveyorKiln_SampleCase_IsStableКонвейерная печьБазовый экспресс-расчёт по удельным долям и низшей теплоте сгоранияФиксация подвода (840 000±0.1840\,000 \pm 0.1 кДж/ч), диапазон полезного тепла ([630 000,632 000][630\,000, 632\,000] кДж/ч), неотрицательная невязка.
ConveyorKiln_DetailedCase_PrintValuesКонвейерная печьПолный детальный технологический расчёт с учётом футеровки и транспортаФормирование таблиц без рециркуляции и с рециркуляцией, КПД η∈(0,1)\eta \in (0, 1), валидность структуры FuelCombustion.
ChamberKiln_SampleCase_IsStableКамерная печьЭкспресс-расчёт камерной печи периодического действияСтабильность подвода тепла, проверка потерь 168 000±0.1168\,000 \pm 0.1 кДж/ч.
ChamberKiln_DetailedCase_PrintValuesКамерная печьДетальный нестационарный теплообмен: нагрев садки, аккумуляция тепла кладкой, ступенчатый график температурПоложительная полезная мощность, сходимость теплового баланса, расчёт нестационарных периодов (разогрев, выдержка, охлаждение).
ElectricKiln_SampleCase_IsStableЭлектрическая печьЭкспресс-расчёт электрической сушилки при заданной мощности ТЭНов (233.33 кВт)Эквивалентность подвода электрической энергии тепловому эквиваленту (840 000±1840\,000 \pm 1 кДж/ч, 1 кВт⋅ч=3600 кДж1 \text{ кВт}\cdot\text{ч} = 3600 \text{ кДж}).
ElectricKiln_DetailedCase_IsStableЭлектрическая печьДетальный расчёт электропечи с конвективной вентиляцией и ограждающими конструкциямиРасчёт расхода вентиляционного воздуха (500 м3/ч500 \text{ м}^3/\text{ч}), теплопередача через свод и стены, КПД η∈(0,1)\eta \in (0, 1).
DrumDryer_SampleCase_IsStableСушильный барабанБазовый тепловой баланс вращающегося барабанного сушильного агрегатаСтабильность балансовых уравнений, расчёт потерь через вращающийся корпус (151 200±0.1151\,200 \pm 0.1 кДж/ч).

3. Детальный анализ тестовых сценариев ​

3.1. Тест конвейерной печи: верификация базового случая ​

В тесте ConveyorKiln_SampleCase_IsStable проверяется согласованность модели при типовом расходе влажного материала 1000 кг/ч1000 \text{ кг/ч} и снижении влажности с 30%30\% до 10%10\%:

csharp
[Fact]
public void ConveyorKiln_SampleCase_IsStable()
{
    var input = new ConveyorKilnInput
    {
        WetMaterialMassFlowKgPerHour = 1000,
        MoistureInMassFraction = 0.30,
        MoistureOutMassFraction = 0.10,
        MaterialTempInC = 20,
        MaterialTempOutC = 80,
        FuelLowerHeatingValueKJPerKg = 42000,
        FuelMassFlowKgPerHour = 20,
        HeatLossFraction = 0.15
    };

    var result = HeatBalanceCalculations.Calculate(input);

    Assert.Equal(DryerUnitType.ConveyorKiln, result.UnitType);
    Assert.InRange(result.TotalInputKJPerHour, 839_999.9, 840_000.1);
    Assert.InRange(result.UsefulHeatKJPerHour, 630_000, 632_000);
    Assert.InRange(result.LossesKJPerHour, 125_999.9, 126_000.1);
    Assert.True(result.UnaccountedKJPerHour > 0);
}

3.2. Тест электрической печи: конвертация электрической мощности ​

Тест ElectricKiln_SampleCase_IsStable валидирует физическую корректность перевода мощности нагревателей из киловатт в килоджоули в час:

Qэлектр=PкВт⋅3600 кДж/чQ_{\text{электр}} = P_{\text{кВт}} \cdot 3600 \text{ кДж/ч}
csharp
[Fact]
public void ElectricKiln_SampleCase_IsStable()
{
    var input = new ElectricKilnInput
    {
        WetMaterialMassFlowKgPerHour = 1000,
        MoistureInMassFraction = 0.30,
        MoistureOutMassFraction = 0.10,
        MaterialTempInC = 20,
        MaterialTempOutC = 80,
        ElectricPowerKw = 233.3333333333, // 233.333.. * 3600 = 840000 кДж/ч
        HeatLossFraction = 0.10
    };

    var result = HeatBalanceCalculations.Calculate(input);

    Assert.Equal(DryerUnitType.ElectricKiln, result.UnitType);
    Assert.InRange(result.TotalInputKJPerHour, 839_999.0, 840_001.0);
    Assert.InRange(result.LossesKJPerHour, 83_999.0, 84_001.0);
    Assert.True(result.UnaccountedKJPerHour > 0);
}

4. Регламент запуска тестов через интерфейс командной строки (CLI) ​

4.1. Запуск полного набора тестов ​

Для прогона всех тестов решения выполните команду из каталога backend/HeatBalanceSystem2:

bash
cd backend/HeatBalanceSystem2
dotnet test HeatBalance.Math.Tests/HeatBalance.Math.Tests.csproj --configuration Release

4.2. Фильтрация и селективный запуск тестов ​

Для ускоренной отладки конкретного модуля используйте параметр --filter:

bash
# Запуск только тестов камерной сушильной печи
dotnet test --filter "FullyQualifiedName~ChamberKiln"

# Запуск только тестов электрической печи с подробным логированием каждого ассерта
dotnet test --filter "FullyQualifiedName~ElectricKiln" --logger "console;verbosity=detailed"

4.3. Оценка покрытия кода тестами (Code Coverage) ​

Для генерации отчёта о покрытии кода тестами используется встроенный сборщик Coverlet:

bash
dotnet test --collect:"XPlat Code Coverage"

Отчёт в формате Cobertura XML сохраняется в каталоге TestResults/ и анализируется инструментами статического контроля качества.


5. Методология разработки новых тестов (Best Practices) ​

При добавлении новых физических моделей или модификации существующих алгоритмов разработчик обязан руководствоваться следующими стандартами:

5.1. Паттерн Arrange-Act-Assert (AAA) ​

Каждый тест должен чётко разделяться на три фазы:

  1. Arrange: формирование объекта входных параметров с реалистичными физическими величинами.
  2. Act: вызов статического метода расчёта HeatBalanceCalculations.Calculate(input).
  3. Assert: верификация инвариантов, балансовых равенств и полей сводной таблицы.

5.2. Параметризованные тесты ([Theory] и [InlineData]) ​

Для проверки поведения модели на различных диапазонах влажности и температур применяются параметризованные тесты:

csharp
[Theory]
[InlineData(0.20, 0.05, 750_000)]
[InlineData(0.35, 0.08, 920_000)]
[InlineData(0.15, 0.02, 610_000)]
public void ConveyorKiln_MoistureVariations_UsefulHeatWithinBounds(
    double moistureIn, double moistureOut, double expectedUsefulHeatMin)
{
    // Arrange
    var input = new ConveyorKilnInput
    {
        WetMaterialMassFlowKgPerHour = 1200,
        MoistureInMassFraction = moistureIn,
        MoistureOutMassFraction = moistureOut,
        FuelLowerHeatingValueKJPerKg = 41800,
        FuelMassFlowKgPerHour = 25
    };

    // Act
    var result = HeatBalanceCalculations.Calculate(input);

    // Assert
    Assert.True(result.UsefulHeatKJPerHour >= expectedUsefulHeatMin);
    Assert.True(result.Efficiency > 0.0 && result.Efficiency < 1.0);
}

5.3. Негативное тестирование и проверка исключений (Edge Cases) ​

Тестовый набор должен гарантировать, что некорректные физические параметры вызывают прогнозируемые исключения ArgumentException:

csharp
[Fact]
public void Calculate_FinalMoistureGreaterThanInitial_ThrowsArgumentException()
{
    // Попытка задать конечную влажность выше начальной (абсурдный процесс сушки)
    var invalidInput = new ConveyorKilnInput
    {
        MoistureInMassFraction = 0.05,
        MoistureOutMassFraction = 0.30
    };

    Assert.Throws<ArgumentException>(() => HeatBalanceCalculations.Calculate(invalidInput));
}

Разработано в рамках проекта моделирования тепловых балансов и промышленного мониторинга