如果我正在编写一个接口,我通常会指定实现应该公开的行为。为了确保这种行为,我们应该针对这个接口编写测试。我如何最好地编写和组织这些测试,以便实现的编写人员能够很容易地使用它们,以确保它们的实现满足需求?是否有某种方式扩展(编写子类)接口测试的方式,或我是否实现了一些设计模式,如工厂?
发布于 2015-03-20 11:32:25
您可以使用接口契约的一些基本测试创建一个抽象类。
考虑以下例子:
interface FactorialComputer {
public function compute($input);
}
class RecursiveFactorialComputer implements FactorialComputer {
public function compute($input) {
if ($input < 0) {
throw new InvalidArgumentException(...);
}
if ($input == 0 || $input == 1) {
return 1;
}
return $input * $this->compute($input - 1);
}
}
class IterativeFactorialComputer implements FactorialComputer {
public function compute($input) {
$result = 1;
for ($i = 1; $i <= $input; $i++) {
$result *= $i;
}
return $result;
}
}和对这两种实现的测试:
abstract class AbstractFactorialComputerTest extends PHPUnit_Framework_TestCase {
/**
* @var FactorialComputer
*/
protected $instance;
protected abstract function getComputerInstance();
public function setUp() {
$this->instance = $this->getComputerInstance;
}
/**
* @expectedException InvalidArgumentException
*/
public function testExceptionOnInvalidArgument() {
$this->instance->compute(-1);
}
public function testEdgeCases()
{
$this->assertEquals(1, $this->instance->compute(0));
$this->assertEquals(1, $this->instance->compute(1));
}
...
}
class RecursiveFactorialComputerTest extends AbstractFactorialComputerTest
{
protected abstract function getComputerInstance() {
return new RecursiveFactorialComputer();
}
public function testComputeMethodCallsCount() {
// get mock and test number of compute() calls
}
}
class IterativeFactorialComputerTest extends AbstractFactorialComputerTest
{
protected abstract function getComputerInstance() {
return new IterativeFactorialComputer();
}
}使用这种方法,每个程序员都应该能够为接口实现创建完整的单元测试。
发布于 2015-03-20 11:15:01
我明白为什么人们告诉你你不需要测试接口。但这不是你想要的。您要求为实现特定接口的多个类执行相同单元测试的更简单的方法。我使用@dataProvider注释来实现这一点(PHPUnit,是的)。
让我们假设您有以下类:
interface Shape {
public function getNumberOfSides();
}
class Triangle implements Shape {
private $sides = 3;
public function getNumberOfSides() {
return $this->sides;
}
}
class Square implements Shape {
private $sides = 4;
public function getNumberOfSides() {
return $this->sides;
}
}现在要测试Triangle getNumberOfSides的实例是否定义并返回3,而对于Square则返回4。
class ShapeTest extends PHPUnit_Framework_TestCase {
/**
* @dataProvider numberOfSidesDataProvider
*/
public function testNumberOfSides(Shape $shape, $expectedSides){
$this->assertEquals($shape->getNumberOfSides(), $expectedSides);
}
public function numberOfSidesDataProvider() {
return array(
array(new Square(), 5),
array(new Triangle(), 3)
);
}
}在这里运行phpunit将产生预期的输出:
There was 1 failure:
1) ShapeTest::testNumberOfSides with data set #0 (Square Object (...), 5)
Failed asserting that 5 matches expected 4.
/tests/ShapeTest.php:12
FAILURES!
Tests: 2, Assertions: 2, Failures: 1.https://stackoverflow.com/questions/29164814
复制相似问题