PHPUnit загружает все классы одновременно. Вызывает фатальную ошибку PHP: не удается переопределить класс

Я сделал все возможное, но я не думаю, что какие-либо вопросы касались этой проблемы.

У меня есть ситуация, когда мой код PHP генерирует определения классов на основе свойств конфигурации.

Определения классов в основном являются держателями данных и могут иметь:

  • общественная собственность
  • или защищенные свойства с открытым интерфейсом, который предоставляет геттер / сеттеры.

В определенных случаях конфигурации сгенерированные ИМЯ КЛАССА БУДУТ ЖЕ, но их ИМЕНА ФАЙЛА БУДУТ РАЗНЫМИ. В реальной среде пользователь просто генерирует единый набор определений классов на основе требуемой конфигурации и использует классы в своем приложении. Нет проблем, даже если пользователь генерирует несколько наборов определений классов. PHP будет радостно работать, если в приложении есть только один набор определений.

У меня есть два тестовых случая PHPUnit, в которых я делаю в основном одни и те же тесты, используя классы с разными определениями, сгенерированными любой конфигурацией. Я использую "require_once" во всем своем коде и делаю то же самое в модульных тестах, "require_once", используя только те файлы классов, которые мне нужны для этого теста.

PHPUnit настроен для запуска всех тестов, которые он находит в моем каталоге тестов и работает в обычном режиме. Когда я добавил тесты для разных поколений классов, PHPUnit перестал работать с фатальной ошибкой PHP: невозможно повторно объявить класс.

Теперь поведение PHPUnit по умолчанию, по-видимому, заключается в загрузке ВСЕХ классов, которые ВСЕ тесты должны запускать за один раз. Это приводит к фатальной ошибке PHP даже до запуска любого теста, потому что PHPUnit выбирает второе определение для сгенерированных классов (они имеют одинаковое имя класса, но разные имена файлов), хотя я только "require_once" редактировал правильные определения классов в каждом тестовый файл.

Я все еще могу запускать тесты, но только с одним тестовым файлом за раз, поэтому в настоящее время я должен запускать все свои тесты вручную или с помощью пакетного файла. Полный отчет о покрытии кода по всем тестам невозможен.

Мне хотелось бы, чтобы PHPUnit загружал только те классы, которые были "require_once" ed для каждого тестового файла, а не для всех тестовых файлов, которые он видит как запускаемые из конфигурации phpunit.xml. Или лучшим способом было бы для PHPUnit загружать свои собственные классы только для всех указанных тестов и оставлять PHP самому, чтобы пользователь "require_once" выполнял каждый тест.

Есть ли способ обойти это? Я посмотрел на параметры конфигурации PHPUnit, но ни один из них не подходит для конкретной проблемы. Я не очень знаком с PHPUnit под прикрытием, поэтому создание другого загрузчика testsuite будет затруднительным.

Вероятно, лучше сделать простой пример. Вот несколько тестовых файлов PHPUnit foo1Test.php и foo2test.php. Единственное различие между ними заключается в том, что они требуют_ другого файла класса, который имеет определение класса Foo. Неважно, что все эти классы пусты, все они совершенно законны, и это хорошо демонстрирует проблему. Я просто поместил все эти файлы в каталог testfoo и запустил на них PHPunit. Вы можете сделать это тоже, и вы получите тот же результат.

foo1Test.php

<?php

require_once dirname ( __FILE__ ).'/Foo1.php';

class Foo1TestCase extends PHPUnit_Framework_TestCase
{
}

?>

foo2Test.php

<?php

require_once dirname ( __FILE__ ).'/Foo2.php';

class Foo2TestCase extends PHPUnit_Framework_TestCase
{
}

?>

Foo1.php

<?php

class Foo
{
}

?>

Foo2.php

<?php

class Foo
{
}

?>

Два тестовых файла foo1Test.php и foo2Test.php являются совершенно корректными файлами и выполняются через следующие командные строки PHPunit.

phpunit foo1Test.php
phpunit foo2Test.php

Как и следовало ожидать, PHPUnit терпит неудачу, жалуясь на отсутствие тестов, что хорошо.

У меня также есть стандартный файл конфигурации phpunit.xml, который будет запускать все тесты в текущем каталоге.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupStaticAttributes="false"
         cacheTokens="false"
         colors="false"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         forceCoversAnnotation="false"
         mapTestClassNameToCoveredClassName="false"
         printerClass="PHPUnit_TextUI_ResultPrinter"
         processIsolation="false"
         stopOnError="false"
         stopOnFailure="false"
         stopOnIncomplete="false"
         stopOnSkipped="false"
         testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
         strict="false"
         verbose="true">
    <testsuite name="fooTests">
        <directory>.</directory>
    </testsuite>
</phpunit>

Я запустил PHPUnit с этим конфигом следующим образом

PHPUnit

Выход:

PHP Fatal error:  Cannot redeclare class Foo in /var/www/testfoo/Foo2.php on line 4
PHP Stack trace:
PHP   1. {main}() /usr/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP   3. PHPUnit_TextUI_Command->run() /usr/share/php/PHPUnit/TextUI/Command.php:130
PHP   4. PHPUnit_TextUI_Command->handleArguments() /usr/share/php/PHPUnit/TextUI/Command.php:139
PHP   5. PHPUnit_Util_Configuration->getTestSuiteConfiguration() /usr/share/php/PHPUnit/TextUI/Command.php:671
PHP   6. PHPUnit_Util_Configuration->getTestSuite() /usr/share/php/PHPUnit/Util/Configuration.php:768
PHP   7. PHPUnit_Framework_TestSuite->addTestFiles() /usr/share/php/PHPUnit/Util/Configuration.php:848
PHP   8. PHPUnit_Framework_TestSuite->addTestFile() /usr/share/php/PHPUnit/Framework/TestSuite.php:419
PHP   9. PHPUnit_Util_Fileloader::checkAndLoad() /usr/share/php/PHPUnit/Framework/TestSuite.php:358
PHP  10. PHPUnit_Util_Fileloader::load() /usr/share/php/PHPUnit/Util/Fileloader.php:79
PHP  11. include_once() /usr/share/php/PHPUnit/Util/Fileloader.php:95
PHP  12. require_once() /var/www/testfoo/foo2Test.php:3

Вот о чем этот вопрос. Хотя тестовые файлы совершенно допустимы в отдельности, PHPUnit не будет запускать тесты под тестовым набором, потому что он пытался загрузить все классы, необходимые для всего тестового набора, ДО того, как он выполнит какие-либо тесты.

На мой взгляд, PHPUnit делает не то, что нужно, выбирая зависимости, которых не должно быть для конкретного теста.

0 ответов

Другие вопросы по тегам