gb.test – The Gambas Unittest

gb.test is a Gambas component for unittesting and test-driven-development (TDD). With this component you can develop software in a test-driven matter (write test first, program functionality afterwards) and you are able to ensure that on refactoring the desired results of your code stays the same.

Tests are output as TAP together with a summary. You can watch the progress of the testing as well as the test result inside the Gambas IDE in the Unit Tests tab. The summary at the end shows "PASSED" or "FAILED" so you can easily see if your tests have been successful or not. But they also can be displayed, analyzed or viewed with any Tap consumer.

You can also run the tests of your project on the command line and thus gb.test provides the tools to run tests automatically.

Example

There is an example in this simple Gambas project.

Testmodule

In test driven development it is usual to first write the test that the future program will later fulfill. Therefore we start by creating a test module.

This is a class, named like any other Gambas class with the ending ".test", for example "THelloWorld.test". This class contains one or more tests, these are public subs whose name must not contain an underscore:


' Gambas test module file
''' Testmodule THelloWorld

Public Sub AHelloWorld()
  Test.Note("I am the first test, because my name starts with A.")
  Assert.Equals(Hello.World(), "Hello World", "HW strings should be equal")
End

With the methods provided by the Assert class you are able to test the output of any public state (variable, constant or function) in your project.

Module (Function) to test:

Now that we have written the test, it is time to develop the program that will fulfill the test. So we create a function "World" in a module "Hello" in our project:


' Gambas module file
''' Module is named "Hello"
'' Returns "World"
Public Function World() As String

  Return "Hello World"

End

Running the test

If you are working with the Gambas IDE you can hit F4 to let your tests run. The IDE will show you the "Unit tests" tab with this content:


1..1
Test THello:AHelloWorld
  # I am the first test, because my name starts with A.
  ok 1 - HW strings should be equal
  1..1
ok 1 - THello:AHelloWorld
# Ran: 'THello.AHelloWorld'
#
# PASSED

If a failure occurs it will report FAILED instead of PASSED and will show you the place of the failure. If you want to debug the code you can set a breakpoint anywhere in your test or production code, hit <F4> again and start debugging.

Testmodules and testmethods can be named the same way as any Gambas Module or Method except that a testmethod may not be named _Setup(), _Teardown(), _SetupEach() or _TeardownEach() and it's name must not contain an underscore.

Testing with the IDE

If you hit Shift-F4 the Gambas IDE lets you create so called "test suites". This is convenient if you have a lot of tests but need to run just one or a couple of them by chance. You can create a lot of test suites and use them to test different aspects of your project separately.

Testsuites are stored in the file .test in the project's path.

Test your project on the console

You also can test your project on the console. The command gbx3 -T "*" /path/to/my/project executes the unittests and prints the result to standard output. You can call single tests or an arrangement of tests in the same way, as these are stored in the file .test after you created a test suite.

You can even let run a testsuite by name by adding a preceeding "@" to it's name if you let it run with gbx3:

gbx3 -T "@my first testsuite" /path/to/my/project

Test fixture

Sometimes it is neccessary to create a "fixture", a special environment for a test or a couple of tests, and to destroy this environment after the test is done. For example a database connection should be established at the beginning of all tests, some tables for testing should be created and deleted for every single testmethod and the database connection should be closed at the end. This can be done with _Setup... and _Teardown... functions inside the testmodule.

Sub _Setup() and Sub _Teardown()

You can create methods with these names to create an environment for all testmethods inside a testmodule, in the beginning _Setup() is invoked and after all testmethods inside the testmodule are done you can destroy the environment with _Teardown().

Sub _SetupEach() and Sub _TeardownEach()

You can create methods with these names to create an environment for each testmethod before it is invoked and to destroy it afterwards. If you have five testmethods inside your testmodule these functions will be invoked five times, _SetupEach() before each testmethod, _TeardownEach() after each testmethod. Got it?

Plan tests

It would be pretty stupid if your test system, for unknown reasons, swallowed single tests and never showed you that they did not run. To protect yourself from this, there is a way to specify a plan that defines the number of assertions that must run inside a testmethod. And it goes like this:


' Gambas test file
''' Testmodule THelloWorld
Public Sub AHelloWorld()
  '' Defines the count of assertions in this testmethod
  Test.Plan(1)
  Assert.Equals(Hello.World(), "Hello World", "HW strings should be equal")
End

If the tests have not fulfilled the plan, the system will display "FAILED" and tell you the reason.