Test-driven development


Outlast Framework fully supports and encourages test-driven development (TDD). This is especially important if you are developing on the plugin- or system-level as here any change could break several dependent applications or plugins.

OFW tests are based on the super-small Enhance unit testing framework, so its API is identical to it. In addition it is integrated fully into the framework as follows…

Basic steps of creating a test

  1. Create a folder /app/test/
  2. Add a file named example.test.php and use the following contents. The class name can be anything, but needs to be unique project-wide:
    <?php
    /**
     * A standard unit test example.
     **/
    
    class ExampleTest extends zajTest {
        public function example_that_will_pass(){
        	$a_variable = true;
            zajTestAssert::isTrue($a_variable);
        }
    
        public function example_that_will_fail(){
        	$a_variable = false;
            zajTestAssert::isTrue($a_variable);
        }
    }
  3. Once the file is saved, the test can be run by going to http://example.com/update/test/ The update menu will run all of the tests for the entire project.

Setting up, tearing down

You can set up and the break down testing data using the special setUp() and tearDown() methods.

You can explicitly return false from your setUp() method which will skip the tests. Note that the tearDown() method will still be called (only logical, given that setUp() was also called).

Assertions

The assertions api is identical to that of the Enhance framework. We chose this framework because it’s a stand-alone, single-file, really simple implementation that covers all of the basics. Of course, you can create a plugin to use any other testing framework if you prefer.

So let’s see the assertions detail:

  • Type assertions are available: isArray, isNotArray, isBool, isNotBool, isFloat, isNotFloat, isInt, isNotInt, isNumeric, isNotNumeric, isObject, isNotObject, isScalar, isNotScalar, isString, isNotString
  • areIdentical($expected, $actual) – passes if type and value is same
  • areNotIdentical($expected, $actual) – passes if type or value are different
  • isTrue($actual) – passes if boolean true
  • isFalse($actual) – passes if boolean false
  • contains($expected, $actual) – passes the actual string contains the expected string
  • notContains($expected, $actual) – passes the actual string does not contain the expected string
  • isNull($actual) – passes if actual value is null
  • isNotNull($actual) – passes if actual value is not null
  • isInstanceOfType($expected, $actual) – passes if actual value is an object of type expected
  • isNotInstanceOfType($expected, $actual) – passes if actual value is not an object of type expected
  • isNotInstanceOfType($expected, $actual) – passes if actual value is not an object of type expected

You can also test logic:

  • fail() – will fail every time, you could use this after some custom logic to fail a test
  • inconclusive() – This call will fail every time – it indicates that a test should fail or has not yet been implemented
  • throws($someClass, 'MethodName') – this expects a thrown exception, so it fail if an exception is not thrown by the target
  • throws($someClass, 'MethodName', array(2, 'Arg2', 5)) – same as above but passing arguments

Throwing notices

In addition to failing outright, your tests can also throw notices. This is useful to notify the developer of deprecated functionality or other non-essential recommendations.

You can throw notices within any of your testing methods by calling the test library’s notice method:

$this->zajlib->test->notice("Something is not right in your code because it calls this and that. You should fix it!");

Keep in mind that notices are displayed outside of their context and do not refer back to either the test name or the line number. You need to add this information in your notice message (if it is needed).

Catching errors during test

You can test OFW errors ($this->zajlib->error()) by temporarily disabling them. You can use surpress_errors_during_test to turn error surpression on or off and get_last to get the text of the last error.

Take the following function:

function an_error_occurs(){
  return $this->zajlib->error("An error!");
}

During your test, you can surpress errors and then get the last error message to verify if you got that message during the execution:

function a_test(){
  // Surpress errors
    $this->zajlib->error->surpress_errors_during_test(true);
  // Run a test
    an_error_occurs();
  // Check the last error, this test will pass!
    $last_error = $this->zajlib->error->get_last('error');
    zajTestAssert::areIdentical("An error!", $last_error);
}

Important! Any surpression will only apply to the current test – even if you do not turn off surpression it will be turned off at the end of your current test function.

Examples

For real-world examples, take a look at the tests found in the system folder under /system/app/test/*.test.php.

Outlast Web & Mobile Development (c) 2023 | Privacy Policy |