Могу ли я использовать @depends, чтобы зависеть от теста с помощью @dataProvider?

У меня есть testclass, в котором один тест выполняется несколько раз с помощью @dataProvider и другого теста, который @depends по первому методу. Однако, когда я вызывал var_dump на то, что нужно передать второму тесту, он дает мне твердый NULL, чего я не ожидал.

Другими словами: что это должно сделать:

<?php 
class DevicesTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider registerDataProvider
     */
    public function testRegister($device, $supposedResult)
    {
        //do a bunch of tests
        return array($device, $supposedResult);
    }

    public function registerDataProvider()
    {
        return array(array("foo", "foo"));
    }

    /**
     * @depends testRegister
     */
    public function testSaveDevicePreferences($deviceArr)
    {
        $this->assertNotEmpty($deviceArr);
    }
}
?>

Ответ 1

Обычно @dataProvider используется, если вы хотите выполнить тест несколько раз с разными наборами данных для каждого. Он существует, чтобы избавить вас от написания кода цикла в тесте и позволить отдельным наборам данных проходить или отказываться индивидуально.

Как я уже сказал в своих комментариях, я считаю, что PHPUnit будет использовать либо @depends либо @dataProvider, и из вашего примера я предполагаю, что второй выигрывает. Другая возможность заключается в том, что тесты с поставщиками данных не могут использоваться в качестве зависимостей, потому что PHPUnit не знает, какой набор тестовых плюс-данных выбрать.

Поскольку registerDataProvider возвращает один набор данных, вы можете так же легко вызвать его из самого теста. Это позволит @depends работать во втором тесте без @dataProvider. Предполагая, что testRegister должен изменить $device и/или $supposedResult testRegister, это должно работать:

class DevicesTest extends PHPUnit_Framework_TestCase {
    public function testRegister() {
        list($device, $supposedResult) = $this->registerDataProvider();
        //do a bunch of tests
        //register a device in the DB
        return array($device, $supposedResult);
    }

    public function registerDataProvider() {
        return array("foo", "foo");
    }

    /**
     * @depends testRegister
     */
    public function testSaveDevicePreferences($data) {
        list($device, $supposedResult) = $data;
        // do stuff dependent on testRegister()
        $this->assertEquals($device, $supposedResult);
    }
}

Если эти переменные не должны быть изменены с помощью первого теста, вы можете просто вызвать registerDataProvider из обоих тестов. Обратите внимание, что PHPUnit не будет отделять возвращаемый массив от зависимости от теста до аргументов зависимого теста, как это делает механизм поставщика данных. Это связано с тем, что он не знает, что возвращаемый массив представляет собой несколько аргументов по сравнению с одним аргументом.

Ответ 2

В текущей версии PHPUnit (5.4 на сегодняшний день) это возможно.

Согласно документации:

Когда тест получает входные данные как из метода @dataProvider, так и из одного или нескольких тестов, которые он @depends, аргументы от поставщика данных будут поступать до тех, которые зависят от тестов. Аргументы из зависимых тестов будут одинаковыми для каждого набора данных.

Вот как это выглядело бы практически:

<?php

class DataProviderAndDependsCombinationTest extends AbstractUnittest{

    public function dataProviderForSomething()
    {
        return array(
            array(
                'someProvidedValue',
                'someOtherProvidedValue'
            )
        );
    }

    public function testToDependOn()
    {
        $this->assertTrue(true);
        return 'someDependedValue';
    }

     /**
     * @dataProvider dataProviderForSomething
     * @depends testToDependOn
     */
    public function testSomething($someProvidedValue, $someOtherProvidedValue, $someDependedValue)
    {
        $this->assertSame('someProvidedValue', $someProvidedValue);
        $this->assertSame('someOtherProvidedValue', $someOtherProvidedValue);
        $this->assertSame('someDependedValue', $someDependedValue);
    }
}

Ответ 3

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

<?php 
class DevicesTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider registerDataProvider
     */
    public function testRegister($device, $supposedResult)
    {
        //do a bunch of tests
        //register a device in the DB
        return array($device, $supposedResult);
    }

    public function registerDataProvider()
    {
        return array(array("foo", "foo"));
    }

    /**
     * @depends testRegister
     * @dataProvider registerDataProvider
     */
    public function testSaveDevicePreferences($device, $supposedResult)
    {
        // do stuff dependent on testRegister()
        $this->assertEquals($device, $supposedResult);
    }
}
?>