Unit testing

About our unit tests

All modern versions of Totara (> Totara Learn 2.2) make use of PHPUnit for unit testing.
Composer facilitates installation, and we have a very customised bootstrap routine that is executed when running it.
In Totara Learn 2.2 and earlier versions we use simple test.

Before you start running, and developing unit tests its important to know what they are to Totara Learn.
For us they are much more inline with integration tests than unit tests.
Parts of our code base are exceptionally old, and were never designed for testing.
The tests that we write often test functional code somewhere in the stack, and we don't shy away from testing against the database, cache systems etc.

Because of this our unit test suite is not fast.
At the time of writing this it is taking our CI system roughly 34 minutes to execute all test cases, a total of 13450 tests and over 270000 assertions.
The good news is that we have a CI system that can run tests for you, and at your request against different versions of PHP and different databases.
Regardless however you need to run it locally.

It is also important to note that since 2016 it is a requirement of every change being made to code that it accompanied by tests. Unit tests for backend changes, and acceptance tests for front end changes.


Getting it running

We use Composer to handle the installation of both PHPUnit and behat.
Before you install however you need to configure your Totara Learn installation for PHPUnit. This is the first step.

Configuring Totara Learn to run PHPUnit

Before we install PHPunit we need to tell Totara Learn a few things about PHPunit and how you want it to install.
The following properties need to be defined in your config.php

  • phpunit_prefix
    All tables within the Totara Learn database start with a prefix (this is to avoid reserved names)
    Because you may be using the same database for testing and phpunit you need to provide a unique prefix to use for tables that will created for the sole purpose of PHPUnit testing.
    Just like the prefix config variable, only different.
  • phpunit_dataroot
    Like above you will also need to provide the path to a directory that will serve as the dataroot directory during testing.
    This directory will be purged at the start, end, and regularly during testing.
    Just like the dataroot config variable, only different.

There are a lot of additional phpunit variables that you can provide as well if you want to further customise how PHPUnit runs for you:

  • phpunit_dbtype
  • phpunit_dblibrary
  • phpunit_dbhost
  • phpunit_dbname
  • phpunit_dbpass
  • phpunit_dboptions

1. Get composer

Follow the guide: https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx

2. Install composer

Easily done. Once within the Totara Learn source directory simply execute:

php composer.phar install

3. Initialise your site for testing

We need to initialise PHPUnit within Totara Learn so that it is ready to run.

php admin/tool/phpunit/cli/init.php

This will install the database structures, prep data root and generally 

You are now ready to run tests.


Run tests

This can be done in a number of ways, including but not limited to the following:

Running all tests

vendor/bin/phpunit

Running a test suite

vendor/bin/phpunit --testsuite="mod_facetoface_testsuite"

Running a single testcase

Like above except that you provide two arguments, the first is the testcase class name, the second is the path to the test file

vendor/bin/phpunit core_user_userdata_username_testcase user/tests/userdata_username_test.php

Running a single test

It's also possible to run a single test within a test case using the fitler argument.

vendor/bin/phpunit --filter test_export user/tests/userdata_username_test.php

Note that when using the filter argument you don't actually need to specify a specific file, doing so just limits the scope of PHPUnit.
In fact filter is usable by itself, if used above all tests that contain "*test_export*" would be executed.

Running a group of tests

More recently we have been writing tests and defining them as groups, so that you can run related tests that are spread across the entire system with ease.

vendor/bin/phpunit --group totara_userdata

Developers can define groups as they are writing tests.
We recommend the group you define is, or starts with, the frankenstyle component name.


Performance testing unit tests

To better understand the tests you are writing, and to help us understand the performance costs of our test cases we have a means within Totara with which we can test the performance of our unit tests.

To start with add the following to your config.php

define('PHPUNIT_PROFILING', true);

Now run tests.

You will find the following two files have appears within your source directory.

  • phpunit_profile_classes_postgres.csv

  • phpunit_profile_methods_postgres.csv

These two files contain the timings on every class and method when you last ran PHPUnit.

Running tests in parallel

Totara 11 and newer comes with support for Paratest. Paratest is a tool which enables you to run the tests in parallel reducing the overall runtime of the test suite.

Initiate the tests

To initiate your site for a parallel test run:

php admin/tool/phpunit/cli/parallel_init.php --processes=4

The processes parameter can be omitted. It defaults to 5 processes.

Running the tests

We provide a script to trigger the run. Just supply the same 'processes' argument as during the init.

php admin/tool/phpunit/cli/parallel_run.php --processes=4