From 991e93ec58df8984f6e411efd3a218a6d44b3951 Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Sun, 22 Aug 2021 10:44:10 +0200 Subject: [PATCH 01/12] initial commit --- TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT | 3 +- TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT | 3 +- TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT | 5 ++- TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL | 12 +++++- TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU | 36 ++++++++++++++-- TcUnit/TcUnit/POUs/FB_Test.TcPOU | 32 ++++++++++++-- TcUnit/TcUnit/POUs/FB_TestResults.TcPOU | 11 ++++- TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU | 43 +++++++++++++++---- TcUnit/TcUnit/POUs/FB_xUnitXmlPublisher.TcPOU | 7 ++- TcUnit/TcUnit/POUs/Functions/TEST.TcPOU | 8 +++- .../TcUnit/POUs/Functions/TEST_FINISHED.TcPOU | 10 +++-- .../POUs/Functions/TEST_FINISHED_NAMED.TcPOU | 10 +++-- TcUnit/TcUnit/TcUnit.plcproj | 4 +- TcUnit/TcUnit/Version/Global_Version.TcGVL | 4 +- 14 files changed, 153 insertions(+), 35 deletions(-) diff --git a/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT b/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT index 50df1fa..63e369f 100644 --- a/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT +++ b/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT @@ -1,5 +1,5 @@  - + diff --git a/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT b/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT index 4e6c70a..055eb3e 100644 --- a/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT +++ b/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT @@ -1,5 +1,5 @@  - + diff --git a/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT b/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT index ffdd1c6..d551eef 100644 --- a/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT +++ b/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT @@ -1,5 +1,5 @@  - + - + - + - GVL_TcUnit.StartedAt); +END_IF + +(* Run TcUnit test suites *) IF NOT AllTestSuitesFinished THEN IF GVL_TcUnit.NumberOfInitializedTestSuites = 0 THEN AllTestSuitesFinished := TRUE; @@ -61,6 +67,7 @@ IF NOT AllTestSuitesFinished THEN GVL_TcUnit.CurrentTestSuiteBeingCalled := GVL_TcUnit.TestSuiteAddresses[Counter]; GVL_TcUnit.CurrentTestSuiteBeingCalled^.SetHasStartedRunning(); GVL_TcUnit.CurrentTestSuiteBeingCalled^(); + GVL_TcUnit.CurrentTestSuiteBeingCalled^.UpdateDuration(); END_IF END_FOR (* Check if some event triggered an abortion of running the tests, in that case abort it now. @@ -68,12 +75,21 @@ IF NOT AllTestSuitesFinished THEN IF AbortRunningTestSuites THEN NumberOfTestSuitesFinished := GVL_TcUnit.NumberOfInitializedTestSuites; END_IF + IF NumberOfTestSuitesFinished = GVL_TcUnit.NumberOfInitializedTestSuites THEN AllTestSuitesFinished := TRUE; END_IF END_IF END_IF +(* Measure the duration it took to run all testsuites *) +AllTestSuitesFinishedTrigger(CLK := AllTestSuitesFinished); +IF AllTestSuitesFinishedTrigger.Q +THEN + GVL_TcUnit.GetCpuAccount(cpuAccountDW => GVL_TcUnit.Duration); + GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) * 0.1;; +END_IF + (* Store test suite results continuously *) TestResults(); @@ -108,7 +124,12 @@ VAR_INST TimerBetweenExecutionOfTestSuites : Tc2_Standard.TOF; END_VAR]]> - GVL_TcUnit.StartedAt); +END_IF + +TimerBetweenExecutionOfTestSuites(PT := TimeBetweenTestSuitesExecution); (* Run TcUnit test suites *) IF NOT AllTestSuitesFinished THEN IF GVL_TcUnit.NumberOfInitializedTestSuites = 0 THEN @@ -127,6 +148,7 @@ IF NOT AllTestSuitesFinished THEN GVL_TcUnit.CurrentTestSuiteBeingCalled := GVL_TcUnit.TestSuiteAddresses[CurrentlyRunningTestSuite]; GVL_TcUnit.CurrentTestSuiteBeingCalled^.SetHasStartedRunning(); GVL_TcUnit.CurrentTestSuiteBeingCalled^(); + GVL_TcUnit.CurrentTestSuiteBeingCalled^.UpdateDuration(); END_IF (* Check if some event triggered an abortion of running the tests, in that case abort it now. This can be accomplished by setting the result of the test suites run to finished. *) @@ -139,6 +161,14 @@ IF NOT AllTestSuitesFinished THEN END_IF END_IF +(* Measure the duration it took to run all testsuites *) +AllTestSuitesFinishedTrigger(CLK := AllTestSuitesFinished); +IF AllTestSuitesFinishedTrigger.Q +THEN + GVL_TcUnit.GetCpuAccount(cpuAccountDW => GVL_TcUnit.Duration); + GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) * 0.1; +END_IF + (* Store test suite results continuously *) TestResults(); diff --git a/TcUnit/TcUnit/POUs/FB_Test.TcPOU b/TcUnit/TcUnit/POUs/FB_Test.TcPOU index 96cf10e..b2322a6 100644 --- a/TcUnit/TcUnit/POUs/FB_Test.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_Test.TcPOU @@ -1,5 +1,5 @@  - + @@ -36,6 +39,12 @@ END_VAR]]> + + + + + + @@ -104,9 +113,13 @@ END_IF]]> - + - + @@ -134,6 +147,19 @@ METHOD INTERNAL SetSkipped]]> + + + + + + - + GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite THEN NumberOfTestsToAnalyse := GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite; @@ -79,6 +83,10 @@ IF StoringTestSuiteResultNumber <= GVL_TcUnit.NumberOfInitializedTestSuites AND (* Store number of assertions made *) TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].NumberOfAsserts := TestToBeStored.GetNumberOfAssertions(); + + (* Store the duration of the test *) + TestSuiteResults.TestSuiteResults[StoringTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].Duration := + TestToBeStored.GetDuration(); END_FOR IF StoringTestSuiteResultNumber = GVL_TcUnit.NumberOfInitializedTestSuites THEN @@ -98,6 +106,7 @@ IF GVL_TcUnit.NumberOfInitializedTestSuites = 0 AND (NOT StoredGeneralTestResult ELSIF StoringTestSuiteResultNumber = GVL_TcUnit.NumberOfInitializedTestSuites AND_THEN GVL_TcUnit.TestSuiteAddresses[StoringTestSuiteResultNumber]^.AreAllTestsFinished() AND StoredTestSuiteResults AND (NOT StoredGeneralTestResults) THEN TestSuiteResults.NumberOfTestSuites := GVL_TcUnit.NumberOfInitializedTestSuites; + TestSuiteResults.Duration := GVL_TcUnit.Duration; FOR GeneralTestResultsTestSuitesCounter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO TestSuiteResults.NumberOfTestCases := TestSuiteResults.NumberOfTestCases + TestSuiteResults.TestSuiteResults[GeneralTestResultsTestSuitesCounter].NumberOfTests; TestSuiteResults.NumberOfSuccessfulTestCases := TestSuiteResults.NumberOfSuccessfulTestCases + diff --git a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU index 9211c64..1534bb3 100644 --- a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU @@ -1,5 +1,5 @@  - + - +END_IF + +AddTest REF= Tests[IteratorCounter];]]> @@ -179,7 +187,7 @@ END_IF (* If we have been running at least one cycle and no tests are registered it means that this testsuite is empty and doesn't contain any test cases. In that case, ignore this testsuite. *) GetCurTaskIndex(); -IF NumberOfTests = 0 AND NOT TwinCAT_SystemInfoVarList._TaskInfo[GetCurTaskIndex.index].FirstCycle AND HasStartedRunning THEN +IF NumberOfTests = 0 AND NOT TwinCAT_SystemInfoVarList._TaskInfo[GetCurTaskIndex.index].FirstCycle AND GetHasStartedRunning() THEN AreAllTestsFinished := TRUE; END_IF]]> @@ -3651,10 +3659,16 @@ METHOD PRIVATE FindTestSuiteInstancePath : Tc2_System.T_MaxString]]> + + + + + + - + 0;]]> @@ -3798,7 +3812,7 @@ END_IF]]> - + StartedAt);]]> @@ -3837,6 +3851,7 @@ END_IF]]> METHOD INTERNAL SetTestFinished : BOOL; VAR_INPUT TestName : Tc2_System.T_MaxString; + FinishedAt : UDINT; END_VAR VAR IteratorCounter : UINT; @@ -3852,7 +3867,7 @@ END_IF IF NumberOfTests > 0 THEN FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO IF Tests[IteratorCounter].GetName() = TestName THEN - Tests[IteratorCounter].SetFinished(); + Tests[IteratorCounter].SetFinished(FinishedAt := FinishedAt); SetTestFinished := TRUE; RETURN; END_IF @@ -3861,5 +3876,15 @@ IF NumberOfTests > 0 THEN END_IF]]> + + + + timestamp); +Duration := Duration + UDINT_TO_LREAL(timestamp - StartedAt) * 0.1;]]> + + \ No newline at end of file diff --git a/TcUnit/TcUnit/POUs/FB_xUnitXmlPublisher.TcPOU b/TcUnit/TcUnit/POUs/FB_xUnitXmlPublisher.TcPOU index 80e1f4d..6fc879e 100644 --- a/TcUnit/TcUnit/POUs/FB_xUnitXmlPublisher.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_xUnitXmlPublisher.TcPOU @@ -1,5 +1,5 @@  - + *) @@ -111,12 +112,14 @@ IF PublishTrigger.Q THEN Xml.NewParameter('name', UnitTestResults.TestSuiteResults[CurrentSuiteNumber].name); Xml.NewParameter('tests', UINT_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].NumberOfTests)); Xml.NewParameter('failures', UINT_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].NumberOfFailedTests)); - + Xml.NewParameter('time', LREAL_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].Duration)); + FOR CurrentTestCount := 1 TO UnitTestResults.TestSuiteResults[CurrentSuiteNumber].NumberOfTests BY 1 DO (* *) Xml.NewTag('testcase'); Xml.NewParameter('name', UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].TestName); Xml.NewParameter('classname', UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].TestClassName); + Xml.NewParameter('time', LREAL_TO_STRING(UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].Duration)); IF UnitTestResults.TestSuiteResults[CurrentSuiteNumber].TestCaseResults[CurrentTestCount].TestIsFailed THEN Xml.NewParameter('status', TEST_STATUS_FAIL); diff --git a/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU index 3baa25e..68c4548 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU @@ -1,5 +1,5 @@  - + TestStartedAt); + Test.SetStartedAtIfNotSet(Timestamp := TestStartedAt); RETURN; END_IF END_FOR]]> diff --git a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU index 631c4b3..7119fba 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU @@ -1,14 +1,18 @@  - + - FinishedAt); + +// Grab the currently running test name TestName := GVL_TcUnit.CurrentTestNameBeingCalled; TEST_FINISHED := FALSE; @@ -18,7 +22,7 @@ TEST_FINISHED := FALSE; *) FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO IF GVL_TcUnit.TestSuiteAddresses[Counter] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN - GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := GVL_TcUnit.CurrentTestNameBeingCalled); + GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := GVL_TcUnit.CurrentTestNameBeingCalled, FinishedAt := FinishedAt); GVL_TcUnit.TestSuiteAddresses[Counter]^.CalculateAndSetNumberOfAssertsForTest(TestName := GVL_TcUnit.CurrentTestNameBeingCalled); GVL_TcUnit.CurrentTestIsFinished := TRUE; TEST_FINISHED := TRUE; diff --git a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU index 5247dd8..e7da216 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU @@ -1,5 +1,5 @@  - + - FinishedAt); + +(* Find the test suite and: 1. Set the test in that test suite as finished 2. Calculate and set the number of asserts made for that test *) FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO IF GVL_TcUnit.TestSuiteAddresses[Counter] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN - FoundTestName := GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := TestName); + FoundTestName := GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := TestName, FinishedAt := FinishedAt); IF NOT FoundTestName THEN IF FailedLookupCounter < MaxNumberOfNonExistentTestNamesFailedLookups THEN GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_ERROR, diff --git a/TcUnit/TcUnit/TcUnit.plcproj b/TcUnit/TcUnit/TcUnit.plcproj index 63d40fb..17f125f 100644 --- a/TcUnit/TcUnit/TcUnit.plcproj +++ b/TcUnit/TcUnit/TcUnit.plcproj @@ -15,7 +15,7 @@ {9ba5f403-6725-42f3-958a-e49cc23e0e00} {d4c50e9b-48cc-4451-9f8a-44fa2a49ee45} false - true + false TcUnit TcUnit TwinCAT unit testing framework. @@ -32,7 +32,7 @@ Documentation and examples are available at www.tcunit.org www.tcunit.org Jakob Sagatowski and contributors - 1.2.0.0 + 1.2.0.1 diff --git a/TcUnit/TcUnit/Version/Global_Version.TcGVL b/TcUnit/TcUnit/Version/Global_Version.TcGVL index acbed66..2d40f75 100644 --- a/TcUnit/TcUnit/Version/Global_Version.TcGVL +++ b/TcUnit/TcUnit/Version/Global_Version.TcGVL @@ -1,5 +1,5 @@  - + From 990dad20e6a4fcb84c0e06746e7f9518a4c5363d Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Tue, 11 Jan 2022 14:11:21 +0100 Subject: [PATCH 02/12] refactor: changes for 4022.29 --- TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT | 2 +- TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT | 2 +- TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT | 2 +- TcUnit/TcUnit/GVLs/GVL_Param_TcUnit.TcGVL | 2 +- TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL | 2 +- TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU | 2 +- TcUnit/TcUnit/POUs/FB_Test.TcPOU | 2 +- TcUnit/TcUnit/POUs/FB_TestResults.TcPOU | 2 +- TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU | 2 +- TcUnit/TcUnit/POUs/FB_xUnitXmlPublisher.TcPOU | 2 +- TcUnit/TcUnit/POUs/Functions/TEST.TcPOU | 2 +- .../TcUnit/POUs/Functions/TEST_FINISHED.TcPOU | 2 +- .../POUs/Functions/TEST_FINISHED_NAMED.TcPOU | 29 +------------------ TcUnit/TcUnit/Version/Global_Version.TcGVL | 2 +- 14 files changed, 14 insertions(+), 41 deletions(-) diff --git a/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT b/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT index 63e369f..f022af4 100644 --- a/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT +++ b/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT @@ -1,5 +1,5 @@  - + - + - + - + - + - + - + - + - + - + - + - + - + FinishedAt); - (* Find the test suite and: - 1. Set the test in that test suite as finished - 2. Calculate and set the number of asserts made for that test - *) FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO - IF GVL_TcUnit.TestSuiteAddresses[Counter] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN - FoundTestName := GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := TestName, FinishedAt := FinishedAt); - IF NOT FoundTestName THEN - IF FailedLookupCounter < MaxNumberOfNonExistentTestNamesFailedLookups THEN - GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_ERROR, - MsgFmtStr := 'Failed to find test $'%s$'', - StrArg := TestName); - FailedLookupCounter := FailedLookupCounter + 1; - (* Abort TcUnit *) - GVL_TcUnit.TcUnitRunner.AbortRunningTestSuiteTests(); - ELSIF NOT AlreadyPrintedFinalWarning THEN - GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_ERROR, - MsgFmtStr := 'Excess failed attempts to mark test finished, failed. Further warnings will be suppressed', - StrArg := TestName); - AlreadyPrintedFinalWarning := TRUE; - END_IF - ELSE - GVL_TcUnit.TestSuiteAddresses[Counter]^.CalculateAndSetNumberOfAssertsForTest(TestName := TestName); - GVL_TcUnit.CurrentTestIsFinished := TRUE; - END_IF - RETURN; - END_IF - END_FOR]]> diff --git a/TcUnit/TcUnit/Version/Global_Version.TcGVL b/TcUnit/TcUnit/Version/Global_Version.TcGVL index 1b87bef..b9e265d 100644 --- a/TcUnit/TcUnit/Version/Global_Version.TcGVL +++ b/TcUnit/TcUnit/Version/Global_Version.TcGVL @@ -1,5 +1,5 @@  - + Date: Tue, 11 Jan 2022 16:11:06 +0100 Subject: [PATCH 03/12] feat: added duration to ADSLOGSTR output --- .../TcUnit/POUs/FB_AdsTestResultLogger.TcPOU | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/TcUnit/TcUnit/POUs/FB_AdsTestResultLogger.TcPOU b/TcUnit/TcUnit/POUs/FB_AdsTestResultLogger.TcPOU index d3837df..4766631 100644 --- a/TcUnit/TcUnit/POUs/FB_AdsTestResultLogger.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_AdsTestResultLogger.TcPOU @@ -74,7 +74,11 @@ IF PrintingTestSuiteResultNumber <= GVL_TcUnit.NumberOfInitializedTestSuites AND STR2 := ', number of failed tests='); StringToPrint := Tc2_Standard.CONCAT(STR1 := StringToPrint, STR2 := UINT_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].NumberOfFailedTests)); - + StringToPrint := Tc2_Standard.CONCAT(STR1 := StringToPrint, + STR2 := ', duration='); + StringToPrint := Tc2_Standard.CONCAT(STR1 := StringToPrint, + STR2 := LREAL_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].Duration)); + GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_HINT, MsgFmtStr := StringToPrint, StrArg := ''); @@ -96,7 +100,11 @@ IF PrintingTestSuiteResultNumber <= GVL_TcUnit.NumberOfInitializedTestSuites AND GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_HINT, MsgFmtStr := '| Test class name=%s', StrArg := TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestClassName); - + (* Print test duration *) + GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_HINT, + MsgFmtStr := '| Test duration=%s', + StrArg := LREAL_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].Duration)); + (* Print test result/status (SUCCESS, FAILED, SKIPPED) + number of assertions made *) IF TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].TestIsFailed THEN StringToPrint := Tc2_Standard.CONCAT(STR1 := '| Test status=', STR2 := TEST_STATUS_FAIL); @@ -109,6 +117,9 @@ IF PrintingTestSuiteResultNumber <= GVL_TcUnit.NumberOfInitializedTestSuites AND StringToPrint := Tc2_Standard.CONCAT(STR1 := StringToPrint, STR2 := ', number of asserts='); StringToPrint := Tc2_Standard.CONCAT(STR1 := StringToPrint, STR2 := UINT_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].NumberOfAsserts)); + StringToPrint := Tc2_Standard.CONCAT(STR1 := StringToPrint, STR2 := ', duration='); + StringToPrint := Tc2_Standard.CONCAT(STR1 := StringToPrint, STR2 := + LREAL_TO_STRING(TcUnitTestResults.TestSuiteResults[PrintingTestSuiteResultNumber].TestCaseResults[TestsInTestSuiteCounter].Duration)); GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_HINT, MsgFmtStr := StringToPrint, StrArg := ''); @@ -168,6 +179,9 @@ IF (GVL_TcUnit.NumberOfInitializedTestSuites = 0 OR PrintingTestSuiteResultNumbe GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_ERROR, MsgFmtStr := '| Failed tests: %s', StrArg := UINT_TO_STRING(TcUnitTestResults.NumberOfFailedTestCases)); + GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_ERROR, + MsgFmtStr := '| Duration: %s', + StrArg := LREAL_TO_STRING(TcUnitTestResults.Duration)); GVL_TcUnit.AdsMessageQueue.WriteLog(MsgCtrlMask := Tc2_System.ADSLOG_MSGTYPE_ERROR, MsgFmtStr := '%s', StrArg := '| ======================================'); From 8f735b382147666113194c0076d7e956021d45ac Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Tue, 11 Jan 2022 17:00:54 +0100 Subject: [PATCH 04/12] fix: use seconds instead of microseconds for durations --- TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT | 2 +- TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL | 2 +- TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU | 4 ++-- TcUnit/TcUnit/POUs/FB_Test.TcPOU | 2 +- TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT b/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT index 13d5f4c..cec09d8 100644 --- a/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT +++ b/TcUnit/TcUnit/DUTs/ST_TestSuiteResults.TcDUT @@ -8,7 +8,7 @@ STRUCT NumberOfTestCases : UINT; // The total number of test cases (for all test suites) NumberOfSuccessfulTestCases : UINT; // The total number of test cases that had all ASSERTS successful NumberOfFailedTestCases : UINT; // The total number of test cases that had at least one ASSERT failed - Duration : LREAL; // Duration it took for all test suites to finish + Duration : LREAL; // Duration it took for all test suites to finish, in seconds (* Test results for each individiual test suite *) TestSuiteResults : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestSuites] OF ST_TestSuiteResult; diff --git a/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL b/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL index 42e7f54..81f1df3 100644 --- a/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL +++ b/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL @@ -22,7 +22,7 @@ VAR_GLOBAL (* Timestamp for the first entry into on of the Run methods *) StartedAt : UDINT; - (* Duration it took for a complete run *) + (* Duration it took for a complete run, in seconds *) Duration : LREAL; (* Whether or not the current test being called has finished running *) diff --git a/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU b/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU index 2fbb128..24c2489 100644 --- a/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU @@ -87,7 +87,7 @@ AllTestSuitesFinishedTrigger(CLK := AllTestSuitesFinished); IF AllTestSuitesFinishedTrigger.Q THEN GVL_TcUnit.GetCpuAccount(cpuAccountDW => GVL_TcUnit.Duration); - GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) * 0.1;; + GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) / 10000000; // seconds END_IF (* Store test suite results continuously *) @@ -166,7 +166,7 @@ AllTestSuitesFinishedTrigger(CLK := AllTestSuitesFinished); IF AllTestSuitesFinishedTrigger.Q THEN GVL_TcUnit.GetCpuAccount(cpuAccountDW => GVL_TcUnit.Duration); - GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) * 0.1; + GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) / 10000000; // seconds END_IF (* Store test suite results continuously *) diff --git a/TcUnit/TcUnit/POUs/FB_Test.TcPOU b/TcUnit/TcUnit/POUs/FB_Test.TcPOU index b460c1e..7cb340b 100644 --- a/TcUnit/TcUnit/POUs/FB_Test.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_Test.TcPOU @@ -119,7 +119,7 @@ VAR_INPUT END_VAR]]> +Duration := UDINT_TO_LREAL(FinishedAt - StartedAt) / 10000000; // seconds]]> diff --git a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU index dc0e68f..c00c165 100644 --- a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU @@ -3847,7 +3847,7 @@ VAR END_VAR]]> timestamp); -Duration := Duration + UDINT_TO_LREAL(timestamp - StartedAt) * 0.1;]]> +Duration := Duration + UDINT_TO_LREAL(timestamp - StartedAt) / 10000000; // seconds]]> From 36fbde3488cbb5c5b745db868a6573176cd0521e Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Tue, 11 Jan 2022 17:01:28 +0100 Subject: [PATCH 05/12] fix: handle invalid reference (disabled tests) --- TcUnit/TcUnit/POUs/Functions/TEST.TcPOU | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU index be7b08f..3993275 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU @@ -27,8 +27,10 @@ FOR CounterTestSuiteAddress := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY IF GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN Test REF= GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress]^.AddTest(TestName := TestName, IsTestOrdered := FALSE); GVL_TcUnit.CurrentTestIsFinished := GVL_TcUnit.TestSuiteAddresses[CounterTestSuiteAddress]^.IsTestFinished(TestName := TestName); - GVL_TcUnit.GetCpuAccount(cpuAccountDW => TestStartedAt); - Test.SetStartedAtIfNotSet(Timestamp := TestStartedAt); + IF __ISVALIDREF(Test) THEN + GVL_TcUnit.GetCpuAccount(cpuAccountDW => TestStartedAt); + Test.SetStartedAtIfNotSet(Timestamp := TestStartedAt); + END_IF RETURN; END_IF END_FOR]]> From 2c5a5ff3b7be364cef390f225ddebd0b7e98a1a4 Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Tue, 11 Jan 2022 17:30:22 +0100 Subject: [PATCH 06/12] fix: reverted xti to 4022.32 format --- TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU | 2 +- .../POUs/Functions/TEST_FINISHED_NAMED.TcPOU | 20 +------------------ TcUnit/_Config/PLC/TcUnit.xti | 10 ++-------- 3 files changed, 4 insertions(+), 28 deletions(-) diff --git a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU index c00c165..28fbe42 100644 --- a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU @@ -3832,7 +3832,7 @@ END_VAR]]> NumberOfTestsToAnalyse := GetNumberOfTestsToAnalyse(); FOR IteratorCounter := 1 TO NumberOfTestsToAnalyse BY 1 DO IF Tests[IteratorCounter].GetName() = TestName THEN - Tests[IteratorCounter].SetFinished(FinishedAt := FinishedAt); + Tests[IteratorCounter].SetFinished(FinishedAt := FinishedAt); SetTestFinished := TRUE; RETURN; END_IF diff --git a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU index a484f06..cc108f9 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU @@ -2,39 +2,22 @@ FinishedAt); 1. Set the test in that test suite as finished 2. Calculate and set the number of asserts made for that test *) - FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO IF GVL_TcUnit.TestSuiteAddresses[Counter] = GVL_TcUnit.CurrentTestSuiteBeingCalled THEN FoundTestName := GVL_TcUnit.TestSuiteAddresses[Counter]^.SetTestFinished(TestName := TestName, FinishedAt := FinishedAt); @@ -71,4 +53,4 @@ FOR Counter := 1 TO GVL_TcUnit.NumberOfInitializedTestSuites BY 1 DO END_FOR]]> - \ No newline at end of file + diff --git a/TcUnit/_Config/PLC/TcUnit.xti b/TcUnit/_Config/PLC/TcUnit.xti index aec400d..d1f2e81 100644 --- a/TcUnit/_Config/PLC/TcUnit.xti +++ b/TcUnit/_Config/PLC/TcUnit.xti @@ -1,15 +1,9 @@ - - + + TcUnit Instance {08500001-0000-0000-F000-000000000064} - - - 1 - Default - - From ce7b58235a0674edc257f71d7dcbb7002e9824ec Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Wed, 26 Jan 2022 11:05:09 +0100 Subject: [PATCH 07/12] test: added tests to check if durations are written correctly into the twincat errorlist --- .../FB_ExtendedTestInformation.cs | 6 ++++++ .../FB_TestNumberOfAssertionsCalculation.cs | 10 +++++----- .../TcUnit-Verifier/Program.cs | 13 ++++++++++++- .../TcUnit-Verifier/TestFunctionBlockAssert.cs | 17 +++++++++++++++-- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_ExtendedTestInformation.cs b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_ExtendedTestInformation.cs index 8208b4f..7f9c7b8 100644 --- a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_ExtendedTestInformation.cs +++ b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_ExtendedTestInformation.cs @@ -9,6 +9,7 @@ public FB_ExtendedTestInformation(IEnumerable errors, string te { Check_TestSuite_Statistics(); AssertTestClassName(); + AssertTestDuration(); Test_BOOL_AssertFailed(); Test_BOOL_AssertSuccess(); Test_BYTE_TwoFailedAsserts(); @@ -36,6 +37,11 @@ private void AssertTestClassName() AssertMessageCount(className, 5, EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); } + private void AssertTestDuration() + { + string duration = "Test duration=%f"; + AssertMessageCount(duration, 260, EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); + } private void Test_BOOL_AssertFailed() { diff --git a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_TestNumberOfAssertionsCalculation.cs b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_TestNumberOfAssertionsCalculation.cs index 72a2649..b5b6f5f 100644 --- a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_TestNumberOfAssertionsCalculation.cs +++ b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/FB_TestNumberOfAssertionsCalculation.cs @@ -16,27 +16,27 @@ public FB_TestNumberOfAssertionsCalculation(IEnumerable errors, private void TestMixed33SuccessulAnd9FailedAssertions() { - AssertContainsMessage("| Test status=FAIL, number of asserts=42", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); + AssertContainsMessage("| Test status=FAIL, number of asserts=42, duration=%f", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); } private void TestWith43SuccessfulAssertions() { - AssertContainsMessage("| Test status=PASS, number of asserts=43", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); + AssertContainsMessage("| Test status=PASS, number of asserts=43, duration=%f", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); } private void TestWith44FailedAssertions() { - AssertContainsMessage("| Test status=FAIL, number of asserts=44", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); + AssertContainsMessage("| Test status=FAIL, number of asserts=44, duration=%f", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); } private void TestWith45SuccessfulArrayAssertions() { - AssertContainsMessage("| Test status=PASS, number of asserts=45", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); + AssertContainsMessage("| Test status=PASS, number of asserts=45, duration=%f", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); } private void TestWith46FailedArrayAssertions() { - AssertContainsMessage("| Test status=FAIL, number of asserts=46", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); + AssertContainsMessage("| Test status=FAIL, number of asserts=46, duration=%f", EnvDTE80.vsBuildErrorLevel.vsBuildErrorLevelLow); } } diff --git a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/Program.cs b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/Program.cs index 8e231bd..a492134 100644 --- a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/Program.cs +++ b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/Program.cs @@ -7,6 +7,7 @@ using TCatSysManagerLib; using System.Threading; using EnvDTE80; +using System.Text.RegularExpressions; namespace TcUnit.Verifier { @@ -108,8 +109,12 @@ static void Main(string[] args) bool numberOfTestsLineFound = false; bool numberOfSuccesfulTestsLineFound = false; bool numberOfFailedTestsLineFound = false; + bool durationLineFound = false; bool testsFinishedRunningLastLineFound = false; int numberOfFailedTests = 0; + float duration; + + const string durationStr = "| Duration:"; log.Info("Waiting for TcUnit-Verifier_TwinCAT to finish running tests..."); @@ -139,6 +144,11 @@ static void Main(string[] args) // Grab the number of failed tests so we can validate it during the assertion phase numberOfFailedTests = int.Parse(error.Description.Split().Last()); } + if (error.Description.Contains(durationStr)) + { + int durationIndex = error.Description.IndexOf(durationStr); + durationLineFound = float.TryParse(error.Description.Substring(durationIndex + durationStr.Length), out duration); + } if (error.Description.Contains("| ======================================")) testsFinishedRunningLastLineFound = true; } @@ -148,7 +158,8 @@ static void Main(string[] args) && numberOfTestSuitesLineFound && numberOfTestsLineFound && numberOfSuccesfulTestsLineFound - && numberOfFailedTestsLineFound + && numberOfFailedTestsLineFound + && durationLineFound && testsFinishedRunningLastLineFound ) break; diff --git a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/TestFunctionBlockAssert.cs b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/TestFunctionBlockAssert.cs index 570b305..20e0710 100644 --- a/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/TestFunctionBlockAssert.cs +++ b/TcUnit-Verifier/TcUnit-Verifier_DotNet/TcUnit-Verifier/TestFunctionBlockAssert.cs @@ -2,6 +2,7 @@ using log4net; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; namespace TcUnit.Verifier { @@ -46,12 +47,24 @@ protected string CreateFailedTestMessageNoAssertionMessage(string method, string private bool AreErrorItemsContainingTestMessage(string testMessage, vsBuildErrorLevel errorLevel) { - return _errors.Any(e => (e.Description.Contains(testMessage.ToUpper())) && e.ErrorLevel.Equals(errorLevel)); + // no regex needed, do a fast check + if(!testMessage.Contains("%f")) + return _errors.Any(e => e.Description.Contains(testMessage.ToUpper()) && e.ErrorLevel.Equals(errorLevel)); + + // convert number placeholders (%f) to a regex that matches floating point values + testMessage = @".*?" + Regex.Escape(testMessage).Replace("%f", @"[+-]?(\d+([.]\d*)?([eE][+-]?\d+)?|[.]\d+([eE][+-]?\d+)?)") + @".*?"; + return _errors.Any(e => Regex.Match(e.Description, testMessage, RegexOptions.IgnoreCase).Success && e.ErrorLevel.Equals(errorLevel)); } private int CountErrorItemsContainingTestMessage(string testMessage, vsBuildErrorLevel errorLevel) { - return _errors.Count(s => (s.Description.Contains(testMessage.ToUpper())) && s.ErrorLevel.Equals(errorLevel)); + // no regex needed, do a fast check + if (!testMessage.Contains("%f")) + return _errors.Count(e => e.Description.Contains(testMessage.ToUpper()) && e.ErrorLevel.Equals(errorLevel)); + + // convert number placeholders (%f) to a regex that matches floating point values + testMessage = @".*?" + Regex.Escape(testMessage).Replace("%f", @"[+-]?(\d+([.]\d*)?([eE][+-]?\d+)?|[.]\d+([eE][+-]?\d+)?)") + @".*?"; + return _errors.Count(e => Regex.Match(e.Description, testMessage, RegexOptions.IgnoreCase).Success && e.ErrorLevel.Equals(errorLevel)); } protected void AssertMessageCount(string message, int messageCount, vsBuildErrorLevel errorLevel) From cfceafd438b197a0f0f904c42a6265abecc63a7d Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Mon, 18 Apr 2022 19:55:10 +0200 Subject: [PATCH 08/12] fix: Picked changed from AddTest. Directly using IteratorCounter some times does not work --- TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU index 28fbe42..84c9bcd 100644 --- a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU @@ -140,7 +140,7 @@ IF IgnoreCurrentTestCase THEN RETURN; END_IF -AddTest REF= Tests[IteratorCounter];]]> +AddTest REF= GetTestByName(TrimmedTestName);]]> @@ -3731,6 +3731,26 @@ GetNumberOfSkippedTests := SkippedTestsCount;]]> + + + + + + Date: Mon, 18 Apr 2022 20:15:53 +0200 Subject: [PATCH 09/12] fix: added comment --- TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT b/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT index f022af4..ecabb4f 100644 --- a/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT +++ b/TcUnit/TcUnit/DUTs/ST_TestCaseResult.TcDUT @@ -10,7 +10,7 @@ STRUCT FailureMessage : Tc2_System.T_MaxString; FailureType : E_AssertionType; NumberOfAsserts : UINT; - Duration : LREAL; + Duration : LREAL; // in seconds END_STRUCT END_TYPE]]> From f3c0eac01d72fe061227876c0cbd55a5983b883e Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Mon, 18 Apr 2022 20:22:09 +0200 Subject: [PATCH 10/12] fixup --- TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT b/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT index 05e0c1b..db0168b 100644 --- a/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT +++ b/TcUnit/TcUnit/DUTs/ST_TestSuiteResult.TcDUT @@ -7,7 +7,7 @@ STRUCT Identity : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestSuites); // Should be 0..GVL_Param_TcUnit.MaxNumberOfTestSuites-1 but gives unknown compiler error NumberOfTests : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite); NumberOfFailedTests : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite); - Duration : LREAL; + Duration : LREAL; // in seconds TestCaseResults : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF ST_TestCaseResult; END_STRUCT END_TYPE]]> From 7ab4b216db95bac5f50e95665a3e271e77774f27 Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Mon, 18 Apr 2022 20:23:23 +0200 Subject: [PATCH 11/12] style: then should be in same line as if in TcUnit --- TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL | 5 +++++ TcUnit/TcUnit/POUs/FB_Test.TcPOU | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL b/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL index 81f1df3..6e68689 100644 --- a/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL +++ b/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL @@ -45,6 +45,11 @@ VAR_GLOBAL (* Buffered ADS message queue for output to the error list *) AdsMessageQueue : FB_AdsLogStringMessageFifoQueue; +END_VAR +VAR_GLOBAL CONSTANT + (* Multiply a value that is given in 100ns units by this value to + convert the value to seconds *) + HundredNanosecondToSecond : LREAL := 1.0 / 10000000.0; END_VAR]]> \ No newline at end of file diff --git a/TcUnit/TcUnit/POUs/FB_Test.TcPOU b/TcUnit/TcUnit/POUs/FB_Test.TcPOU index 7cb340b..a00a4d9 100644 --- a/TcUnit/TcUnit/POUs/FB_Test.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_Test.TcPOU @@ -150,12 +150,11 @@ METHOD INTERNAL SetSkipped]]> - From bb917b6f7d4ec5bbd276b344ae2c2d6a61d3b171 Mon Sep 17 00:00:00 2001 From: Stefan Besler Date: Mon, 18 Apr 2022 20:57:17 +0200 Subject: [PATCH 12/12] fix: changed comments for timestamp feat: use getcpucounter instead of getcpuaccount refactor: use a function for getting the cpucounter instead of directly calling the function block --- TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL | 9 ++++---- TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU | 16 +++++--------- TcUnit/TcUnit/POUs/FB_Test.TcPOU | 12 +++++----- TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU | 22 ++++++++----------- .../Functions/F_GetCpuCounterAs64bit.TcPOU | 18 +++++++++++++++ TcUnit/TcUnit/POUs/Functions/TEST.TcPOU | 4 +--- .../TcUnit/POUs/Functions/TEST_FINISHED.TcPOU | 6 ++--- .../POUs/Functions/TEST_FINISHED_NAMED.TcPOU | 4 ++-- TcUnit/TcUnit/TcUnit.plcproj | 3 +++ 9 files changed, 52 insertions(+), 42 deletions(-) create mode 100644 TcUnit/TcUnit/POUs/Functions/F_GetCpuCounterAs64bit.TcPOU diff --git a/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL b/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL index 6e68689..b853da2 100644 --- a/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL +++ b/TcUnit/TcUnit/GVLs/GVL_TcUnit.TcGVL @@ -15,12 +15,11 @@ VAR_GLOBAL (* Current name of test being called *) CurrentTestNameBeingCalled : Tc2_System.T_MaxString; - (* Timestamp for the latest start of the current test *) - CurrentTestNameStartedAt : UDINT; - GetCpuAccount : Tc2_System.GETCPUACCOUNT; + (* Used to get the current cpu cycle counter to calculate the duration of tests and test suits, respectively *) + GetCpuCounter : Tc2_System.GETCPUCOUNTER; - (* Timestamp for the first entry into on of the Run methods *) - StartedAt : UDINT; + (* Stores the CPU cycle count with 100ns precision since the first entry into one of the Run methods (RUN, RUN_IN_SEQUENCE) *) + StartedAt : LWORD; (* Duration it took for a complete run, in seconds *) Duration : LREAL; diff --git a/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU b/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU index 24c2489..57b0107 100644 --- a/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_TcUnitRunner.TcPOU @@ -50,9 +50,8 @@ VAR NumberOfTestSuitesFinished : UINT := 0; END_VAR]]> - GVL_TcUnit.StartedAt); + GVL_TcUnit.Duration); - GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) / 10000000; // seconds + GVL_TcUnit.Duration := LWORD_TO_LREAL(F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter) - GVL_TcUnit.StartedAt) * GVL_TcUnit.HundredNanosecondToSecond; // seconds END_IF (* Store test suite results continuously *) @@ -124,9 +122,8 @@ VAR_INST TimerBetweenExecutionOfTestSuites : Tc2_Standard.TOF; END_VAR]]> - GVL_TcUnit.StartedAt); + GVL_TcUnit.Duration); - GVL_TcUnit.Duration := (GVL_TcUnit.Duration - GVL_TcUnit.StartedAt) / 10000000; // seconds + GVL_TcUnit.Duration := LWORD_TO_LREAL(F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter) - GVL_TcUnit.StartedAt) * GVL_TcUnit.HundredNanosecondToSecond; // seconds END_IF (* Store test suite results continuously *) diff --git a/TcUnit/TcUnit/POUs/FB_Test.TcPOU b/TcUnit/TcUnit/POUs/FB_Test.TcPOU index a00a4d9..6077def 100644 --- a/TcUnit/TcUnit/POUs/FB_Test.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_Test.TcPOU @@ -21,8 +21,8 @@ VAR AssertionMessage : Tc2_System.T_MaxString; // Assertion message for the first assertion in this test AssertionType : E_AssertionType; // Assertion type for the first assertion in this test - StartedAt : UDINT; // Temporary variable to calculate the actual duration of the test - Duration : LREAL; // Duration of the test in microseconds + StartedAt : LWORD; // Temporary variable to calculate the actual duration of the test, the value holds the cpu cycle counter when a test is started in 100ns precision + Duration : LREAL; // Duration of the test in seconds END_VAR]]> @@ -115,11 +115,11 @@ END_IF]]> +Duration := LWORD_TO_LREAL(FinishedAt - StartedAt) * GVL_TcUnit.HundredNanosecondToSecond; // seconds]]> @@ -148,9 +148,9 @@ METHOD INTERNAL SetSkipped]]> - diff --git a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU index 84c9bcd..626fda5 100644 --- a/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU +++ b/TcUnit/TcUnit/POUs/FB_TestSuite.TcPOU @@ -19,7 +19,6 @@ VAR defined already. The definition of a test that is defined already is that we call on it with the same name twice in the same cycle *) GetCurrentTaskIndex : Tc2_System.GETCURTASKINDEX; - GetCpuAccount : Tc2_System.GETCPUACCOUNT; NumberOfTests : UINT(0..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite) := 0; Tests : ARRAY[1..GVL_Param_TcUnit.MaxNumberOfTestsForEachTestSuite] OF FB_Test; @@ -38,12 +37,12 @@ VAR AdsAssertMessageFormatter : FB_AdsAssertMessageFormatter; AssertMessageFormatter : I_AssertMessageFormatter := AdsAssertMessageFormatter; - (* Timestamp when the testsuite was started, this also is an indication whether this - test suite has started running its tests *) - StartedAt : UDINT; + (* Stores the CPU cycle count with 100ns precision. It also is an indication whether this + test suite has started running its tests*) + StartedAt : LWORD; (* Duration it took to run all tests in this testsuite - including the overhead from TcUnit - in microseconds *) + in seconds *) Duration : LREAL; (* Number of ordered tests (created by TEST_ORDERED()) that this test suite contains *) @@ -3808,7 +3807,8 @@ END_FOR]]> - StartedAt);]]> + @@ -3841,7 +3841,7 @@ END_FOR]]> METHOD INTERNAL SetTestFinished : BOOL; VAR_INPUT TestName : Tc2_System.T_MaxString; - FinishedAt : UDINT; + FinishedAt : LWORD; END_VAR VAR IteratorCounter : UINT; @@ -3861,13 +3861,9 @@ SetTestFinished := FALSE;]]> - + - timestamp); -Duration := Duration + UDINT_TO_LREAL(timestamp - StartedAt) / 10000000; // seconds]]> + diff --git a/TcUnit/TcUnit/POUs/Functions/F_GetCpuCounterAs64bit.TcPOU b/TcUnit/TcUnit/POUs/Functions/F_GetCpuCounterAs64bit.TcPOU new file mode 100644 index 0000000..002f022 --- /dev/null +++ b/TcUnit/TcUnit/POUs/Functions/F_GetCpuCounterAs64bit.TcPOU @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU index 3993275..ce1fc23 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST.TcPOU @@ -9,7 +9,6 @@ END_VAR VAR CounterTestSuiteAddress : UINT; Test : REFERENCE TO FB_Test; - TestStartedAt : UDINT; END_VAR]]> TestStartedAt); - Test.SetStartedAtIfNotSet(Timestamp := TestStartedAt); + Test.SetStartedAtIfNotSet(Timestamp := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter)); END_IF RETURN; END_IF diff --git a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU index d31217f..d4c5245 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED.TcPOU @@ -1,16 +1,16 @@  - + FinishedAt); +FinishedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter); // Grab the currently running test name TestName := GVL_TcUnit.CurrentTestNameBeingCalled; diff --git a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU index cc108f9..9970ef2 100644 --- a/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU +++ b/TcUnit/TcUnit/POUs/Functions/TEST_FINISHED_NAMED.TcPOU @@ -10,7 +10,7 @@ END_VAR VAR Counter : UINT := 0; FoundTestName : BOOL := FALSE; - FinishedAt : UDINT; + FinishedAt : LWORD; // cpu cycle counter in 100ns precision END_VAR VAR_STAT FailedLookupCounter : UINT := 0; @@ -21,7 +21,7 @@ VAR CONSTANT END_VAR]]> FinishedAt); +FinishedAt := F_GetCpuCounterAs64bit(GVL_TcUnit.GetCpuCounter); (* Find the test suite and: 1. Set the test in that test suite as finished diff --git a/TcUnit/TcUnit/TcUnit.plcproj b/TcUnit/TcUnit/TcUnit.plcproj index 012d03c..c2a16de 100644 --- a/TcUnit/TcUnit/TcUnit.plcproj +++ b/TcUnit/TcUnit/TcUnit.plcproj @@ -148,6 +148,9 @@ Documentation and examples are available at www.tcunit.org Code + + Code + Code