Documenting namespaces for test code in composer.json

When you build an application or library and use composer for autoloading, you typically configure one or more autoloaders for production code in the autoload section of composer.json.

{
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  }
}

phpunit/phpunit, the popular testing framework, will search directories configured in phpunit.xml or passed as arguments to the test runner for instantiable classes that directly or indirectly extend PHPUnit\Framework\TestCase and with a class name ending with Test.

phpbench/phpbench, the popular benchmarking framework, will search a directory passed to the test runner for instantiable classes with a class name ending with Bench.

Neither of these tools is concerned with whether these classes are declared in namespaces or can be autoloaded.

So why bother configuring an autoloader for test code in the autoload-dev section of composer.json?

{
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "App\\Test\\": "test/"
    }
  }
}

Configuring an autoloader for test code in the autoload-dev section of composer.json has the following advantages:

  1. You document the namespace for tests for yourself and other developers.

    When other developers join your closed-source project or want to contribute to your open-source project, or even when you pick up work on this project after a pause, everyone will understand which namespace they should declare in tests.

    By documenting the namespace for tests in the autoload-dev section of composer.json, you can avoid confusing other developers or repeatedly having to answer the question of which namespace you should use.

  2. You document the namespace and allow autoloading of abstract test cases, test helpers, test doubles, data providers, and other helpful objects.

    When your project grows, you may extract abstract test cases to share functionality across test cases when inheritance is an option. Alternatively, you may implement one or more helper traits to share functionality across test cases when inheritance is not an option. For example, the PHP framework of your choice may ship with abstract test cases that you need to extend, but you still want to reuse functionality.

    When you have had your share of mocking frameworks, you may prefer to implement test doubles for specific scenarios by hand.

    When you find that your tests could benefit from reusing data providers, you may want to extract data providers into classes.

    When you extensively use data providers with complex scenarios, you may decide to extract test scenarios into value objects.

    By documenting the namespace for auxiliary test code in the autoload-dev section of composer.json, you acknowledge and encourage developers to extract functionality in abstract test cases, test helpers, test doubles, data providers, and other helpful objects into autoloadable classes.

  3. You document the namespace for your favorite IDE.

    When PhpStorm indexes and analyzes a project, it also inspects composer.json and synchronizes the autoloading configuration with the PHP namespace configuration in the project.

    When you create classes or test cases using the user interface of PhpStorm, it creates classes and test cases in the appropriate directories based on the namespace configuration.

    When you copy or move classes, or move or rename namespaces using the user interface of PhpStorm, PhpStorm will move classes to the appropriate location based on the namespace configuration.

    By documenting the namespace for test code in the autoload-dev section of composer.json, you avoid having to configure namespace mappings manually in PhpStorm and allow PhpStorm to do its magic right out of the box.

By documenting namespaces for test code in the autoload-dev section of composer.json of a project, you make the life of every developer working on that project easier and can be more productive.

Do you have any projects where you have not yet documented namespaces for test code?

Do you find this article helpful?

Do you have feedback?

Do you need help with your PHP project?