Skip to content

Unit Test Cleanup #1227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 0 additions & 58 deletions HEC.FDA.Model/Spatial/PointShapefile.cs

This file was deleted.

32 changes: 21 additions & 11 deletions HEC.FDA.Model/Spatial/StructureDataValidator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Geospatial.Features;
using System;
using System.Collections.Generic;
using Utility.Memory;

Expand All @@ -12,17 +13,18 @@ public static class StructureDataValidator
/// <summary>
/// Check that the given row has all the specified fields. out param returns the whole row as objects, and list of the column headers with missing data.
/// </summary>
public static bool RowHasValuesForColumns(PointShapefile pointShapefile, int rowIndex, List<string> requiredFields, out List<string> missingValues)
public static bool RowHasValuesForColumns(PointFeatureCollection pointShapefile, int rowIndex, List<string> requiredFields, out List<string> missingValues)
{
bool valid = true;
missingValues = new();
TableRow row = pointShapefile.Rows[rowIndex];
TableRow row = pointShapefile.AttributeTable.Rows[rowIndex];

for(int i = 0; i < requiredFields.Count; i++)
{
string fieldName = requiredFields[i];
object val = row.Value(fieldName);
if(CellIsEmpty(val))
Type type = row.Table.GetColumn(fieldName).Type;
if (CellIsEmpty(val, type))
{
valid = false;
missingValues.Add(fieldName);
Expand All @@ -34,16 +36,17 @@ public static bool RowHasValuesForColumns(PointShapefile pointShapefile, int row
/// <summary>
/// Checks that all rows have the specified field. out param returns index of rows without.
/// </summary>
public static bool RowsHaveValueForColumn(PointShapefile pointShapefile, string field, out List<int> rowsWithMissingData)
public static bool RowsHaveValueForColumn(PointFeatureCollection pointShapefile, string field, out List<int> rowsWithMissingData)
{
bool valid = true;
rowsWithMissingData = [];

var rows = pointShapefile.Rows;
var rows = pointShapefile.AttributeTable.Rows;
for (int i = 0; i < rows.Count; i++)
{
object val = rows[i].Value(field);
if (CellIsEmpty(val))
Type type = rows[i].Table.GetColumn(field).Type;
if (CellIsEmpty(val, type))
{
rowsWithMissingData.Add(i);
valid = false;
Expand All @@ -57,17 +60,18 @@ public static bool RowsHaveValueForColumn(PointShapefile pointShapefile, string
/// <summary>
/// Checks that all rows have unique vlaues for the specified column. out param returns index of rows with duplicated data. Ignores rows with no data.
/// </summary>
public static bool AllRowsHaveUniqueValueForColumn<T>(PointShapefile pointShapefile, string columnName, out List<int> rowsWithDuplicatedData)
public static bool AllRowsHaveUniqueValueForColumn<T>(PointFeatureCollection pointShapefile, string columnName, out List<int> rowsWithDuplicatedData)
{
bool valid = true;
var rows = pointShapefile.Rows;
var rows = pointShapefile.AttributeTable.Rows;
rowsWithDuplicatedData = [];
List<object> previousVals = [];

for (int i = 0; i < rows.Count; i++)
{
object val = rows[i].Value(columnName);
if (CellIsEmpty(val))
Type type = rows[i].Table.GetColumn(columnName).Type;
if (CellIsEmpty(val, type))
{
continue;
}
Expand All @@ -85,9 +89,15 @@ public static bool AllRowsHaveUniqueValueForColumn<T>(PointShapefile pointShapef
}


private static bool CellIsEmpty(object cellValue)
private static bool CellIsEmpty(object cellValue, Type type)
{
///ints have to have some value. Can't be null. Geospatial will return -1 for missing values in an int column.
if(type == typeof(int))
{
return ((int)cellValue == -1);
}
return (cellValue == DBNull.Value || cellValue == null);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@

namespace HEC.FDA.ModelTest.integrationtests;

[Trait("RunsOn", "Local")]
[Collection("Serial")]
[Trait("RunsOn", "Never")]
public class BigInventoryStageDamageTest
{
#region Structure Data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace HEC.FDA.ModelTest.integrationtests
{
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
[Collection("Serial")]
public class DefaultDataComputeOutcomes
{
Expand Down Expand Up @@ -268,7 +268,7 @@ public void AnalyticalWithRegUnreg_ScenarioResults(double expectedResidentialMea
//Act
double actualResidentialMeanEAD = scenarioResults.MeanExpectedAnnualConsequences(impactAreaID1, residentialDamageCategory);
double actualCommercialMeanEAD = scenarioResults.MeanExpectedAnnualConsequences(impactAreaID1, commercialDamageCategory);
double tolerance = 0.19;
double tolerance = 0.2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we reconsider whether this test is helpful?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likely. Where did the expected values come from?

double residentialEADRelativeDifference = Math.Abs(actualResidentialMeanEAD - expectedResidentialMeanEAD) / expectedResidentialMeanEAD;
double commercialEADRelativeDifference = Math.Abs(actualCommercialMeanEAD - expectedCommericialMeanEAD) / expectedCommericialMeanEAD;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace HEC.FDA.ModelTest.integrationtests
{
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class DesPeresStudyDataTests
{
static int impactAreaID = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace HEC.FDA.ModelTest.integrationtests
{
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class GraphicalUncertaintyShould
{
private static CurveMetaData curveMetaData = new CurveMetaData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace HEC.FDA.ModelTest.integrationtests
{
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class StudyDataAnalyticalFrequencyResultsTests
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace HEC.FDA.ModelTest.integrationtests
/// see: https://drive.google.com/file/d/12WJL6ambACQLfqGUwbg7tv_wMxLn-a6t/view?usp=sharing
/// </summary>
///
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class StudyDataGraphicalFlowFrequencyResultsTests
{
static int equivalentRecordLength = 48;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace HEC.FDA.ModelTest.integrationtests
/// The data is based on without project, 2025, Reach 1, Residential
/// </summary>
///
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class StudyDataGraphicalStageFrequencyResultsTests
{
static int impactareaid = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace HEC.FDA.ModelTest.unittests.MessagingTests
{
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class ImpactAreaScenarioSimulationShould
{
static int equivalentRecordLength = 48;
Expand Down
2 changes: 1 addition & 1 deletion HEC.FDA.ModelTest/unittests/PerformanceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
namespace HEC.FDA.ModelTest.unittests
{
[Collection("Serial")]
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class PerformanceTest
{
static double[] Flows = { 0, 100000 };
Expand Down
54 changes: 28 additions & 26 deletions HEC.FDA.ModelTest/unittests/PointShapefileShould.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using Geospatial.Features;
using Geospatial.IO;
using HEC.FDA.Model.Spatial;
using HEC.FDA.Model.structures;
using HEC.FDA.ModelTest.Resources;
Expand All @@ -10,65 +12,65 @@

namespace HEC.FDA.ModelTest.unittests;
[Collection("Serial")]
[Trait("RunsOn", "Remote")]
public class PointShapefileShould
{
[Fact]
[Trait("RunsOn", "Remote")]
public void InvalidateInvalidShapefile()
private static PointFeatureCollection pointShapefile = GetFeatures(Resources.StringResourcePaths.pathToNSIShapefile);

private static PointFeatureCollection GetFeatures(string pointShapefilePath)
{
Assert.Throws<Exception>(() => new PointShapefile(Resources.StringResourcePaths.pathToIAShapefileNODBF));
if (ShapefileIO.TryRead(pointShapefilePath, out PointFeatureCollection collection)) ;
{
return collection;
}
throw new Exception("Failed to read shapefile");
}

[Fact]
public void LoadValidShapefile()
public void InvalidateInvalidShapefile()
{
PointShapefile shapefile = new PointShapefile(Resources.StringResourcePaths.pathToNSIShapefile);
Assert.NotNull(shapefile);
Assert.False(ShapefileIO.TryRead(Resources.StringResourcePaths.pathToIAShapefileNODBF, out PolygonFeatureCollection collection));
}

[Fact]
public void GetRowValues_ReturnCorrectValues()
public void LoadValidShapefile()
{
// Arrange
PointShapefile shapefile = new PointShapefile(Resources.StringResourcePaths.pathToNSIShapefile);
int rowId = 0;
string[] columnNames = { "fd_id", "occtype", "yrbuilt" };
object[] expectedRowValues = {26813713, "RES1-1SNB",1900};

// Act
object[] actualRowValues = shapefile.GetRowValues(rowId, columnNames);

// Assert
Assert.Equal((int)expectedRowValues[0], (int)actualRowValues[0]);
Assert.Equal((string)expectedRowValues[1], (string)actualRowValues[1]);
Assert.Equal((int)expectedRowValues[2], (int)actualRowValues[2]);
Assert.True(ShapefileIO.TryRead(Resources.StringResourcePaths.pathToIAShapefile, out PolygonFeatureCollection collection));
}

[Fact]
public void GetColumnValues_ReturnCorrectValues()
{
// Arrange
PointShapefile shapefile = new PointShapefile(Resources.StringResourcePaths.pathToNSIShapefile);
if (!ShapefileIO.TryRead(Resources.StringResourcePaths.pathToNSIShapefile, out PointFeatureCollection shapefile))
{
throw new Exception("Failed to read shapefile");
}
string columnName = "fd_id";
int[] expectedColumnValues = {26813713, 26814025, 26816202};

// Act
int[] actualColumnValues = shapefile.GetColumnValues(columnName).Cast<int>().ToArray();
IEnumerable<object> actualColumnValues = shapefile.AttributeTable.Rows.Select((r) => (r.Value(columnName)));
int[] intvals = actualColumnValues.Cast<int>().ToArray();


// Assert
Assert.Equal(expectedColumnValues, actualColumnValues[..3]);
Assert.Equal(expectedColumnValues, intvals[..3]);
}

[Fact]
public void GetColumnType_ReturnCorrectType()
{
// Arrange
PointShapefile shapefile = new PointShapefile(Resources.StringResourcePaths.pathToNSIShapefile);
if (!ShapefileIO.TryRead(Resources.StringResourcePaths.pathToNSIShapefile, out PointFeatureCollection shapefile))
{
throw new Exception("Failed to read shapefile");
}
string columnName = "fd_id";
Type expectedColumnType = typeof(int);

// Act
Type actualColumnType = shapefile.GetColumnType(columnName);
Type actualColumnType = shapefile.AttributeTable.GetColumn(columnName).Type;

// Assert
Assert.Equal(expectedColumnType, actualColumnType);
Expand Down
1 change: 1 addition & 0 deletions HEC.FDA.ModelTest/unittests/RandomTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Xunit;

namespace HEC.FDA.ModelTest.unittests;
[Trait("RunsOn", "Remote")]
/// <summary>
/// This test exists just to verify that the random number generator in .NET is consistent across versions, which is explicitly NOT Gauranteed.
/// Failure means we need to update the expected values to match the new version of .NET
Expand Down
23 changes: 2 additions & 21 deletions HEC.FDA.ModelTest/unittests/StageDamageShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

namespace HEC.FDA.ModelTest.unittests
{
[Trait("RunsOn", "Local")]
[Trait("RunsOn", "Remote")]
public class StageDamageShould
{

Expand Down Expand Up @@ -256,32 +256,13 @@ private Inventory CreateInventory()
return inventory;
}


[Fact]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have a similar test somewhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not necessarily. Truth is this test hadn't been run in a long time, and the case it was testing throws an exception way before it looks like it did in this test. A lot of processing is kicked off right in the constructor of IASD. We might reconsider that, because constructors can't fail as gracefully as we can on other methods.

For now, this test just isn't useful, and should go.

public void ErrorsShouldStopCompute()
{
//Arrange
Inventory inventory = CreateInventory();
ImpactAreaStageDamage impactAreaStageDamage = new ImpactAreaStageDamage(impactAreaID, inventory, hydraulicDataset, String.Empty, usingMockData: true);
List<ImpactAreaStageDamage> impactAreaStageDamageList = new List<ImpactAreaStageDamage>() { impactAreaStageDamage };
ScenarioStageDamage scenarioStageDamage = new ScenarioStageDamage(impactAreaStageDamageList);

//Act
//This compute should return a list with count of 0 stage-damage functions - we didnt provide any H&H summary relationships
//so cannot calculate stage frequency, and the compute should check for that
List<UncertainPairedData> nullStageDamage = impactAreaStageDamage.Compute().Item1;

//Assert
Assert.Equal(0, nullStageDamage.Count);
}

[Theory]
[InlineData(6)]
public void StructureDetailsShould(double expectedLength)
{
//Arrange
Inventory inventory = CreateInventory();
ImpactAreaStageDamage impactAreaStageDamage = new ImpactAreaStageDamage(impactAreaID, inventory, hydraulicDataset, String.Empty, usingMockData: true);
ImpactAreaStageDamage impactAreaStageDamage = new ImpactAreaStageDamage(impactAreaID, inventory, hydraulicDataset, String.Empty, graphicalFrequency: stageFrequency, usingMockData: true);
List<ImpactAreaStageDamage> impactAreaStageDamageList = new List<ImpactAreaStageDamage>() { impactAreaStageDamage };
ScenarioStageDamage scenarioStageDamage = new ScenarioStageDamage(impactAreaStageDamageList);
Dictionary<int, string> iaNames = new();
Expand Down
Loading
Loading