Skip to content

Unittest parameterization #267

Closed
Closed
@thekid

Description

@thekid

Scope of Change

This will extend the unittest API by adding a facility for providing values to a test.

Rationale

This will make it easier to discover problems in tests written using foreach loops currently, and at the same time reduce the amount of code that needs to be written for tests with separate test methods for every value.

Functionality

Parameterized test case methods can be annotated with a @values annotation.

Value sources

Inline

The values are taken from the annotation itself, as an array:

#[@test, @values(array(1, 2, 3))]
public function fixture($value) {
}

Locally sourced

The values are returned from a public instance method inside the current class

public function values() {
  return array(1, 2, 3);
}

#[@test, @values('values')]
public function fixture($value) {
}

Outsourced

The values are returned from a public static method inside a class specified by a double-colon notation.

class ValueProvider extends Object {
  public static function values() {
    return array(1, 2, 3);
  }
}

#[@test, @values('ValueProvider::values')]
public function fixture($value) {
}

Method sources - arguments

For the values sourced to methods, additional arguments may be provided by using the named annotation form. The source method is then invoked with the given arguments. If the args key is omitted, the method is invoked without any arguments (and may thus use their defaults):

public function range($lo= 1, $hi= 3) {
  return range($lo, $hi);
}

#[@test, @values(source= 'range', args= array(1, 10))]
public function fixture($value) {
}

Example 1: Refactoring multiple tests

This example collapses two separate methods into using the inline value source.

Before

  /**
   * Test name[=...
   *
   */
  #[@test, @expect('lang.FormatException')]
  public function unbalanced_opening_bracket_in_key() {
    $this->fixture->deserialize($this->input('name[=...'), Type::$VAR);
  }

  /**
   * Test name]=...
   *
   */
  #[@test, @expect('lang.FormatException')]
  public function unbalanced_closing_bracket_in_key() {
    $this->fixture->deserialize($this->input('name]=...'), Type::$VAR);
  }

After

  /**
   * Test unbalanced brackets such as "name[=..." and "name]=..." raise exceptions.
   *
   */
  #[@test, @expect('lang.FormatException'), @values(array('name[=...', 'name]=...'))]
  public function unbalanced_bracket_in_key($key) {
    $this->fixture->deserialize($this->input($key), Type::$VAR);
  }

Security considerations

n/a

Speed impact

Negligible

Dependencies

n/a

Related documents

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions