Creating Unit Tests

Basic Test Files

A test file is a Blitz file that is laid out in a certain way so it can be understood by BlitzUnit.

Each unit test file must contain:

  • A test fixture -- This is a Blitz Type that is used to group tests together. It also contains variables and objects that commonly used in the file's unit tests, such as banks or images.

  • Test functions -- These are standard Blitz functions that take an parameter called "this" that is an instance of the test fixture type.

  • Assertions -- Each test should contain only one Assertion. Assertions test if a condition has been met, and if not will flag a failure with BlitzUnit.

Optional items for a test file:

  • Setup method -- A function called "Setup" that will be called at the start of each test to initialise data within the test fixture. It takes a parameter called "this" that is an instance of the test fixture.

  • TearDown method -- A function called "TearDown" that cleans up resources created by "Setup", and will be called when each test has finished. Again, it takes a parameter called "this" that is an instance of the test fixture.

Important: The test file should contain only one type (your test fixture) and only test functions (with the exception of Setup and TearDown). Other functions should be included using the Blitz "Include" function.

A Detailed Example

The simplest way to see how it all works is to write a test fixture and see what happens.

In this (rather contrived) example, we want to check that our function "concat" will join two strings together with a space between them. HOWEVER, if either argument is empty the function should return the non-empty argument. White space should be preserved in all cases.

Example1.concat.bb - Deliberate bug

Function concat$(part1$, part2$)
	return part1 + " " + part2
End Function

You'll notice the function above as a bug in it. It doesn't check for empty arguments, so it won't behave as it should. Let's see if our testing catches that.

Example2.concat_tests.bb

Include "concat.bb"

Type Example_ConcatTests
    Field arg1$, arg2$, expected$
End Type

Function Setup(this.Example_ConcatTests)
    this\arg1     = "Hello"
    this\arg2     = "World"
    this\expected = "Hello World"
End Function

; Check basic behaviour
Function ConcatTest(this.Example_ConcatTests)
    Assert_AreStringsEqual(this\expected, concat(this\arg1, this\arg2), "")
End Function

; Test empty strings
; Note nothing is passed to the function, as BlitzUnit will automatically
; update the function definition.
Function EmptyStringTest()
	Assert_AreStringsEqual(this\arg1, concat(this\arg1, ""), "") 
End Function

; Test whitespace is preserved
Function WhiteSpaceIsPreservedTest()
	Assert_AreStringsEqual(this\expected + " ", concat(this\arg1, this\arg2 + " "), "")
End Function 

The first test passes with the expected behaviour, but the second test fails because "Hello " is returned instead of "Hello".

One solution might be to use "Trim" on the return value, so let's add another test to see what happens.

Example3.concat.bb - Another bug

Function concat$(part1$, part2$)
    return Trim(part1 + " " + part2)
End Function

Now the "Empty String" test passes, but the whitespace test fails. Let's try again...

Example4.concat.bb - Now it works

Function concat$(part1$, part2$)
	If part1 = "" then return part2
	if part2 = "" then return part1
	
	return part1 + " " + part2
End Function

Phew, everything passes!

Hopefully such a long-winded example hasn't put you off from unit testing! With just a few short tests, you can quickly check that your function is behaving the way it should.

More samples can be found in the "examples" folder.