2012-02-19 72 views
11

我写了一个API,它从另一个API获取数据并将其转换为XML。我如何使用phpunit来测试输出是否是预期的XML并且是有效的?phpunit测试xml输出

我应该创建的所有节点示例XML,然后检查输出反对呢?

回答

4

通常有两种方法:

  1. 硬编码预计为个XML字符串变量在您的测试类,并使用这些字符串与实际结果进行比较。
  2. 将预期的XML创建为常规文件系统文件,但属于您的代码库(您将它们视为resources)。在测试中加载预期文件,并再次将其与结果进行比较。

这些选项两者都是可行的,但是第一种方法(XML作为硬编码字符串变量),当个XML很大可能会有点笨拙 - 它可能是更好的将其移动到单独的文件即可。

8

作为一个我认为可以批准的搜索结果,对于遇到这个测试生成的XML馈线函数/类的问题的任何人来说,

有很多方法来测试一个XML输出是正确的,有些比其他人更容易。

我最近完成了一个类似的脚本到其OP是问在这个时候。

如果你已经从一个功能部分XML输出以下(姑且称之为$人 - >输出()):

<person> 
    <eyes>blue</eyes> 
    <hair> 
     <style>curly</style> 
    </hair> 
</person> 

首先想到的可能是使用代码,你必须生成xml和地点到测试案例进行测试,以确保该XML并没有改变,这样的事情:

function testWholeOutput() { 

    $person = new person(); 
    $person->setEyes("blue"); 
    $person->setHairStyle("curly"); 

    $this-assertEquals(file_get_contents("data\pregenerated_xml.xml"), $person->output()); 
} 

测试通过,皆大欢喜......然而,这不允许的扩张XML。另一个问题是,你从字面上测试你输出的东西,这可能会导致更多的问题。

如果一个新的功能被放在这需要发色的知识,会发生什么?测试将中断,您需要从脚本中执行另一个xml输出以确认xml输出仍然正常工作。

此外,如果测试中断,我们不知道它坏了,只是新的字符串不同于旧的字符串。

解决方案:phpUnit有一个函数调用assertTag()(和assertNotTag()),它将通过xml并可以断言标记是否存在,内容是什么,并确认它的设置是否正确。像下面的内容将不会打破,如果更多的项目被添加到XML输出:

function testOutputPersonHasEyes() { 

    $person = new person(); 
    $person->setEyes("blue"); 
    $person->setHairStyle("curly"); 

    $this->assertTag(
     array('tag' => 'person', 
     'child' => array('tag' => 'eyes') 
      ), 
      $person->output()); 
    } 

这里的assertTag正在检查一个“人”的标签,里面有一个子标签的“眼睛”。现在,如果你周围的XML输出交换到这样的事情:

<person> 
    <hair> 
      <style>curly</style> 
    </hair> 
    <eyes>blue</eyes> 
</person> 

你仍然通过上面的测试,因为这仍然是有效的XML,并且仍然有效输出,这是消耗该XML的任何脚本。

很明显,您需要编写测试以确保内容符合预期,并且其他项目是正确的,但该结构允许较少的虚假负面测试,并且从长远来看可以减少工作量,尽管会损害更多时间开发时。

对于附加功能,Tobias Schlitt wrote a great article单元测试phpUnit中的xml生成,并且还通过创建一个dom对象并使用它围绕testcase类进行封装并使用php xPath进行测试,以及一个不错的这样做的利弊解释。

+2

assertTag()和assetNotTag()被弃用的4.2版本 – 2015-02-20 12:27:05

+0

@ChrisK,@DougAmos,那么你俩有一个替代的解决方案使用PHPUnit的'assertTag()'? – Jodes 2015-08-21 08:39:58

3

它可以使用this phpunit component, phpunit-dom-assertions完成,可以使用作曲家安装。

然后使用其assertSelectEquals()代替phpunitassertTag()(现在贬值)来测试标签的内容。

所以,一个person内检查一个eyes标签,而不是:

$this->assertTag(
    array('tag' => 'person', 
    'child' => array('tag' => 'eyes') 
     ), 
     $person->output()); 
} 

这样做:

$this->assertSelectCount(
     'person > eyes', 
     true, 
     $person->output() 
    ); 

而且专门找棕色的眼睛,这样做:

$this->assertSelectEquals(
     'person > eyes', 
     'brown', 
     true, 
     $person->output() 
    ); 
4

我会这样做。 1)你的类应该使用:myClass extends PHPUnit_Framework_TestCase, 2)然后所有的测试都必须以[test]函数开始,例如是这样的:

function testFunction() 
{ 
    $testXml = '<xml><message>Hi there PHP</message></xml>'; 
    $xml = simplexml_load_string($testXml, 'SimpleXMLElement', LIBXML_NOCDATA); 

    if ($xml !== false && isset($xml->message)) { 

     //either this 
     var_dump($xml->message); 
     $this->assertEquals('Hi there PHP', $xml->message); 

     //or this, should be stdClass 
     $xmlObj = json_decode(json_encode((array) xml), 1); 
     var_dump($xmlObj->message); 
     $this->assertEquals('Hi there PHP', $xmlObj->message); 
    } 
}