Over a million developers have joined DZone.

Practical PHP Testing Patterns: Derived Value

· Web Dev Zone

Make the transition to Node.js if you are a Java, PHP, Rails or .NET developer with these resources to help jumpstart your Node.js knowledge plus pick up some development tips.  Brought to you in partnership with IBM.

Tests are example scenarios were we exercised our code: a large enough number of examples results in a complete specification and coverage. We are exploring how to express the values that the examples consist of, being them string, integers, arrays or any kind of object.

In the Derived Value pattern, values are not hardcoded into tests like for Literal Value, but they are derived from other values with some procedure, which may be inline code, but also methods or even external helpers.

The issues

Derived Value is not to be introduced lightly: if not used correctly, its disadvantages outweigh its benefits (which will be more clear in the different variations). By the way, its goal is to eliminate duplication by producing values from a fixed source on the fly, instead of making the programmer generate them once and for all when writing the test.

If Derived Values follow the same logic of the production code, the same bug may appear in the production code and in the test at the same time, defeating our defect localization goals. In general, you must pay attention that bugs or regressions in the derivations may cause your test to become a false positive.


Each specialization of the pattern attempts to remove a bit of duplication by introducing logic in the test. The trade-off is between a simpler test harder to modify and a complex test whose logic may hide bugs.

  • Derived Input: one of the input is calculated from other inputs to made the relationship clear and avoid redundancy, keeping the input data automatically consistent. For example, if you have to extract all pairs of cards from a deck of $cards = 52 cards, you won't extract $pairs = 26 pairs but $pairs = $cards / 2 pairs.
  • One Bad Attribute: you may create a valid object, and then make one attribute invalid to focus the test on this aspect. Other values are not taken into consideration by the reader, and do not have to be updated by the programmers after unrelated changes to them. A Creation Method helps to centralize the logic for creating the valid version.
  • Derived Expectation: the expected value is calculated instead of being predefined. A simple case of this was seen in the Literal Value article (an inline multiplication and sum), but in this variation the logic may be extracted in one method (which would be exactly a replica of production code).

You may use some production code to test other production code, in case it simplifies the assertions. For example, consider testing objects equality: you can produce a new, target object and make PHP do the work by comparing them with ==. With this mechanism you become a little vulnerable to regressions in that class, but you avoid exposing fields via getters just for making a comparison on the test:

$color = ...
$expected = new Color(0, 0x66, 0x99);
$this->assertEquals($expected, $color);


The sample code shows you the three variations, each with an explanation of the issues of the alternative solution: hardcoding (which would not be bad per se).

class DerivedValueTest extends PHPUnit_Framework_TestCase
     * In this example, $center is computed to avoid a test bug because someone
     * updated $array and forgot the $center variable.
     * In short, to remove duplication.
    public function testADerivedInputRemovesDuplicationAndImprovesClarity()
        $array = array('a', 'b', 'center', 'd', 'e');
        $center = floor(count($array) / 2);
        $this->assertEquals('center', $array[$center]);

     * A data structure HTTP request is created and then invalidated.
     * Compare this with redefining the array every time and make sure
     * the other keys are still valid.
     * I use an array in place of an object for brevity in this explanation.
    public function testOneBadAttributeValuesAreBuiltFromValidOnes()
        $request = $this->createGetRequest(); // hides module and controller details
        $request['action'] = 'this-will-cause-a-404';
        $this->markTestIncomplete('When calling the SUT, the action should be judged as invalid.');

    private function createGetRequest()
        return array(
            'module' => 'default',
            'controller' => 'index',
            'action' => 'index'

     * If we have a "casting-out-nines" test to quickly check our results, 
     * at least as in a smoke test, we can use a derived expectation.
     * Since our test cases are usually many simplified scenarios where
     * to exercise the production code, deriving the right result shouldn't 
     * require as much code as in there. If you have to mirror the production 
     * code, stop: the test would become too tied with the implementation, to 
     * the point of reproducing its bugs.
     * These tests come handy when the amount of data is huge (e.g. multimedia 
     * files) and generating a sanity check is by far faster than hardcoding
     * everything by hand (the image contains a car at pixel (45; 100) ...).
    public function testADerivedExpectationLetsYouAssertWithoutHardcoding()
        $array = array();
        $elements = 4; // our unique parameter
        for ($i = 1; $i <= $elements; $i++) {
            $array[] = $i;
        $expectedTotal = $elements * ($elements + 1) / 2; // Gauss formula
        $total = array_sum($array);
        $this->assertEquals($expectedTotal, $total);

Learn why developers are gravitating towards Node and its ability to retain and leverage the skills of JavaScript developers and the ability to deliver projects faster than other languages can.  Brought to you in partnership with IBM.


Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}