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):

  • Make a request to an endpoint and assert the http code is 200, return the response
  • Parse the response body and do some assertions on it, return the parsed response body
  • Do some assertions on the debug values of the parsed response body
  • Make a new request to another endpoint and assert the http code is 200, return the response
  • 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

    EDIT: I should mention that my tests are extending Silex' WebTestCase, though I'm not sure if it makes a difference.

    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)
    {
        // ...
    }
    

    I think the main problem is that the tests are too complex, and should not depend that much on each other. The solution was to reduce some of the complexity by refactoring the tests. Here's a rough outline of what I did:

  • Moved some of the more complex test cases from Integration testing to Unit testing. So I'm not testing the endpoint any more, but the methods that are executed when you go to the endpoint.
  • Added a generic test case that operates on data from a data provider which includes, not exclusively, the urls to the different endpoints. This test case simply tests that the endpoints are returning the expected http code and some other small things. This allowed me to put all of my Integration testing into one simple test case.
  • I'm pretty happy with the solution, I deleted 7-8 test classes, and the complex testing that got moved to Unit testing is also simplified.

    链接地址: http://www.djcxy.com/p/64554.html

    上一篇: Dragon NaturallySpeaking程序员

    下一篇: 如何在使用数据提供者时保持较小的测试?