PHPUnit: Как создать функцию, которая будет вызываться один раз для всех моих тестов? - PullRequest
55 голосов
/ 23 августа 2011

У меня есть класс тестового случая PHPUnit (состоящий из некоторых тестовых функций). Я хотел бы написать функцию oneTimeSetUp(), которая будет вызываться один раз для всех моих тестов в классе (в отличие от стандартной функции setUp(), которая вызывается один раз для каждого теста в классе). Другими словами, я ищу PHPUnit, эквивалентный аннотации JUnit @BeforeClass .

Тот же вопрос с функцией oneTimeTearDown().

Возможно ли это сделать в PHPUnit?

Ответы [ 5 ]

81 голосов
/ 23 августа 2011

Взгляните на setUpBeforeClass() из раздела 6 документации PHPUnit.

Для одноразового tearDown вы должны использовать tearDownAfterClass();.

Оба этиметоды должны быть определены в вашем классе как статические методы.

7 голосов
/ 17 февраля 2016

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

Если вы похожи на меня, ваш первый «интеграционный тест» должен очистить БД и запустить миграцию. Это дает вам базовую базу данных для всех тестов. На этом этапе я постоянно меняю файлы миграции, поэтому настройка базовых показателей действительно является частью всех тестов.

Миграция занимает некоторое время, поэтому я не хочу запускать ее во всех тестах.

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

Итак, то, что я сделал, СУПЕР легко, но не очень хорошо объясняется в интернете. Я создал простой тест для настройки базы данных. Затем в вашем файле phpspec.xml добавьте тестовый набор ....

<testsuite name="Products">
    <file>tests/in/SystemSetupTest.php</file>
    <file>tests/in/ProductTest.php</file>
    <file>tests/in/ProductImportTest.php</file>
</testsuite>

А в SystemSetupTest.php ....

class SystemSetupTest extends ApiTester
{

    /** @test */
    function system_init()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        self::createEM(); //this has all the code to init the system...
    }
}

Затем выполните это как:

phpunit --testsuite Products

В конце концов, это намного легче. Это позволит мне правильно построить свою систему.

Кроме того, я использую laravel 5. При использовании setUpBeforeClass() у меня возникают проблемы с загрузкой, которые, я уверен, я могу исправить, но метод, который я использую выше, работает отлично.

1 голос
/ 11 мая 2019

setUpBeforeClass() - это способ сделать это, если все ваши тесты буквально содержатся в одном классе.

Тем не менее, ваш вопрос предполагает, что вы можете использовать свой тестовый класс в качестве базового класса.для нескольких тестовых классов.В этом случае setUpBeforeClass будет запускаться перед каждым.Если вы хотите запустить его только один раз, вы можете защитить его статической переменной:

abstract class TestBase extends TestCase {

  protected static $initialized = FALSE;

  public function setUp() {
    if (!self::$initialized) {
      // Do something once here for _all_ test subclasses.
      self::$initialized = TRUE;
    }
  }

}

Последним вариантом может быть тестовый слушатель .

1 голос
/ 07 сентября 2018

В этих случаях можно использовать опцию bootstrap.

Вы можете вызвать его из командной строки

phpunit --bootstrap myBootstrap.php

Или поместите его в файл XML, например:

<phpunit bootstrap="myBootstrap.php">
...
</phpunit>
0 голосов
/ 09 мая 2019

Расширение принятого ответа:

Ни один из setUpBeforeClass(), tearDownAfterClass(), @beforeClass, @afterClass не выполняется в контексте объекта (статические методы). Вы можете обойти это ограничение, защитив любой код @before статическим свойством вместо этого, например так:

class MyTest extends PHPUnit\Framework\TestCase
{
    private static $ready;

    /**
     * @before
     */
    protected function firstSetUp()
    {
        if (self::$ready))
            return;

        /* your one time setUp here */

        self::$ready = true;
    }
}

Однако его нельзя использовать для @after, потому что невозможно сказать, когда был вызван последний тест.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...