Template
194 lines
8.6 KiB
C#
194 lines
8.6 KiB
C#
using FluentAssertions;
|
|
using Strata.ContinuousImprovement.Biz.Exploration;
|
|
using Strata.ContinuousImprovement.Biz.Exploration.CaseTypeFamilies;
|
|
using Strata.ContinuousImprovement.Biz.Exploration.Filters;
|
|
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
namespace Strata.ContinuousImprovement.Biz.Test.Integration.SnowflakeIntegrationTests
|
|
{
|
|
[ExcludeFromCodeCoverage]
|
|
[TestFixture, Category("Integration"), Category("CCI")]
|
|
public class FlexibleExplorationSummaryDetailTest : IntegrationTestBase
|
|
{
|
|
private static readonly Guid _configurationGuid = Guid.Parse("aa4cba4f-2506-462c-8e34-c45b21653988");
|
|
|
|
[OneTimeSetUp]
|
|
public async Task SetupExploration()
|
|
{
|
|
var explorationInfo = CreateExplorationInfo();
|
|
var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None);
|
|
|
|
if (!summaries.Any())
|
|
throw new InvalidOperationException("No Case Type Family summaries returned for setup.");
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetCaseTypeFamilySummaryDetails_WhenNoFilters_IsEquivalent()
|
|
{
|
|
// arrange
|
|
var explorationInfo = CreateExplorationInfo();
|
|
|
|
// act
|
|
var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None);
|
|
var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First();
|
|
explorationInfo.CaseTypeFamilyId = testSummary.Data.Id;
|
|
|
|
var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None);
|
|
var testDetail = testDetails.First();
|
|
// assert
|
|
testDetail.Data.Should().BeEquivalentTo(testSummary.Data,
|
|
options => options
|
|
.Using<double>(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001))
|
|
.WhenTypeIs<double>());
|
|
}
|
|
|
|
[TestCaseSource(nameof(ExclusionCriteriaTestCases))]
|
|
public async Task GetCaseTypeFamilySummaries_WithExclusions(ExclusionCriteria exclusions)
|
|
{
|
|
await RunExclusionSummaryTests(exclusions);
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetCaseTypeFamilySummaryDetails_WithFilters_IsEquivalent()
|
|
{
|
|
// arrange - filtering on mortality (IsSelected = true => MortalityRate = 1)
|
|
var booleanFilter = CreateBooleanFilter(ChipKey.Mortality);
|
|
var explorationInfo = CreateExplorationInfo(booleanFilter);
|
|
|
|
// act
|
|
var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None);
|
|
var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First();
|
|
explorationInfo.CaseTypeFamilyId = testSummary.Data.Id;
|
|
|
|
var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None);
|
|
var testDetail = testDetails.First();
|
|
// assert
|
|
testDetail.Data.Should().BeEquivalentTo(testSummary.Data,
|
|
options => options
|
|
.Using<double>(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001))
|
|
.WhenTypeIs<double>());
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetCaseTypeFamilySummaryDetails_WithFiltersAndExclusions_IsEquivalent()
|
|
{
|
|
// arrange - iqr + mad exclusion combo with a boolean filter
|
|
var booleanFilter = CreateBooleanFilter(ChipKey.Mortality);
|
|
var exclusions = new ExclusionCriteria
|
|
{
|
|
CostExclusionType = ExclusionCriteriaType.Iqr,
|
|
CostExclusionValue = 1.5,
|
|
LosExclusionType = ExclusionCriteriaType.Mad,
|
|
LosExclusionValue = 2
|
|
};
|
|
var explorationInfo = CreateExplorationInfo(booleanFilter, exclusions);
|
|
|
|
// act
|
|
var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None);
|
|
var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First();
|
|
explorationInfo.CaseTypeFamilyId = testSummary.Data.Id;
|
|
|
|
var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None);
|
|
var testDetail = testDetails.First();
|
|
// assert
|
|
testDetail.Data.Should().BeEquivalentTo(testSummary.Data,
|
|
options => options
|
|
.Using<double>(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001))
|
|
.WhenTypeIs<double>());
|
|
}
|
|
|
|
private FilterChipItem CreateDischargeDateFilter() => new()
|
|
{
|
|
ChipType = ChipType.DateRange,
|
|
Filters = [],
|
|
DateRange = [new DateTime(2024, 1, 1), new DateTime(2025, 1, 1)]
|
|
};
|
|
|
|
private FilterChipItem CreateBooleanFilter(ChipKey key)
|
|
{
|
|
if (key is ChipKey.Mortality)
|
|
{
|
|
return new FilterChipItem
|
|
{
|
|
ChipType = ChipType.Boolean,
|
|
GlobalId = "Mortality",
|
|
IsSelected = true, // determines true/false of filter
|
|
Key = ChipKey.Mortality,
|
|
Operator = OperatorType.In,
|
|
Filters = new List<TreeNode>()
|
|
{
|
|
new TreeNode
|
|
{
|
|
DisplayText = "Yes"
|
|
}},
|
|
};
|
|
}
|
|
|
|
throw new ArgumentException($"Unsupported boolean filter: {key}", nameof(key));
|
|
}
|
|
|
|
private ExplorationCostDriverInfo CreateExplorationInfo(FilterChipItem? additionalFilter = null, ExclusionCriteria? exclusion = null)
|
|
{
|
|
var dischargeDateFilter = CreateDischargeDateFilter();
|
|
var filterChipItems = additionalFilter != null ?
|
|
new List<FilterChipItem> { dischargeDateFilter, additionalFilter }
|
|
: new List<FilterChipItem> { dischargeDateFilter };
|
|
|
|
return new ExplorationCostDriverInfo
|
|
{
|
|
ConfigurationGuid = _configurationGuid,
|
|
ExclusionCriteria = exclusion ?? new ExclusionCriteria(),
|
|
Filters = new Biz.Exploration.Filters.Filter
|
|
{
|
|
DischargeDateStart = dischargeDateFilter.DateRange.First(),
|
|
DischargeDateEnd = dischargeDateFilter.DateRange.Last(),
|
|
FilterChipItems = filterChipItems
|
|
}
|
|
};
|
|
}
|
|
|
|
private async Task RunExclusionSummaryTests(ExclusionCriteria exclusions)
|
|
{
|
|
// arrange
|
|
var explorationInfo = CreateExplorationInfo(null, exclusions);
|
|
|
|
// act
|
|
var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None);
|
|
var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First();
|
|
explorationInfo.CaseTypeFamilyId = testSummary.Data.Id;
|
|
|
|
var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None);
|
|
var testDetail = testDetails.First();
|
|
// assert
|
|
testDetail.Data.Should().BeEquivalentTo(testSummary.Data,
|
|
options => options
|
|
.Using<double>(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001))
|
|
.WhenTypeIs<double>());
|
|
}
|
|
|
|
private static IEnumerable<TestCaseData> ExclusionCriteriaTestCases()
|
|
{
|
|
yield return new TestCaseData(
|
|
new ExclusionCriteria
|
|
{
|
|
CostExclusionType = ExclusionCriteriaType.Mad,
|
|
CostExclusionValue = 2,
|
|
LosExclusionType = ExclusionCriteriaType.Mad,
|
|
LosExclusionValue = 2
|
|
}
|
|
).SetName("GetCaseTypeFamilySummaryDetails_WithMADExclusions_IsEquivalent");
|
|
|
|
yield return new TestCaseData(
|
|
new ExclusionCriteria
|
|
{
|
|
CostExclusionType = ExclusionCriteriaType.Iqr,
|
|
CostExclusionValue = 1.5,
|
|
LosExclusionType = ExclusionCriteriaType.Iqr,
|
|
LosExclusionValue = 1.5
|
|
}
|
|
).SetName("GetCaseTypeFamilySummaryDetails_WithIQRExclusions_IsEquivalent");
|
|
}
|
|
}
|
|
}
|