Up and running with: XMLUnit

This is the sixth article in our series on new, popular or otherwise interesting tools used in test automation. You can read all posts within this series by clicking here.

What is XMLUnit?
From the XMLUnit.org website: XMLUnit provides you with the tools to verify the XML you emit is the one you want to create. It provides helpers to validate against an XML Schema, assert the values of XPath queries or compare XML documents against expected outcomes. The most important part is a diff-engine that provides you with full control over what kind of difference is important to you and which part of the generated document to compare with which part of your reference document.

Where can I get XMLUnit?
XMLUnit can be downloaded from the XMLUnit GitHub site. Snapshot binaries for XMLUnit 2.0 (the version that is covered in this post) can also be obtained from the Maven repository.

How do I install and configure XMLUnit?
Installing XMLUnit is as simple as downloading the latest xmlunit-core snapshot version and adding it as a dependency to your Java project.

Creating a first XMLUnittest
Let’s start with a very simple test that validates the value of a specific element of a predefined XML message:

@Test
public void aFirstTest() {
		
	Source source = Input.fromString("<foo>bar</foo>").build();
	XPathEngine xpath = new JAXPXPathEngine();
	String content = xpath.evaluate("/foo/text()", source);
	Assert.assertEquals(content, "bar");
}

Note that I have created this XMLUnit test as a TestNG test to make running the tests easier and to have TestNG automatically generate a test report.

Useful features
Using XMLUnit, XML validations can not only be done based on predefined strings containing XML, but also directly on the XML result of a call to a REST service. This is done in a very similar way:

@Test
public void restCallTest() {
		
	Source source = Input.fromURI("http://parabank.parasoft.com/parabank/services/bank/customers/12212").build();
	XPathEngine xpath = new JAXPXPathEngine();
	String content = xpath.evaluate("//city/text()", source);
	Assert.assertEquals(content, "Beverly Hills");
}

The only thing that is changed is the use of Input.fromURI instead of Input.fromString. Similar methods are available to perform XPath-based validations directly from an InputStream, a File, or a Node object, amongst others.

XMLUnit can not only perform element-based validation, it can also do a full compare of two XML messages. In this example, the XML returned by the same REST service call used in the previous example is compared against a predefined XML messages stored on the local file system (as response.xml in the messages subdirectory):

@Test
public void compareTest() {
		
	DiffBuilder db = DiffBuilder.compare(Input.fromFile("messages/response.xml")).withTest(Input.fromURI("http://parabank.parasoft.com/parabank/services/bank/customers/12212").build());
	Diff d = db.build();
		
	if(d.hasDifferences()) {
		Iterator<Difference> diffs = d.getDifferences().iterator();
		while(diffs.hasNext()) {
			Reporter.log(diffs.next().toString());
		}
	}
		
	Assert.assertEquals(d.hasDifferences(), false);
}

Any differences between the two XML files are written to the TestNG report file using the default Reporter:

XMLUnit differences written to a TestNG report

Finally, XMLUnit can also validate XML messages against an XSD document:

@Test
public void validationTest() {
		
	Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
	v.setSchemaSources(Input.fromFile("messages/orderschema.xsd").build());
	ValidationResult result = v.validateInstance(Input.fromFile("messages/order.xml").build());
		
	Iterator<ValidationProblem> problems = result.getProblems().iterator();
		
	while (problems.hasNext()) {
		Reporter.log(problems.next().toString());
	}
		
	Assert.assertEquals(result.isValid(), true);
}

Again, any issues that occur during schema validation can be written to the TestNG report using the default Reporter:

XMLUnit schema issues in TestNG report

Further reading
An Eclipse project including the tests I’ve demonstrated above and the reports that have been generated can be downloaded here.

"