Test-Driven Development (TDD) platform for VBA.
Strongly inspired by Ruby's RSpec.
Also inspired by VBA-TDD for the "With structure" and the Expectation syntax.
- Download the file
VBASpec.xlam. - Put it in your Office Addins folder (usually
~\AppData\Roaming\Microsoft\Addins\). - Follow this guide to activate it via the Addins dialog.
- And this one to add the Reference in your code.
First create an instance:
Dim Suite As VBASpecSuite
Set Suite = New VBASpecSuiteThen Describe what you are testing:
With Suite.Describe("Something")
...Then explain what It is doing:
With Suite.Describe("Something")
With .It("exists")
...Then code what is Expected:
With Suite.Describe("Something")
With .It("exists")
.Expect(something).ToNotBeNothingUnder the hood, the Describe() method returns an ExampleGroup class which is passed to the With statement. You can then access its It() method (notice the preceding .), which then returns an Example class which have a Expect() method (again the preceding .) that returns an Expectation class.
So the last piece of code could as well have been written like so:
Suite.Describe("Something").It("exists").Expect(something).ToNotBeNothingand it would give the exact same result.
But when using the With syntax, we can chain as many sibling methods as we like inside the same parent:
With Suite.Describe("Something")
With .It("exists")
.Expect(something).ToNotBeNothing
End With
With .It("is a number, not a string")
.Expect(something).ToBeAn "Integer"
.Expect(something).ToNotBeA "String"
End With
End Withwhich mimics the closure syntax, found in interpreted languages, that would otherwise not be possible in a compiled language like VBA.
VBASpecExpectation class provides methods that lets you express expected outcomes on an object in an example.
.Expect(1 + 1).ToEqual 2 'Passes
.Expect(1 + 1).ToEqual 3 'Fails with message: "Expected 2 to equal 3"Here is the list of all expectations, along with their negated counterpart:
.Expect(Actual).ToEqual Expected 'Actual = Expected
.Expect(Actual).ToNotEqual Expected
.Expect(Actual).ToBe Expected 'Actual Is Expected
.Expect(Actual).ToNotBe Expected.Expect(Actual).ToBeA/ToBeAn Expected 'TypeName(Actual) = Expected
.Expect(Actual).ToNotBeA/ToNotBeAn Expected.Expect(Actual).ToBeEmpty 'Actual = (Empty|Nothing|Null|Missing|"")
.Expect(Actual).ToNotBeEmpty
.Expect(Actual).ToBeNothing 'Actual Is Nothing
.Expect(Actual).ToNotBeNothing
.Expect(Actual).ToBeZero 'Actual is equal to 0
.Expect(Actual).ToNotBeZero.Expect(Actual).ToBeTrue 'Actual = True
.Expect(Actual).ToBeTruthy 'Actual evaluates to True
.Expect(Actual).ToBeFalse 'Actual = False
.Expect(Actual).ToBeFalsy 'Actual evaluates to False.Expect(Actual).ToBeLessThan/ToBeLT Expected
.Expect(Actual).ToBeLessThanOrEqual/ToBeLTE Expected
.Expect(Actual).ToBeGreaterThan/ToBeGT Expected
.Expect(Actual).ToBeGreaterThanOrEqual/ToBeGTE Expected
.Expect(Actual).ToBeCloseTo Expected, [SignificantFigures (Default: 2)]
.Expect(Actual).ToNotBeCloseTo Expected, [SignificantFigures (Default: 2)].Expect(Actual).ToInclude Expected 'Expected is included in Actual
.Expect(Actual).ToNotInclude Expected
.Expect(Actual).ToBeginWith Expected 'Expected is at the beginning of Actual
.Expect(Actual).ToNotBeginWith Expected
.Expect(Actual).ToEndWith Expected 'Expected is at the end of Actual
.Expect(Actual).ToNotEndWith Expected
'(These all work with Arrays, Collections and Strings)On Error Resume Next '<- Really important
var = 1 / 0 ' The expectation must be placed AFTER the line that cause the error
.Expect.Error 'Passes when ANY error is raised
.Expect.Error(11) 'Passes, since 'Division by zero (Error 11)' was raised
.Expect.Error(12) 'Fails
On Error Goto 0On Error Resume Next '<- Really important
var = 1 / 2 ' The expectation must be placed AFTER the line that could cause the error
.Expect.NoError 'Passes
var = 1 / 0
.Expect.NoError 'Fails
On Error Goto 0.Expect.NoError.WasRaised 'The function .WasRaised can also be added at the end
.Expect.Error(11).WasRaised 'Mostly for aesthetic reasons...
.Expect.Error.WasRaisedmodTest.bas :
Sub Test()
Dim Suite as VBASpecSuite
Set Suite = New VBASpecSuite
With Suite.Describe("modUtils")
With .Describe(".Max([ParamArray])")
With .It("returns the highest number")
.Expect(Max(2, 3, 5, 8)).ToEqual 8
.Expect(Max(8, 5, 3, 2)).ToEqual 8
End With
With .It("works with decimal numbers")
.Expect(Max(2.3, 5.8, 13.21)).ToEqual 13.21
End With
End With
End With
End SubmodUtils.bas :
Public Function Max(ParamArray Numbers())
Dim Number As Variant
For Each Number In Numbers
If Number > Max Then Max = Number
Next Number
End Function