2013-03-29 3 views
52

Я только что установил версию PHPUnit 3.7.19 от Себастьяна Бергмана через Composer и написал класс, который я хотел бы выполнить для тестирования.Автозагрузка классов в PHPUnit с использованием Composer и autoload.php

Я хотел бы, чтобы все мои классы автозагружаемые в каждом модульном тесте без необходимости использовать include или require в верхней части моего теста, но это, оказывается, трудно!

Это то, что моя структура каталогов выглядит (замыкающая/слэш указывает каталог, а не файл):

  • composer.json
  • composer.lock
  • composer.phar
  • Библиотека/
    • returning.php
  • тесты/
    • returningTest.php
  • поставщик/
    • бен/
      • PHPUnit
    • композитор/
    • PHPUnit/
    • Symfony/
    • autoload.php

Мой файл composer.json включает в себя следующее:

"require": { 
    "phpunit/phpunit": "3.7.*", 
    "phpunit/phpunit-selenium": ">=1.2" 
} 

Мой returning.php файл класса включает в себя следующее:

<?php 
class Returning { 
    public $var; 
    function __construct(){ 
     $this->var = 1; 
    } 
} 
?> 

My returningTest.php тестовый файл включает в себя следующее:

<?php 
class ReturningTest extends PHPUnit_Framework_TestCase 
{ 
    protected $obj = null; 

    protected function setUp() 
    { 
     $this->obj = new Returning; 
    } 

    public function testExample() 
    { 
     $this->assertEquals(1, $this->obj->var); 
    } 

    protected function tearDown() 
    { 

    } 
} 
?> 

Однако, когда я бегу ./vendor/bin/phpunit tests из командной строки, я получаю следующее сообщение об ошибке:

PHP Fatal error: Class 'Returning' not found in /files/code/php/db/tests/returningTest.php on line 8

Я заметил, что composer произвел autoload.php файл в vendor/autoload.php, но не уверен, что это относится к моей проблеме.

Кроме того, в некоторых других ответах на Stack Overflow люди упоминали об использовании PSR-0 в композиторе и в команде namespace в PHP, но мне не удалось использовать ни один из них.

Пожалуйста, помогите!Я просто хочу автозагружать свои классы в PHPUnit, поэтому я могу просто использовать их для создания объектов, не беспокоясь о include или require.


обновление: 14 августа 2013

Теперь я создал Open Source проект под названием PHPUnit Skeleton, чтобы помочь вам встать и работает с тестированием PHPUnit легко для вашего проекта.

+9

спасибо за организацию вопрос хорошо. – kta

ответ

64

Ну, сначала. Вы должны указать автозагрузчику, где найти файл php для класса. Это делается, следуя стандарту PSR-0.

Лучший способ - использовать пространства имен. Автозагрузчик выполняет поиск файла Acme/Tests/ReturningTest.php при запросе класса Acme\Tests\ReturningTest. Там есть несколько замечательных учебников по пространству имен, просто поиск и чтение. Обратите внимание, что пространство имен - это , а не что-то, что входит в PHP для автозагрузки, это то, что можно использовать для автоматической загрузки.

Композитор поставляется со стандартным автозагрузчиком PSR-0 (один в vendor/autoload.php). В вашем случае вы хотите сообщить автозагрузчику поиск файлов в каталоге lib. Затем, когда вы используете ReturningTest, он будет искать /lib/ReturningTest.php.

Добавьте это в composer.json:

{ 
    ... 
    "autoload": { 
     "psr-0": { "": "lib/" } 
    } 
} 

Больше информации в the documentation.

Теперь автозагрузчик может найти свои классы, необходимые для того, чтобы PHPunit знал, что перед запуском тестов должен быть выполнен файл: файл начальной загрузки. Вы можете использовать опцию --bootstrap указать, где находится файл начальной загрузки находится:

$ ./vendor/bin/phpunit tests --bootstrap vendor/autoload.php 

Однако, это лучше использовать PHPunit configuration file:

<!-- /phpunit.xml.dist --> 
<?xml version="1.0" encoding="utf-8" ?> 
<phpunit bootstrap="./vendor/autoload.php"> 

    <testsuites> 
     <testsuite name="The project's test suite"> 
      <directory>./tests</directory> 
     </testsuite> 
    </testsuites> 

</phpunit> 

Теперь вы можете запустить команду, и она будет автоматически обнаруживать конфигурационный файл:

$ ./vendor/bin/phpunit 

Если поместить конфигурационный файл в другой каталог, вам необходимо поместить путь к этой директории в командном остроумии h -c вариант.

+0

