mercredi 30 mars 2016

How to keep your tests small while using data providers?

I am testing the endpoints/API of a web application. I have multiple small tests that depend on the return values of the preceding tests. Some of the tests even depend on side effects that are made by the preceding tests. Here's an example of how it goes (the numbered list items represent individual test cases):

  1. Make a request to an endpoint and assert the http code is 200, return the response
  2. Parse the response body and do some assertions on it, return the parsed response body
  3. Do some assertions on the debug values of the parsed response body
  4. Make a new request to another endpoint and assert the http code is 200, return the response
  5. Parse the response body and assert that the side effects from test 1 actually took place

As you can see the tests sort of propagate from test 1, and all the other tests depend on its return value or side effects.

Now I want to execute these tests with data from a data provider to test the behavior with multiple users from our application. According to the phpunit documentation, this is not possible. From the docs:

When a test depends on a test that uses data providers, the depending test will be executed when the test it depends upon is successful for at least one data set. The result of a test that uses data providers cannot be injected into a depending test.

Just to be clear, what I want is for test 1 to execute x number of times with y values, and have all the other tests propagate its return value or check its side effects each time. After some googling, the only solution that comes to mind is to put all the tests into one single test to remove all dependencies. However I have multiple test suites with this behavior, and some of the tests would get really big and unwieldy.

So, how can I keep the dependencies between small test cases while using data providers? I'm using php 5.5 along with Silex 1.3 and phpunit 4.8

Here's an example in case I was unclear:

public function testValidResponse()
{
    $client = $this->createClient();
    $client->request('POST', '/foo', $this->params);
    $this->assertEquals(200, $client->getResponse()->getStatusCode());
    return $client->getResponse();
}

/**
 * @depends testValidResponse
 */
public function testStatusIsOk(Response $response)
{
    $json = json_decode($response->getContent(), true);
    $this->assertTrue($json['status']);
    return $json;
}

/**
 * @depends testStatusIsOk
 */
public function testExecutionTime($json)
{
    $this->assertLessThan($this->maxExecutionTime, $json['debug']['executionTimeSec']);
}

/**
 * @depends testValidResponse
 */
public function testAnotherEndpointValidResponse()
{
    $client = $this->createClient();
    $client->request('GET', '/bar');
    $this->assertEquals(200, $client->getResponse()->getStatusCode());
    return $client->getResponse();
}

/**
 * @depends testAnotherEndpointValidResponse
 */
public function testSideEffectsFromFirstTest(Response $response)
{
    // ...
}

Aucun commentaire:

Enregistrer un commentaire