Проверка подлинности 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);
}

Это хорошо работает, если у вас есть только несколько тестов, которые нужно выполнять изолированно.