Customizing ABLUnit so that the Consultingwerk AssertException is handled as "Failure"
In Unit Testing (unhandled) runtime errors and errors thrown from assertion methods to validate a test’s result typically have a different meaning – although they are technically speaking both errors that are thrown from the test (or the tested code) to the test runtime.
ABLUnit distinguishes between failures and errors. Failures are caused by errors thrown from the assertion methods and errors are remaining unhandled runtime exceptions. By default, ABLUnit does only consider errors thrown by the ABLUnit assertion methods a failure. Errors thrown by the Consultingwerk Assertion methods are seen as errors.
ABLUnit distinguishes this by the type of errors catched by the test runtime: Errors of type OpenEdge.Core.AssertionFailedError are handled as a failure and all other types of errors count into error.
The following simple unit test shows the difference in how ABLUnit visualizes errors thrown by the Consultingwerk assertion methods:
BLOCK-LEVEL ON ERROR UNDO, THROW. CLASS Test.SCL1274.TestClass: @Test. METHOD PUBLIC VOID TestOeAssertion (): OpenEdge.Core.Assert:Equals(1, 2) . END METHOD. @Test. METHOD PUBLIC VOID TestConsultingwerkAssertion (): Consultingwerk.Assertion.Assert:Equals(1, 2) . END METHOD. END CLASS.
Using the Include Files in Consultingwerk/Studio/AblUnit/11_6_0 it’s possible modify the ABLUnit classes so that the Consultingwerk AssertException is handled in the same way as the ABLUnit AssertFailedError:
Implementing the customization to ABLUnit
Due to the rather poor design of ABLUnit we cannot avoid modifying ABLUnit’s source code provided by Progress Software to achieve handling the two assertion related exceptions/error classes in the same way. We need to add code to the
- OpenEdge.ABLUnit.Reflection.ClassAnnotationInfo
- OpenEdge.ABLUnit.Reflection.ProcedureAnnotationInfo
classes. In the ClassAnnotationInfo there are in total three CATCH blocks affected and in ProcedureAnnotationInfo there is a single CATCH block. We have implemented the customization by inserting the two include files near the locations where the AssertionFailedError is handled:
- Consultingwerk/Studio/AblUnit/11_6_0/handle-consultingwerk-exception.i
- Consultingwerk/Studio/AblUnit/11_6_0/handle-consultingwerk-exception2.i
Attached to this document you’ll find the two modified classes based on OpenEdge 11.6 ADE source code. Based on our testing those classes work also with OpenEdge 11.6.1 and 11.6.2
When implementing this for a different version of ABLUnit, search the ABLUnit source code for “AssertFailedError” and add the first include file just before CATCH blocks for AssertFailedError and the second include file in CATCH blocks for Progress.Lang.Error just before the IF THEN ELSE block where the error’s type is inspected.
/* Mike Fechner, Consultingwerk Ltd. 27.05.2016 Handle Consultingwerk AssertException (and derived types like ABLUnit AssertFailedError */ {Consultingwerk/Studio/AblUnit/11_6_0/handle-consultingwerk-exception.i} CATCH err AS AssertionFailedError : testResult:TestResult = TestTestResult:StatusFailed. testResult:ErrorMessage = err:GetMessage(). testResult:TestName = testMethod:getTestName(). testResult:Error = err. END CATCH.
CATCH e AS Progress.Lang.Error : IF expectedException = "" THEN DO: /* Mike Fechner, Consultingwerk Ltd. 27.05.2016 Handle Consultingwerk AssertException (and derived types like ABLUnit AssertFailedError */ {Consultingwerk/Studio/AblUnit/11_6_0/handle-consultingwerk-exception2.i testResult testMethod} IF (e:GetClass():TypeName = "OpenEdge.Core.AssertionFailedError") THEN DO: testResult:TestResult = TestTestResult:StatusFailed. testResult:TestName = testMethod:getTestName(). testResult:Error = e. testResult:ErrorMessage = e:GetMessage(1). END. ELSE DO: testResult:TestResult = TestTestResult:StatusError. testResult:TestName = testMethod:getTestName(). testResult:Error = e. END. END. ELSE IF (ClassAnnotationInfo:IsTypeOf(e, GetExpectedErrorType(expectedException))) THEN DO: testResult:TestResult = TestTestResult:StatusPassed. testResult:TestName = testMethod:getTestName(). END. ELSE DO: testResult:TestResult = OpenEdge.ABLUnit.Results.TestTestResult:StatusFailed. testResult:TestName = testMethod:getTestName(). testResult:ErrorMessage = "Expecting:" + expectedException + " but found:" + e:GetClass():TypeName. testResult:Error = e. END. END CATCH.
Using the customized version of ABLUnit
In order to use the customized version of these two ABLUnit classes, they must be placed in a subdirectory OpenEdge.ABLUnit.Reflection underneath a directory that is in the PROPATH before the ablunit.pl library:
Attached Files