Проверка подлинности phpunit
Я запускаю серию тестов в phpunit, которые существуют в отдельных testuites, список которых контролируется файлом конфигурации phpunit. Когда тесты запускаются индивидуально (т.е. Не через файл конфигурации и, следовательно, начиная с testuite за один раз), они проходят, но при запуске вместе я получаю сбой.
При закрытом изучении проблема заключается в том, что каждый из этих testuite загружается в фреймворк (через require_once), и эта структура выполняет некоторую внутреннюю конфигурацию, основанную на настройках во время require_once. Похоже, что между запуском testuites, отдельно указанным в файле конфигурации phpunit, сохраняются различные вещи. В этом конкретном случае структура уже рассматривается как загруженная.
Итак, есть ли способ заставить phpunit выполнять последовательность тестов, независимо от того, что происходит с запуском phpunit на тестах по одному за раз? (phpunit запускается cruisecontrol на автотестовой машине и локально разработчиками перед отправкой.) Я пробовал варианты, такие как "-process-изоляция" и "-no-globals-backup" без успеха.
Быстрый пример, который иллюстрирует проблему, будет файл констант. php:
<?php
if (defined('XYZZY')) define('TEST', 1);
else define('TEST', 2);
testuite 'TestOne.php':
<?php
define('XYZZY', "");
require_once('constant.php');
class TestOne extends PHPUnit_Framework_TestCase
{
public function testOne()
{
$this->assertEquals(TEST, 1);
}
}
аналогичный testuite 'TestTwo.php':
<?php
require_once('constant.php');
class TestTwo extends PHPUnit_Framework_TestCase
{
public function testTwo()
{
$this->assertEquals(TEST, 2);
}
}
и конфигурационный файл phpunit:
<phpunit>
<testsuites>
<testsuite name="First">
<file>./TestOne.php</file>
</testsuite>
<testsuite name="Second">
<file>./TestTwo.php</file>
</testsuite>
</testsuites>
</phpunit>
Ответы
Ответ 1
Я пытаюсь предоставить вам некоторые рабочие примеры --process-изоляция и глобальную резервную копию.
Надеюсь, вы сможете работать с этими тестами. Если не просто оставить мне комментарий, и я увижу, чтобы вернуться к вам.
Я тестировал большую часть этого с 3.4.15, и все против HEAD (3.5.x тоже ожидается)
Самый простой способ сделать это:
<?php
class Test extends PHPUnit_Framework_TestCase
{
public function testOne()
{
define('FOO', 'BAR');
$this->assertEquals('BAR', FOO);
}
public function testTwo()
{
define('FOO', 'BAZ');
$this->assertEquals('BAZ', FOO);
}
}
и производит:
phpunit - процесс изоляции процессаTest.php
PHPUnit @package_version @Себастьяна Бергмана.
..
Время: 0 секунд, Память: 1.25Mb
ОК (2 теста, 2 утверждения)
Итак, строите из этого, если вы группируете свой тест в testuites или можете запустить настройку для каждого тестового теста (в зависимости от того, насколько это дорого) вы можете пойти с чем-то простым:
<?php
class Test extends PHPUnit_Framework_TestCase
{
public function setUp()
{
// your bootstrap for testsuite X
// Maybe put this in a baseclass for that suite ?
}
public function testOne()
{
$this->assertEquals('BAR', FOO);
}
Короче
Убедитесь, что вы запустили свой установочный код ПОСЛЕ того, как вы ввели тест (и изоляцию процесса)
Если все остальное не работает, и вы/не можем решить это:
С расширением runkit
(небезопасным ни для чего, даже для NEAR-производства, для использования в крайнем случае) вы можете вызывать такие функции, как runkit-constant-remove()
Надеюсь, это поможет литте. Если нет: дайте мне знать
Ответ 2
Я столкнулся с подобной проблемой и натолкнулся на другой способ сделать это, возможно, не был доступен в тот момент, когда этот вопрос изначально был задан.
В моем случае мне пришлось протестировать некоторый унаследованный код, который проверял глобальную константу, и выполнил определенное действие, если оно было установлено. Это было достаточно легко, но после define
с константой в одном тесте она сохранялась в оставшихся тестах. Чтобы изменить это поведение, PHPUnit предоставляет @runInSeparateProcess и @preserveGlobalState аннотации.
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function test_presence_of_constant() {
define('SOME_OVERRIDE', 'true');
$result = $this->target->legacyMethod();
$this->assertEquals('thereWasSomeOverride', $result);
}
Это хорошо работает, если у вас есть только несколько тестов, которые нужно выполнять изолированно.