如何在使用数据提供程序的同时保持测试的小型化?
How to keep your tests small while using data providers?
我正在测试 Web 应用程序的 endpoints/API。我有多个小测试取决于前面测试的 return 值。一些测试甚至依赖于前面测试产生的副作用。这是一个如何进行的示例(编号列表项代表单个测试用例):
- 向端点发出请求并断言 http 代码为 200,return 响应
- 解析响应主体并对它做一些断言,return解析的响应主体
- 对已解析的响应主体的调试值进行一些断言
- 向另一个端点发出新请求并断言 http 代码为 200,return 响应
- 解析响应主体并断言测试 1 的副作用确实发生了
如您所见,测试从测试 1 开始传播,所有其他测试都取决于它的 return 值或副作用。
现在我想使用来自数据提供程序的数据执行这些测试,以测试来自我们应用程序的多个用户的行为。根据 phpunit 文档,这是不可能的。来自文档:
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.
明确一点,我想要的是测试 1 使用 y 值执行 x 次,并让所有其他测试每次都传播其 return 值或检查其副作用。
经过一些谷歌搜索后,想到的唯一解决方案是将所有测试放入一个测试中以删除所有依赖项。然而,我有多个具有这种行为的测试套件,并且一些测试会变得非常庞大和笨拙。
那么,如何在使用数据提供者的同时保持小测试用例之间的依赖关系呢?我正在使用 php 5.5 以及 Silex 1.3 和 phpunit 4.8
编辑:我应该提到我的测试正在扩展 Silex 的 WebTestCase,但我不确定它是否有所作为。
这里有一个例子,以防我不清楚:
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)
{
// ...
}
我认为主要问题是测试太复杂了,不应该太依赖彼此。解决方案是通过重构测试来降低一些复杂性。这是我所做的粗略概述:
- 从集成测试中移走了一些更复杂的测试用例
到单元测试。因此,我不再测试端点,而是在您转到端点时执行的方法。
- 添加了一个通用测试用例,该用例对来自数据提供者的数据进行操作,其中包括但不限于不同端点的 url。这个测试用例只是测试端点是否返回了预期的 http 代码和其他一些小东西。这让我可以将所有集成测试放入一个简单的测试用例中。
我对这个解决方案非常满意,我删除了 7-8 测试 类,并且移至单元测试的复杂测试也得到了简化。
我正在测试 Web 应用程序的 endpoints/API。我有多个小测试取决于前面测试的 return 值。一些测试甚至依赖于前面测试产生的副作用。这是一个如何进行的示例(编号列表项代表单个测试用例):
- 向端点发出请求并断言 http 代码为 200,return 响应
- 解析响应主体并对它做一些断言,return解析的响应主体
- 对已解析的响应主体的调试值进行一些断言
- 向另一个端点发出新请求并断言 http 代码为 200,return 响应
- 解析响应主体并断言测试 1 的副作用确实发生了
如您所见,测试从测试 1 开始传播,所有其他测试都取决于它的 return 值或副作用。
现在我想使用来自数据提供程序的数据执行这些测试,以测试来自我们应用程序的多个用户的行为。根据 phpunit 文档,这是不可能的。来自文档:
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.
明确一点,我想要的是测试 1 使用 y 值执行 x 次,并让所有其他测试每次都传播其 return 值或检查其副作用。 经过一些谷歌搜索后,想到的唯一解决方案是将所有测试放入一个测试中以删除所有依赖项。然而,我有多个具有这种行为的测试套件,并且一些测试会变得非常庞大和笨拙。
那么,如何在使用数据提供者的同时保持小测试用例之间的依赖关系呢?我正在使用 php 5.5 以及 Silex 1.3 和 phpunit 4.8
编辑:我应该提到我的测试正在扩展 Silex 的 WebTestCase,但我不确定它是否有所作为。
这里有一个例子,以防我不清楚:
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)
{
// ...
}
我认为主要问题是测试太复杂了,不应该太依赖彼此。解决方案是通过重构测试来降低一些复杂性。这是我所做的粗略概述:
- 从集成测试中移走了一些更复杂的测试用例 到单元测试。因此,我不再测试端点,而是在您转到端点时执行的方法。
- 添加了一个通用测试用例,该用例对来自数据提供者的数据进行操作,其中包括但不限于不同端点的 url。这个测试用例只是测试端点是否返回了预期的 http 代码和其他一些小东西。这让我可以将所有集成测试放入一个简单的测试用例中。
我对这个解决方案非常满意,我删除了 7-8 测试 类,并且移至单元测试的复杂测试也得到了简化。