相似但不相同!
當(dāng)使用 IgnoreTextAndAttributeValuesDifferenceListener 類(lèi)時(shí),必須聲明這兩個(gè)文檔是 similar 而非 identical。如果錯(cuò)誤地調(diào)用了 identical,那么需要處理屬性值。
當(dāng)然,DTD 的模式和 XML 模式都有助于 XML 結(jié)構(gòu)驗(yàn)證,然而,有時(shí)文檔并不需要引用它們 —— 在這些場(chǎng)景下,結(jié)構(gòu)驗(yàn)證可能會(huì)很有用。同樣,如果需要忽略特定的一些值(例如那些 Date 值),可以實(shí)現(xiàn) DifferenceListener 接口(正如 IgnoreTextAndAttributeValuesDifferenceListener 所做的一樣)并提供一個(gè)定制實(shí)現(xiàn)。
XMLUnit 和 XPath
為實(shí)現(xiàn) XML 測(cè)試的所有三個(gè)方面,XMLUnit 還可以借助 XPath 進(jìn)行 XML 文檔特定部分的驗(yàn)證。
例如,使用清單 1 所示相同的格式,我想驗(yàn)證由應(yīng)用程序生成的第一個(gè) Class 元素的 name 屬性值是否是 com.acme.web.Widget。要實(shí)現(xiàn)此目的,我必須創(chuàng)建一個(gè) XPath 表達(dá)式來(lái)導(dǎo)航到準(zhǔn)確的位置;而且,XMLUnit 的 XMLTestCase 提供了一個(gè)方便的 assertXpathExists() 方法,這意味著我必須現(xiàn)在擴(kuò)展 XMLTestCase。
清單 8. 使用 XPath 來(lái)驗(yàn)證準(zhǔn)確的 XML 值
public void testToXMLFormatOnly() throws Exception{
BatchDependencyXMLReport report =
new BatchDependencyXMLReport(new Date(), this.getFilters());
report.addTargetAndDependencies(
"com.acme.web.Widget", this.getDependencies());
report.addTargetAndDependencies(
"com.acme.web.Account", this.getDependencies());
assertXpathExists("//Class[1][@name='com.acme.web.Widget']",
report.toXML());
}
如清單 8 所示,XMLUnit 和 XPath 一起協(xié)作提供了可以準(zhǔn)確驗(yàn)證 XML 文檔 的一種便捷機(jī)制,而不是進(jìn)行大規(guī)模的差異測(cè)試。請(qǐng)記住要在 XMLUnit 內(nèi)充分利用 XPath,您的測(cè)試用例必須要擴(kuò)展 XMLTestCase。如果熟悉 XPath 也會(huì)大有幫助!
XPath 是什么?
XPath 或 XML Path Language 是一種表達(dá)式語(yǔ)言,用來(lái)基于樹(shù)表示定位 XML 文檔的各部分。XPath 允許您導(dǎo)航 XML 文檔并可以幫您選擇文檔值。
為何要舍近求遠(yuǎn)呢?
XMLUnit 是一種基于 Java 的開(kāi)放源碼工具,它使測(cè)試 XML 文檔更為簡(jiǎn)單和靈活,而這是使用 String 比較所達(dá)不到的。使用 XMLUnit 進(jìn)行差異測(cè)試所存在的惟一缺點(diǎn)是測(cè)試會(huì)依賴(lài)于文件系統(tǒng)來(lái)加載控制文檔。在編寫(xiě)測(cè)試時(shí),請(qǐng)務(wù)必考慮這一附加的依賴(lài)性。
雖然 XMLUnit 已經(jīng)有段時(shí)間沒(méi)有發(fā)布任何更新了,但它當(dāng)前的特性集已經(jīng)足夠健壯來(lái)應(yīng)對(duì)各種測(cè)試沖擊,并且它用在這種情況下基本上是免費(fèi)的!