I seem to now have a working Unit Test solution for B4A for anybody interested.
The test code and test runner are included in the project to be tested, but can be excluded from compilation using a conditional directive - I use '#if UNIT_TESTS', with 'UNIT_TESTS' defined when required in a Build Configuration (B4A menu option: Project | Build Configurations).
You can define any number of test classes and methods like so:
The attached Test Runner (class CTestRunner) will discover all Classes with names beginning with a specified prefix, e.g. 'CTest', and run all Subs with names beginning with a specified prefix, e.g. 'Test_'.
In Starter I Have:
In my 'Main' Activity I have:
and later, to run the unit tests, log a test report, and show an Html version of the results via a WebView:
and beneath the Basic subs:
Note that one Java method in CTestRunner ('GetClassNamesInPackage') uses a deprecated approach, and that also the whole approach may break with any new version of B4A (!).
IMPORTANT - CTestRunner as attached only works with the Rapid Debugger. To use it with the Legacy Debugger, set the constant 'LEGACY_DEBUGGER' on line 357 to 'true'. I'll true to make this automatic soon.
Hope this helps someone,
Jim
The test code and test runner are included in the project to be tested, but can be excluded from compilation using a conditional directive - I use '#if UNIT_TESTS', with 'UNIT_TESTS' defined when required in a Build Configuration (B4A menu option: Project | Build Configurations).
You can define any number of test classes and methods like so:
B4X:
' Class: CTest1
#if UNIT_TESTS
Sub Class_Globals
Private TR As CTestRunner
End Sub
Public Sub Initialize
TR = Starter.TestRunner
End Sub
public Sub Test_1
TR.AssertIsTrue(True)
TR.AssertIsTrue(1 = 1)
End Sub
public Sub Test_2
TR.AssertIsFalse(False)
TR.AssertIsFalse(1 = 0)
End Sub
public Sub Test_3
TR.AssertIntsAreEqual(2, 2)
End Sub
public Sub Test_4
TR.AssertIntsDiffer(2, 3)
End Sub
#else
Sub Class_Globals
End Sub
#End If
The attached Test Runner (class CTestRunner) will discover all Classes with names beginning with a specified prefix, e.g. 'CTest', and run all Subs with names beginning with a specified prefix, e.g. 'Test_'.
In Starter I Have:
B4X:
Sub Process_Globals
#if UNIT_TESTS
Dim TestRunner As CTestRunner
#end if
End Sub
In my 'Main' Activity I have:
B4X:
Sub Process_Globals
Private NativeMe As JavaObject
End Sub
Sub Activity_Create(FirstTime As Boolean)
If FirstTime Then
NativeMe.InitializeContext
#if UNIT_TESTS
Starter.TestRunner.Initialize(NativeMe)
#end if
End If
and later, to run the unit tests, log a test report, and show an Html version of the results via a WebView:
B4X:
#if UNIT_TESTS
Starter.TestRunner.Verbosity = 1
' Test all Classes beginning with 'ctest' / all Subs beginning with 'test'.
Starter.TestRunner.RunAll("ctest", "test")
Log(Starter.TestRunner.GetTextReport)
Starter.ShowHtmlText = Starter.TestRunner.GetHtmlReport
StartActivity(ShowHtml)
#End If
and beneath the Basic subs:
B4X:
#if JAVA
public String GetPackageCodePath()
{
return getPackageCodePath();
}
public Object GetProcessBA()
{
return processBA;
}
#End If
Note that one Java method in CTestRunner ('GetClassNamesInPackage') uses a deprecated approach, and that also the whole approach may break with any new version of B4A (!).
IMPORTANT - CTestRunner as attached only works with the Rapid Debugger. To use it with the Legacy Debugger, set the constant 'LEGACY_DEBUGGER' on line 357 to 'true'. I'll true to make this automatic soon.
Hope this helps someone,
Jim