Wouter, спасибо за очень подробное объяснение. Я пробовал эти точные шаги, но я все еще получаю ошибку 'PHP Fatal error: Class 'Returning' не найден в /files/code/php/db/tests/returningTest.php в строке 8'. Как узнать, что я делаю неправильно? –

+0

@WouterJ '' только устанавливает автозагрузчик для классов под "lib /". Вам по-прежнему необходимо автозагружать классы в разделе «tests /». –

+3

@ChuanMa no, PHPunit будет сканировать через каталог 'tests /' и запускать тестовые классы, их уже автозагрузка. –

34

[Update2] Еще более простой альтернативный подход заключается в использовании autoload-dev директиву в composer.json (reference). Преимущество в том, что вам не нужно поддерживать два bootstrap.php (один для prod, один для dev) только для того, чтобы автозагружать разные классы.

{ 
    "autoload": { 
    "psr-4": { "MyLibrary\\": "src/" } 
    }, 
    "autoload-dev": { 
    "psr-4": { "MyLibrary\\Tests\\": "tests/" } 
    } 
} 

[Update] Ответ Wouter J является более полным. Но мой может помочь людям, которые хотят настроить автозагрузку PSR-0 в папке tests/.
Phpunit просматривает все файлы с этим рисунком *Test.php. Поэтому нам не нужно самостоятельно загружать их. Но мы по-прежнему хотим автозагружать другие поддерживающие классы под номером tests/, такие как fixture/stub или некоторые родительские классы.

Простым способом является просмотр того, как сам проект Composer настраивает тест phpunit. На самом деле это очень просто. Обратите внимание на строку с «bootstrap».

ссылка: https://github.com/composer/composer/blob/master/phpunit.xml.dist

<?xml version="1.0" encoding="UTF-8"?> 

<phpunit backupGlobals="false" 
     backupStaticAttributes="false" 
     colors="true" 
     convertErrorsToExceptions="true" 
     convertNoticesToExceptions="true" 
     convertWarningsToExceptions="true" 
     processIsolation="false" 
     stopOnFailure="false" 
     syntaxCheck="false" 
     bootstrap="tests/bootstrap.php" 
> 
    <testsuites> 
     <testsuite name="Composer Test Suite"> 
      <directory>./tests/Composer/</directory> 
     </testsuite> 
    </testsuites> 

    <groups> 
     <exclude> 
      <group>slow</group> 
     </exclude> 
    </groups> 

    <filter> 
     <whitelist> 
      <directory>./src/Composer/</directory> 
      <exclude> 
       <file>./src/Composer/Autoload/ClassLoader.php</file> 
      </exclude> 
     </whitelist> 
    </filter> 
</phpunit> 

ссылка: https://github.com/composer/composer/blob/master/tests/bootstrap.php

<?php 

/* 
* This file is part of Composer. 
* 
* (c) Nils Adermann <[email protected]> 
* Jordi Boggiano <[email protected]> 
* 
* For the full copyright and license information, please view the LICENSE 
* file that was distributed with this source code. 
*/ 

error_reporting(E_ALL); 

$loader = require __DIR__.'/../src/bootstrap.php'; 
$loader->add('Composer\Test', __DIR__); 

Последняя строка выше самозарядные тестовые классы PHPUnit под пространством имен Composer \ Test.

+6

Также используйте блок« require-dev »вместо блока« require »для добавления пакетов phpunit в composer.json. Вы не хотите, чтобы код phpunit был установлен на производстве. Дополнительную информацию см. В документе doc. –

5

Ни один из этих ответов не был тем, что я искал. Да PHPUnit загружает тестовые файлы, но не заглушки/приборы. Ответ Chaun Ma не сокращает его, потому что запуск vendor/bin/phpunit уже включает автозагрузку, поэтому нет способа получить экземпляр автозагрузчика, чтобы направить больше путей в его стек.

В конце концов я нашел это в документации:

If you need to search for a same prefix in multiple directories, you can specify them as an array as such:

{ 
    "autoload": { 
     "psr-0": { "Monolog\\": ["src/", "lib/"] } 
    } 
} 
+0

Да. последний phpunit уже включает автозагрузчик композиторов. Но мой подход все еще работает (мы используем его уже почти 2 года). Преимущество состоит в том, что мы не хотим автоматически загружать тестовые классы в производство. Вот еще одна полезная ссылка SO (отвечает разработчик композитора): http://stackoverflow.com/questions/12790681/composer-cannot-load-loader-when-phpunit-is-used –

+0

Обратите внимание, что даже если 'vendor \ bin \ phpunit' уже «требует» композитора для автозагрузчика, он не останавливает вас «требовать» его снова и получает объект '$ loader' для добавления новых классов. –