前言
我在用String直接比较两个XML时,attribute的顺序不一致导致unit test fails in Jenkins,这个库完美的解决了该问题。Nexus上传的是V1.6,最新版是2.0,被完全重写,但是还没有release。 XMLUnit支持Java和.Net。
XMLUnit简介
XMLUnit使用Junit的assert风格来比较XML文档的内容和格式,它是一个开源项目。XMLUnit本身是服务一个测试系统,该系统生成并接收大量的XML文件,需要比较生成的XML和接收的XML内容是否一致。使用DTD或Schema只能验证一个XML是否正确,却不能比较两个XML的内容。
比较原理
XMLUnit比较两个XML的基本单元是difference,如果两个XML片段没有difference,则他们是identical;如果它们的difference是recoverable的,则两个XML是similiar;如果difference是unrecoverable的,则两个XML是不同的。
通常来说,两个XML文件元素或节点内容相同,顺序不同,是similiar;如果顺序也相同,则是identical。(详细内容请看:XMLUnit-Java.pdf, Chapter 3)
继承XMLTestCase比较XML
使用继承XMLTestCase方式中,assertXMLEqual(“Compare message”, xml1, xml2)时,XMLTestCase实际上市创建了一个Diff对象,Diff对象保存了比较的结果,并且提供了similar()方法和identical()方法。
assertXMLEqual()实际上是调用Diff.similar()方法,比较相似
assertXMLIdentical()实际上是调用Diff.identical(),比较相等
D4C中通常比较的是两个XML文件是否相当,所以应当调用assertXMLIdentical();
不继承XMLTestCase,手动创建Diff比较XML
如果不想继承XMLTestCase,我们可以手动创建Diff来比较两个XML文件:
继承XMLTestCase
myDiff.toString()中包含了两个XML文件的详细不匹配信息(XPath格式),帮助我们修复test。例如: junit.framework.AssertionFailedError: XML similar org.custommonkey.xmlunit.Diff [different] Expected element tag name ‘root’ but was ‘people’ – comparing at /root[1] to at /people[1]
获得比较的所有Difference
构建Diff对象的时候,只要碰到Difference,就会停下。要想得到两个XML文件的所有Difference,需要DetailedDiff,构建DetailedDiff要先创建Diff。
Get all differences
比较两个XML文件的格式
忽略节点的值和属性值:
这个类的名字好长,看来类的名字可以很长,如果这样能够让别人理解这个类的功能。我们也可以implement DifferenceListener来自定义,用以满足自己的比较需求。
修改XMLUnit的xml解析引擎
XMLUnit.setControlParser(“org.apache.xerces.jaxp.DocumentBuilderFactoryImpl”); XMLUnit.setTestParser(“org.apache.xerces.jaxp.DocumentBuilderFactoryImpl”); XMLUnit.setSAXParserFactory(“org.apache.xerces.jaxp.SAXParserFactoryImpl”); 可以使用任何的JAXP引擎,如: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl org.apache.xerces.jaxp.SAXParserFactoryImpl org.apache.xalan.processor.TransformerFactoryImpl
Issues
如果test case继承了XMLTestCase,Junit中的@Before, @BeforeClass, @After, @AfterClass将不起作用,但是@Test还会起作用。
忽略Element content的whitespace
XMLUnit.setIgnoreWhitespace(true); 去掉element content的头尾空白,相当于是trim。 下面两个XML片段,assert结果是identical:
忽略注释
XMLUnit.setIgnoreComments(true); 下面两个XML片段,assert结果是identical:
忽略CDATA
下面两个XML片段,是identical
忽略节点属性的顺序
XMLUnit.setIgnoreAttributeOrder(true);
我将setIgnoreAttributeOrder设置成false,下面的XML片段依然是identical,也许是XMLUnit将String解析成XML时,重新生成attribute的顺序了。
使用XPath局部验证XML
前提,需要继承XMLTestCase。适用于XML很大,确定其它地方没有改动,只有个别节点被改动了,为了快速,只需要验证被改动的节点。关于XPath的使用还有很多,下面是最基本的使用。
参考文档: