ProductionUiCordonel: - unit tests improved

This commit is contained in:
Thomas Wiedebusch
2025-04-14 12:07:52 +02:00
parent a7036d34b1
commit 06026d56ae
2 changed files with 77 additions and 62 deletions
@@ -86,7 +86,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
/// <summary>
/// The exec path of the assembly for debug in environment.
/// </summary>
private readonly String _assemblyExecRootPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private readonly String _assemblyExecRootPath =
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "";
/// <summary>
/// Fw package path relative to solution main folder.
@@ -146,7 +147,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
set; get;
}
public MockGenesis Meter
public MockGenesis? Meter
{
set; get;
}
@@ -256,6 +257,10 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
/// </remarks>
public CommonSteps()
{
MethodToTest = "";
PropertyToCheck = "";
ObjectTypeName = "";
TestName = "";
var subFolder = Path.Combine("Hardware", "WaterMeter", "Genesis", "MockGenesis");
var solutionPath = "";
if (NCrunchEnvironment.NCrunchIsResident())
@@ -264,7 +269,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
}
else
{
if (_assemblyExecRootPath != null)
if (!string.IsNullOrWhiteSpace(_assemblyExecRootPath))
{
// We are in the Unit test folder "..\Common\Production\ProductionUiCordonel.UnitTests\bin\Debug"
// and need to go back to "..\Common"
@@ -570,12 +575,12 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
case "ExecFinalParametrization":
// Load parameters
if (meterSizeForParams != testCase.Meter.MeterSize || regionForParams != testCase.Meter.Region ||
if (meterSizeForParams != testCase.Meter?.MeterSize || regionForParams != testCase.Meter?.Region ||
!unmodifiedParamsUsableAsReferenceForNextTest)
{
var rawProgParams = new List<ProgrammingParameters>();
if (!RegisterRestorer.ImportRawProgrammingParametersFromFile(_mockRawParamsRootPath,
testCase.Meter.Region, testCase.Meter.MeterSize, rawProgParams))
testCase.Meter?.Region, testCase.Meter?.MeterSize, rawProgParams))
{
var errorMsg = $"TestNo: {testCase.TestNo}\n ERROR: Could not load programming parameters\n";
Console.WriteLine(errorMsg);
@@ -597,8 +602,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
intermediateRecoveryRegisters.Clear();
intermediateRecoveryRegisters.AddRange(testCase.RegisterRestorer.RecoveryRegisters);
meterSizeForParams = testCase.Meter.MeterSize;
regionForParams = testCase.Meter.Region;
meterSizeForParams = testCase.Meter?.MeterSize;
regionForParams = testCase.Meter?.Region;
unmodifiedParamsUsableAsReferenceForNextTest = true;
}
// Take the parameters from the last run if those haven't changed meanwhile (identical meter size and region)
@@ -659,7 +664,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
}
if (string.IsNullOrEmpty(testResult.EOLProgress.ProductionStatusFwVersion))
testResult.EOLProgress.ProductionStatusFwVersion = testCase.Meter.FwVersion;
testResult.EOLProgress.ProductionStatusFwVersion = testCase.Meter?.FwVersion;
break;
case "CheckFinalParametrization":
@@ -668,9 +673,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
registerName = "SYSTEM_UpgradePermissions";
var readValue = RegisterConverter.ByteArrayToValue<UInt32>(
testCase.Meter.ReadRegister(registerName));
testCase.Meter?.ReadRegister(registerName));
readValue++;
testCase.Meter.WriteRegister(registerName, readValue);
testCase.Meter?.WriteRegister(registerName, readValue);
paramsCheckWillSucceed = false;
}
@@ -709,8 +714,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
testPp.ProductionStatus = testCase.CordonelDeviceStatus;
testPp.RegisterRestorer = testCase.RegisterRestorer;
// The new Object[]{null} is a placeholder for the out return if needed for the method type reflection
var parameters = new Object[] { null };
// The new Object?[]{null} is a placeholder for the out return if needed for the method type reflection
var parameters = new Object?[] { null };
// Public methods do NOT return a variable
if (!IsPrivateMethod)
parameters = null;
@@ -739,8 +744,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (testResult.StatusReturn != StatusReturn.Failed)
testResult.StatusReturn = statusReturn;
if (parameters != null)
testResult.FeedbackMsg += $"{(String)parameters[0]} ";
if (parameters?[0] is String)
testResult.FeedbackMsg += $"{parameters[0]} ";
}
/// <summary>
@@ -874,7 +879,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
// Login is needed for building the MeterAppListVersion and generating the accessible register list.
// This register list will be used to check for valid ranges.
testCase.Meter.Login();
testCase.Meter?.Login();
// This is the multiple row test table defining individual test cases
ReadTable(row, ref testCase);
@@ -901,7 +906,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
// Login is needed for building the MeterAppListVersion and generating the accessible register list.
// This register list will be used to check for valid ranges.
_presets.Meter.Login();
_presets.Meter?.Login();
// A preset table is limited to exclusively one row, those settings will be used for every test of the
// test-cases!
@@ -949,7 +954,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseInt(tableRow, "EOL Id", out strValue, out var intValue))
{
parsedTableRow.RequiredEOLProgress.Id = (Int32)intValue;
if (intValue != null) parsedTableRow.RequiredEOLProgress.Id = (Int32)intValue;
}
var strHeader = "EOL StartDate";
@@ -1020,12 +1025,13 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseInt(tableRow, "Cordonel ProdOrderNo", out strValue, out intValue))
{
parsedTableRow.Meter.OrderNumber = (Int32)intValue;
if (parsedTableRow.Meter != null && intValue != null)
parsedTableRow.Meter.OrderNumber = (Int32)intValue;
}
if (ParseInt(tableRow, "Requirement ProdOrderNo", out strValue, out intValue))
{
parsedTableRow.ProductionRequirements.ProductionOrderNr = (Int32)intValue;
if (intValue != null) parsedTableRow.ProductionRequirements.ProductionOrderNr = (Int32)intValue;
parsedTableRow.RequiredEOLProgress.RequirementOrderChecked = EOLStatus.OK;
}
@@ -1035,7 +1041,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseInt(tableRow, "Cordonel PcbId", out strValue, out intValue))
{
parsedTableRow.Meter.PcbId = strValue;
if (parsedTableRow.Meter != null) parsedTableRow.Meter.PcbId = strValue;
}
if (ParseInt(tableRow, "Requirement PcbId", out strValue, out intValue))
@@ -1046,7 +1052,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseInt(tableRow, "EOL PcbId", out strValue, out intValue))
{
parsedTableRow.RequiredEOLProgress.PcbId = (Int32)intValue;
if (intValue != null) parsedTableRow.RequiredEOLProgress.PcbId = (Int32)intValue;
}
#endregion
@@ -1055,7 +1061,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseString(tableRow, "Cordonel LUT CRC", out strValue))
{
parsedTableRow.Meter.LutCrc = strValue;
if (parsedTableRow.Meter != null) parsedTableRow.Meter.LutCrc = strValue;
}
if (ParseString(tableRow, "Requirement LUT CRC", out strValue))
@@ -1070,7 +1076,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseString(tableRow, "Cordonel Region", out strValue))
{
parsedTableRow.Meter.Region = strValue;
if (parsedTableRow.Meter != null) parsedTableRow.Meter.Region = strValue;
}
if (ParseString(tableRow, "Requirement Region", out strValue))
@@ -1085,7 +1091,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseString(tableRow, "Cordonel Meter Size", out strValue))
{
parsedTableRow.Meter.MeterSize = strValue;
if (parsedTableRow.Meter != null) parsedTableRow.Meter.MeterSize = strValue;
}
if (ParseString(tableRow, "Requirement Meter Size", out strValue))
@@ -1131,9 +1137,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
// Login needed to install the FW from hard-coded package description file. This is essential as only
// then one App could be erased or modified
parsedTableRow.Meter.Login();
parsedTableRow.Meter?.Login();
parsedTableRow.RequiredEOLProgress.ProductionStatusFwVersion = strValue;
var isInstalled = parsedTableRow.Meter.InstallNewMockFw(fwName: strValue);
var isInstalled = parsedTableRow.Meter != null && parsedTableRow.Meter.InstallNewMockFw(fwName: strValue);
var errorMsg = $"FW \"{strValue}\" could not be found in \"MockFwExamples\", parsing or " +
"installation failed!";
Assert.That(isInstalled, errorMsg);
@@ -1145,9 +1151,12 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
// Initially needed to install MockFw and set up the initial core revision. If the login will be
// delayed then the "Core Revision" is going to be overwritten from the content of the firmware
// package description file.
parsedTableRow.Meter.Login();
parsedTableRow.Meter.CoreRevision = (Int32)(floatValue * 100);
parsedTableRow.Meter.StrCoreRevision = strValue;
if (parsedTableRow.Meter != null)
{
parsedTableRow.Meter.Login();
if (floatValue != null) parsedTableRow.Meter.CoreRevision = (Int32)(floatValue * 100);
parsedTableRow.Meter.StrCoreRevision = strValue;
}
}
if (ParseString(tableRow, "Requirement FW Version", out strValue))
@@ -1161,7 +1170,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (modifyAppId != null)
{
parsedTableRow.Meter.ModifyMockApp((Byte)modifyAppId, appVersion, appCrc, eraseApp);
parsedTableRow.Meter?.ModifyMockApp((Byte)modifyAppId, appVersion, appCrc, eraseApp);
}
#endregion
@@ -1214,18 +1223,23 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseFloat(tableRow, "Actual Lifetime [days]", out strValue, out floatValue))
{
parsedTableRow.CordonelDeviceStatus.ExceededLifeTime_s = (UInt64)(floatValue * 24 * 3600);
if (floatValue != null) parsedTableRow.CordonelDeviceStatus.ExceededLifeTime_s =
(UInt64)(floatValue * 24 * 3600);
parsedTableRow.RequiredEOLProgress.ProductionStatusBatteryLoadChecked = EOLStatus.OK;
parsedTableRow.RequiredEOLProgress.ProductionStatusRemainingLifeTimeChecked = EOLStatus.OK;
}
if (ParseFloat(tableRow, "Actual Drained [%]", out strValue, out floatValue))
{
parsedTableRow.CordonelDeviceStatus.DrainedBatteryLoad_uAs =
(UInt64)(floatValue * parsedTableRow.CordonelDeviceStatus.InitialBatteryLoad_mAh *
parsedTableRow.CordonelDeviceStatus.BatteryQuantity * 1000 * 3600 / 100);
parsedTableRow.RequiredEOLProgress.ProductionStatusDrainedBatteryLoad = floatValue;
if (floatValue != null)
{
parsedTableRow.CordonelDeviceStatus.DrainedBatteryLoad_uAs =
(UInt64)(floatValue * parsedTableRow.CordonelDeviceStatus.InitialBatteryLoad_mAh *
parsedTableRow.CordonelDeviceStatus.BatteryQuantity * 1000 * 3600 / 100);
parsedTableRow.RequiredEOLProgress.ProductionStatusDrainedBatteryLoad = floatValue;
}
//GenesisStatusHandler.CalculateLifeTime(parsedTableRow.CordonelDeviceStatus);
//parsedTableRow.RequiredEOLProgress.ProductionStatusRemainingLifeTime =
// parsedTableRow.CordonelDeviceStatus.RemainingLifeTimeYears;
@@ -1275,14 +1289,16 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (ParseInt(tableRow, "Test Bench State[4]", out strValue, out intValue))
{
if (parsedTableRow.TestBenchState != null && parsedTableRow.TestBenchState.Count >= 5)
parsedTableRow.TestBenchState[4] = strValue;
if (parsedTableRow.TestBenchState.Count >= 5)
if (strValue != null)
parsedTableRow.TestBenchState[4] = strValue;
}
if (ParseInt(tableRow, "Test Bench State[5]", out strValue, out intValue))
{
if (parsedTableRow.TestBenchState != null && parsedTableRow.TestBenchState.Count >= 6)
parsedTableRow.TestBenchState[5] = strValue;
if (parsedTableRow.TestBenchState.Count >= 6)
if (strValue != null)
parsedTableRow.TestBenchState[5] = strValue;
}
if (ParseInt(tableRow, "Meter Calib Fact 1", out strValue, out intValue))
@@ -1294,8 +1310,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
parsedTableRow.RequiredEOLProgress.ProductionStatusZeroFlowChecked = EOLStatus.OK;
if (intValue != null)
{
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1", null,
RegisterConverter.ValueToByteArray((UInt16)intValue));
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1",
readBackValue: RegisterConverter.ValueToByteArray((UInt16)intValue));
}
}
@@ -1303,8 +1319,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
if (intValue != null)
{
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor2", null,
RegisterConverter.ValueToByteArray((UInt16)intValue));
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor2",
readBackValue: RegisterConverter.ValueToByteArray((UInt16)intValue));
}
}
@@ -1312,8 +1328,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
if (intValue != null)
{
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor3", null,
RegisterConverter.ValueToByteArray((UInt16)intValue));
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor3",
readBackValue: RegisterConverter.ValueToByteArray((UInt16)intValue));
}
}
@@ -1350,7 +1366,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X"))
{
parsedTableRow.Meter.KillConfigRegisters();
parsedTableRow.Meter?.KillConfigRegisters();
parsedTableRow.RequiredEOLProgress.ParametrizationCompareChecked = EOLStatus.FAIL;
parsedTableRow.RequiredEOLProgress.ParametrizationDoneChecked = EOLStatus.FAIL;
}
@@ -1433,7 +1449,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X") && !singleSelectionLock)
{
singleSelectionLock = true;
parsedTableRow.Meter.OrderNumber = 0;
if (parsedTableRow.Meter != null) parsedTableRow.Meter.OrderNumber = 0;
parsedTableRow.RequiredEOLProgress.RequirementOrderChecked = EOLStatus.FAIL;
}
}
@@ -1463,7 +1479,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X"))
{
singleSelectionLock = true;
parsedTableRow.Meter.Region = "?";
if (parsedTableRow.Meter != null) parsedTableRow.Meter.Region = "?";
parsedTableRow.RequiredEOLProgress.RequirementRegionChecked = EOLStatus.FAIL;
}
}
@@ -1478,7 +1494,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X"))
{
singleSelectionLock = true;
parsedTableRow.Meter.LutCrc = "?";
if (parsedTableRow.Meter != null) parsedTableRow.Meter.LutCrc = "?";
parsedTableRow.RequiredEOLProgress.ProductionStatusLutCrc = "";
}
}
@@ -1492,7 +1508,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
else if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X"))
{
singleSelectionLock = true;
parsedTableRow.Meter.MeterSize = "?";
if (parsedTableRow.Meter != null) parsedTableRow.Meter.MeterSize = "?";
parsedTableRow.RequiredEOLProgress.ProductionStatusMeterSize = "";
}
}
@@ -1589,9 +1605,9 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
if (!string.IsNullOrEmpty(strValue) && strValue.Equals("X") && !singleSelectionLock)
{
parsedTableRow.Meter.ReLogin();
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1", null,
RegisterConverter.ValueToByteArray((UInt16)0));
if (parsedTableRow.Meter != null) parsedTableRow.Meter.ReLogin();
PresetRegisterRestorer(parsedTableRow.CalibCheckRegisterRestorer, "GENESISFLOW_CalFactor1",
readBackValue: RegisterConverter.ValueToByteArray((UInt16)0));
parsedTableRow.RequiredEOLProgress.ProductionStatusCalibrationChecked = EOLStatus.FAIL;
}
}
@@ -1605,8 +1621,8 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
if (ObjectTypeName.Equals(strHeader.Replace(" ", "")))
{
ClassAccess.SetPropertyValue<EOLStatus, EOLProgressModel>(parsedTableRow.RequiredEOLProgress,
PropertyToCheck, GetEOLStatusFromName(strValue));
ClassAccess.SetPropertyValue(parsedTableRow.RequiredEOLProgress, PropertyToCheck,
GetEOLStatusFromName(strValue));
}
}
@@ -1615,8 +1631,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
{
if (ObjectTypeName.Equals(strHeader))
{
ClassAccess.SetPropertyValue<String, EOLProgressModel>(parsedTableRow.RequiredEOLProgress,
PropertyToCheck, strValue);
ClassAccess.SetPropertyValue(parsedTableRow.RequiredEOLProgress, PropertyToCheck, strValue);
}
}
@@ -1641,7 +1656,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
/// - Initial.
/// </remarks>
private static void PresetRegisterRestorer(RegisterRestorer regRestorer, String regName,
Byte[] writeValue = null, Byte[] readBackValue = null)
Byte[]? writeValue = null, Byte[]? readBackValue = null)
{
try
{
@@ -1703,7 +1718,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
/// <remarks date="2024-Nov-19" author="Thomas Wiedebusch">
/// - Initial.
/// </remarks>
private static Boolean ParseFloat(TableRow tableRow, String strHeader, out String strValue,
private static Boolean ParseFloat(TableRow tableRow, String strHeader, out String? strValue,
out Double? value)
{
value = null;
@@ -1740,7 +1755,7 @@ namespace Xylem.Common.Production.ProductionUiCordonel.UnitTests.Steps
/// <remarks date="2024-Nov-18" author="Thomas Wiedebusch">
/// - Accept "null" as input.
/// </remarks>
private static Boolean ParseInt(TableRow tableRow, String strHeader, out String strValue,
private static Boolean ParseInt(TableRow tableRow, String strHeader, out String? strValue,
out Int32? value)
{
value = null;