-
Notifications
You must be signed in to change notification settings - Fork 46
Using VBAUnit
As we could not find any tutorial on the Internet specific to VBA Unit, here is our try to pass our knowledge around.
VBA Unit is a framework for unit testing in VBA Projects, very much inspired by the famous JUnit written in and for Java. It is rather old and not maintained anywore, but it works and it is useful.
It consists in a variety of modules and class modules that just need to be imported in the workbook you are working in.
They are embedded by default in VBAToolKit.
- The unit tests are written exclusively in Tester modules.
- The Tester modules are class modules that must respect the template of the
TesterTemplate
module - The Tester modules must have their name ending with
Tester
- The unit tests are the
Sub
s in a Tester module that have their name beginning withTest
This template has two important subroutines to us :
-
The
ITestCase_SetUp()
subroutine will be run before each unit test : it is typically used to create the test environment. -
The
ITestCase_TearDown()
subroutine will be run after each unit test : it is typically used to wipe clean the test environment.
Other parts of the template are worth knowing :
-
The
TestNothing()
subroutine is just here for example purporses. You shall delete it or replace it by a proper test. -
The
ITestCase_RunTest()
subroutine is a little bit special, as its code will not be written by the developer ! More on that later.
It runs all the tests that have been written in the module.
-
For any failure to be recorded, a unit test
Sub
has to use one of the two satements provided by VBA Unit :-
mAssert.Should (Condition As Boolean, Optional Comment As String)
-
mAssert.Equals (Actual As Variant, Expected As Variant, Optional Comment As String)
-
-
The
Equals
statement is generally nice to use as it prints the actual and expected value when a test fails.
-
In the "Immediate Window" of VBA IDE, type
prep
and press Enter.-
In each Tester module, the
ITestCase_RunTest()
andITest_Suite()
subroutine will get updated with theSub
s whose name begins withTest
. -
It is recommended to type
prep
every time you want to run the tests, even though (you could swear !) you did not change any name or deleted any test.
-
-
In the "Immediate Window" of VBA IDE, type
run
and press Enter.- All the tests will be ran. Then, VBA Unit will display a list of the tests that failed and their associated comments.
-
When you're working on a class or module, you certainly don't need to re-run all the tests all the time. You can run a sole Tester class by specifying it as a parameter for the run command:
run("MyClassTester")
. Don't forget sometimes to run all the tests, particularly just before a commit! -
It is also possible to compose a particular Test suite. Create a Sub in a standard Module to:
- Create an instance of the TestSuite class
Dim mySuite as new TestSuite
. - Add test classes with
mySuite.AddTest("MyClassTester")
or specific methods withmySuite.AddTest("MyClassTester","testMethodName")
. - Run this specific Test Suite with
mySuite.Manager.Run(mySuite)
.
-
Sometimes, you might want to run only one Test sub in a Tester class, but you still need the Setup and Teardown. Instead of commenting manually all the subs you don't need, just copy paste all the code of the class in a new Tester class, remove all the subs you don't want, and run this new Tester class.
-
When an error occurs in one unit test that was not ready for it, it will break the whole testing sequence. This is both unpleasant and time consuming. You may want to systematically use error handlers with
mAssert.Should Not,"Unexepected error " & err.Number & " in " & err.Source : " & err.Description
statements in your testSub
s. -
If it happens anyhow, some weird error messages may pop-up the next time you do your
prep run
. This is usually caused by the Test folder not being empty. Delete everything in it manually, and doprep run
again. -
It's impossible to isolate VBAUnit in its own VBA Project. Due to strict dependance relation between VBA projects, it's impossible to not include VBAUnit into the project under test. Tests classes needs to call VBAUnit, and ClassLister in VBAUnit calls Tests classes. As a workaround, it is certainly possible to create a TestProject including Tester classes and VBAUnit modules to separate the project under test and the test project
-
When testing Excel workbooks containing macros, the test may be longer because VBA IDE displays the code panes of the opened Excel workbook. Solution: close all code panes from the Excel templates used for test.