2

我对单元测试概念很陌生,我坚持写我的第一个。

我有一种标准化 ID 值的方法。它应该为任何正数返回传递的值(即使它是内部带有数字的字符串),对于任何其他传递的值都应该返回零 (0)。

function normalizeId($val) {
    // if $val is good positive number return $val;
    // else return 0;
}

我想为此函数编写一个单元测试并对任何可能的参数进行断言。例如: 5, -5, 0, "5", "-5", 3.14, "fff", new StdClass()等。

我应该在我的 TestCase 类中为任何这种情况编写一个方法,还是在单独的行上使用一个所有条件的方法?IE

public function testNormalizeId() {
    $this->assertEquals(5, MyClass::normalizeId(5));
    $this->assertEquals(0, MyClass::normalizeId(-5));
    $this->assertEquals(0, MyClass::normalizeId("fff"));
}

或者

public function testNormalizeId_IfPositiveInt_GetPositiveInt() {
    $this->assertEquals(5, MyClass::normalizeId(5));
}
public function testNormalizeId_IfNegativeInt_GetZeroInt() {
   $this->assertEquals(0, MyClass::normalizeId(-5));
}
public function testNormalizeId_IfNotIntAsString_GetZeroInt() {
    $this->assertEquals(0, MyClass::normalizeId("fff"));
}

最佳实践如何?我听说第二个选择很好,但我担心很多可能的参数值有很多方法。可以是正数、负数、零、内含正数的字符串、内含负数的字符串、内含浮点数的字符串等。

编辑

或者也许是第三种方法provider

public function testNormalizeIdProvider()
{
    return array(
        array(5, 5),
        array(-5, 0),
        array(0, 0),
        array(3.14, 0),
        array(-3.14, 0),
        array("5", 5),
        array("-5", 0),
        array("0", 0),
        array("3.14", 0),
        array("-3.14", 0),
        array("fff", 0),
        array("-fff", 0),
        array(true, 0),
        array(array(), 0),
        array(new stdClass(), 0),
    );
}

/**
 * @dataProvider testNormalizeIdProvider
 */
public function testNormalizeId($provided, $expected)
{
    $this->assertEquals($expected, MyObject::normalizeId($provided));
}
4

2 回答 2

2

我对 PHP 和您可以在其中使用的单元测试框架不是很了解,但是在单元测试的一般领域中,出于这些原因,我推荐第二种方法

  • 为特定类型的输入提供特定的测试用例失败,而不必通过实际的断言失败消息来找出哪个失败。

  • 如果您决定需要对具有多个输入的特定类型的转换执行测试(例如,如果您决定有一个包含 1,000 个随机字符串的文本文件并希望将它们加载到一个测试驱动程序并运行测试用例,以便稍后通过功能或验收测试为每个条目转换字符串)

  • 当您需要一些特殊逻辑来设置时,可以更轻松地更改单个测试用例

  • 当您错过某种类型的转换时更容易发现,因为方法名称更容易根据清单读取:)

  • (可疑)可能会更容易发现您的“神级”可能需要内部重构以使用单独的子类来执行特定类型的转换(并不是说您的方法是错误的,但您可能会找到一个逻辑转换类型非常讨厌;当您查看 20 或 30 个单独的测试用例时,这些测试用例可以提供动力咬紧牙关并开发更专业的转换器类)

希望有帮助。

于 2013-10-22T19:52:05.680 回答
2

正如您自己发现的那样,使用数据提供者。在仅改变参数和期望值的多个方法中复制精确的测试用例没有任何好处。

就个人而言,对于这种简单的情况,我确实从一种方法中的所有测试开始。我会从一个简单的好案例开始,然后逐渐添加更多案例。我可能觉得不需要立即将其更改为数据提供者,因为它不会立即获得回报 - 但另一方面,事情可能会发生变化,并且此测试结构可能是需要重构的短期解决方案。

因此,每当您发现自己在这样的多测试用例方法中添加了更多测试行时,请停止并改用数据提供程序。

于 2013-10-22T21:21:31.940 回答