S
S
Stanislav2018-10-12 09:52:29
PHP
Stanislav, 2018-10-12 09:52:29

PHPUnit: What's the right way to test the classes that need to be tested and their initial creation/population?

For example, we have a class that implements the `ArrayAccess` interface. Accordingly, even just filling it with values, we are already using its functionality, which must also be tested, namely the offsetSet() method. That is, we have a test for the OffsetSet() method itself:

protected function setUp()
    {
        $this->Filter = new Filter();
    }

public function testOffsetSet()
    {
        $this->Filter[ 'page' ]        = 1;
        $this->Filter[ 'limit' ]       = 2;
        $this->Filter[ 'category_id' ] = 3;

        $this->AssertEquals($this->Filter->get_array(), [
            'page'        => 1,
            'limit'       => 2,
            'category_id' => 3,
        ]);
    }

And here we check whether the construction with square brackets will work. The get_array() method is auxiliary, we don’t touch it now, it simply returns us an array that we store in this object.
Then we start testing the following functionality, such as the offsetGet method:
public function testOffsetGet()
    {
        $this->Filter[ 'page' ]        = 1;
        $this->Filter[ 'limit' ]       = 2;
        $this->Filter[ 'category_id' ] = 3;

        echo $this->Filter[ 'page' ];
    }

And at this moment it becomes clear that in this method we use the functionality tested in another, namely the assignment through square brackets, which actually happens with the call to OffsetSet (). In general, nothing prevents me from putting this assignment in setUp() and doing it there every time, well, or writing some kind of dataProvider, but is there a better way for all this? How then to proceed, how to spread across tests (and link them themselves) the creation of the class under test, its filling with initial data, checking its filling with initial data and other tests?
I heard about @depends and even @depends clone, the first one I successfully use at the moment like this:
private $Filter;

protected function setUp()
{
    $this->Filter = new Filter();
}

protected function tearDown()
{
    unset($this->Filter);
}

/**
 * @return Filter
 */
public function testOffsetSet()
{
    $this->Filter[ 'page' ]        = 1;
    $this->Filter[ 'limit' ]       = 2;
    $this->Filter[ 'category_id' ] = 3;

    return $this->Filter;
}

/**
 * @depends testOffsetSet
 *
 * @param Filter $filter
 */
public function testGet_array($filter)
{
    $this->AssertEquals($filter->get_array(), [
        'page'        => 1,
        'limit'       => 2,
        'category_id' => 3,
    ]);
}

Questions:
Is this approach correct?
Wouldn't it be better to do the initial assignment at the setUp() stage?
And the main question is how to use @depends clone? I did not really understand the logic of this method, and indeed the semantics under which it will work.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
@
@smple, 2018-10-25
_

ArrayAccess is an interface and, accordingly, it is not necessary to test it, but specific methods of the class and check that the class implements it.
for example, let there be a Magic class that implements ArrayAccess, then MagicTest could be something like this

class MagicTest extends Test
{
   public function __setUp()
   {
       $this->magic = new Magic();
   }
   public function providerValue()
   {
     return ;// и тд
   }
   /**
    * @dataProvider providerValue
    * @depends testMustBeArrayAccesable
    */
   public function testSet($key, $value)
   {
        $this->magic[$key] = $value;
        assertSame($value, $this->magic[$key]);
   }

   public fuinction testMustBeArrayAccesable()
   {
        assertTrue($this->magic instanceof ArrayAccess);
   }
}

but it makes no sense to write a test for ArrayAccess, you need to check what is required from the class and not from its interface.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question