我如何构建一个PHPUnit assertTag()匹配器来匹配这样的HTML表?

时间:2011-09-13 15:51:52

标签: php html phpunit

我正在尝试验证HTML表格是否具有给定ID,并且有2行,每行包含4个单元格。

这是我尝试过的匹配器定义,据我所知,应该有效:

$matcher = array(
    'tag' => 'table',
    'attributes' => array('id' => 'peopleLarge'),
    'children' => array(
        'count' => 2,
        'only' => array(
            'tag' => 'tr',
            'children' => array(
                'count' => 4,
                'only' => array(
                    'tag' => 'td'
                )
            )
        )
    )
);

$this->assertTag($matcher, $sOutput);

正在测试的输出是:

<table id="peopleLarge">
    <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
    </tr>
    <tr>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
    </tr>
</table>

但是,此测试总是失败。

我认为我正在编写匹配器定义错误,那么有谁知道更多关于PHPUnit的信息,那么我可以帮助我吗?

PHPUnit的输出如下:

PHPUnit_Framework_ExpectationFailedException : Failed asserting that <boolean:false> is true.
#0 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\Assert.php(2087): fail()
#1 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\Assert.php(756): assertThat()
#2 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\Assert.php(2048): assertTrue()
#3 C:\_company\t\timeforchildren\webroot\tests\app\views\People_View_LargeTest.php(93): assertTag()
#4 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\TestCase.php(738): invokeArgs()
#5 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\TestCase.php(628): runTest()
#6 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\TestResult.php(666): runBare()
#7 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\TestCase.php(576): run()
#8 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\TestSuite.php(757): run()
#9 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\Framework\TestSuite.php(733): runTest()
#10 C:\wamp\bin\php\php5.3.0\PEAR\PHPUnit\TextUI\TestRunner.php(305): run()
#11 C:\Users\Nils\AppData\Local\Temp\phpunit_webroot_Nils.php(485): doRun()
#12 C:\Users\Nils\AppData\Local\Temp\phpunit_webroot_Nils.php(750): runTest()
#13 C:\Users\Nils\AppData\Local\Temp\phpunit_webroot_Nils.php(853): main()

非常感谢,

2 个答案:

答案 0 :(得分:3)

是的,assertTag()的输出很糟糕。

我建议将其分解为多个断言和/或测试。我认为您收到错误的原因是它在 'count' => 4 行上感到困惑。

我发现,一种好的技术是逐渐构建$matcher数组,当你收到错误时,这就是问题所在。相反,您可以编写整个内容,然后将其全部注释掉并逐渐删除注释。

当评论该特定行时,断言成功。如果没有评论,我会遇到同样的错误。

这是一个奇怪的部分:如果你输入的值其他而不是4,例如5,你会得到一个不同的错误:

Invalid argument supplied for foreach()

我认为它可能会变得混乱,因为当孩子数量本身&gt;时,你会计算孩子的孩子(孙子,如果你愿意的话)。 1.我尝试使用值“8”,因为从技术上讲,您的HTML包含 8 td,它们是tr的子项,但是显示了foreach()错误。

建议:

  1. 分成多个断言和/或测试。可能是一个单独的基于正则表达式的断言来确认各种元素和层次结构的计数

  2. 提示,不仅仅是建议:没有必要这样做

    'attributes' => array('id' => 'peopleLarge'),
    

    相反,您可以这样做:

    'id' => 'peopleLarge',
    

    (ID本身就是assertTag()的标准)

答案 1 :(得分:2)

我通常使用xpath添加一些自定义匹配器。这些自定义匹配器可以包含更多描述性消息。

在你的情况下

private function assertHasXpath($xpath, $message = '', $group = 'Other') {
  if (empty($message)) {
    $message = "xpath '{$xpath}' not found.";
  }
  $xpath = $this->xpath($xpath);
  $truthiness = count($xpath) > 0;
  return $this->assertTrue($truthiness, $message, $group);
}

private function assertHasTableWithColumns($amount_columns, $message = '', $group = 'Other') {
  $xpath = "//*//table/tr/td";
  $amount_found = count($this->xpath($xpath))

  if (empty($message)) {
    $message = "No table with {$amount_columns} found. Found {$amount_found}";
  }
  return $this->assertTrue(($amount_found == $amount_columns), $message, $group);
}

然后,您可以编写非常具有描述性和可读性的测试(即测试应该是什么)。

public function testHasTitleWithPeople() {
  $this->drupalGet("people");
  $this->assertHasXpath("//*/h2[@class='title'][contains(text(),'People')]");
  // This pattern is complex enough to warrant its own assertTitleWithContent($content)

}

public function testRendersTable() {
  $this->drupalGet("people");
  $this->assertHasTableWithColumns(4);
}