2012-02-19 143 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); 
    } 
}