Fluent assertions for XML
Groovy Java Shell
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
gradle
xmlassert-assertj-java7
xmlassert-assertj-java8
xmlassert/src
.gitignore
.travis.yml
LICENSE
NOTICE
README.adoc
build.gradle
gradle.properties
gradlew
gradlew.bat
release.sh
settings.gradle

README.adoc

Build Status
Maven Central
Gitter

XML Assert

Small library for those who have a hard time understanding the complexity of XPath.

Rationale

Have you ever met such a XPath expression?

/root[matches(property1, concat('',"'",'"<>\[\]\(\)'))]

Pretty isn’t it? Wouldn’t it be better to just read:

assertThat(xml).node("root").node("property1").matches('\'"<>\\[\\]\\(\\)')

XMLAssert to the rescue!

Fast intro

Assertions

The library has a couple of main classes. One is XmlAssertion that gives you public static methods:

public static XmlVerifiable assertThat(String xml)

NOTE! The aforementioned version caches the Document for the provided XML.

and

public static XmlVerifiable assertThat(org.w3c.dom.Document parsedXml)

Both these methods give return the public XmlVerifiable interface which is a fluent interface with which you can build your XPath expression. Please check the Javadocs of that file for more information.

Building XPaths

As you could see it’s not that easy to build a XPath. With XMLAssert you can use the XPathBuilder class to finally build the XPaths yourself! This is the contract for the XPathBuilder class:

/**
 * Returns a builder of {@link XmlVerifiable} with which you can build your
 * XPath. Once finished just call {@link XmlVerifiable#xPath()} to get
 * XPath as String.
 */
public static XmlVerifiable builder()

and when you call:

XPathBuilder.builder().node("some").node("nested").array("withlist").contains("name").isEqualTo("name1").xPath();

you will receive /some/nested/withlist[name='name1'] String.

Retrieving XPath value

Wouldn’t it be great to retrieve the value from the XML via the XPath? There you go!

Note
It works only for String values
def 'should resolve the value of XML via XPath'() {
        given:
            String xml =
                    '''<?xml version="1.0" encoding="UTF-8" ?>
    <root>
        <element>
            <some>
                <nested>
                    <json>with value</json>
                    <anothervalue>4</anothervalue>
                    <withlist>
                        <name>name1</name>
                    </withlist>
                    <withlist>
                        <name>name2</name>
                    </withlist>
                    <withlist>
                        <anothernested>
                            <name>name3</name>
                        </anothernested>
                    </withlist>
                </nested>
            </some>
        </element>
        <element>
            <someother>
                <nested>
                    <json>true</json>
                    <anothervalue>4</anothervalue>
                    <withlist>
                        <name>name1</name>
                    </withlist>
                    <withlist>
                        <name>name2</name>
                    </withlist>
                    <withlist2>a</withlist2>
                    <withlist2>b</withlist2>
                </nested>
            </someother>
        </element>
    </root>'''
        expect:
            XPathBuilder.builder(xml).node("root").array("element").node("some").node("nested").node("json").read() == 'with value'
            XPathBuilder.builder(xml).node("root").array("element").node("some").node("nested").node("anothervalue").read() == 4.toString()
            assertThat(xml).node("root").array("element").node("someother").node("nested").node("json").read() == true.toString()
    }

All thanks to the XmlReader interface:

/**
 * Returns the value from the XML, based on the created XPath.
 */
String read();

How to add it

Just add it as your dependency (Example for Gradle)

testCompile 'com.toomuchcoding.xmlassert:xmlassert:0.0.2'

Dependencies

XMLAssert is really lightweight. It depends only on:

compile 'com.rackspace.eclipse.webtools.sourceediting:org.eclipse.wst.xml.xpath2.processor:2.1.100'
compile 'xerces:xercesImpl:2.11.0'
compile "ch.qos.logback:logback-classic:1.1.2"

Examples

Example 1

For the XML

 <?xml version="1.0" encoding="UTF-8" ?>
 <some>
     <nested>
         <json>with &quot;val&apos;ue</json>
         <anothervalue>4</anothervalue>
         <withattr id="a" id2="b">foo</withattr>
         <withlist>
             <name>name1</name>
         </withlist>
         <withlist>
             <name>name2</name>
         </withlist>
         <withlist>
             8
         </withlist>
         <withlist>
             <name id="10" surname="kowalski">name3</name>
         </withlist>
     </nested>
 </some>

The following is true

XMLAssert expressions:

assertThat(xml1).node("some").node("nested").node("anothervalue").isEqualTo(4)
assertThat(xml1).node("some").node("nested").node("anothervalue")
assertThat(xml1).node("some").node("nested").node("withattr").withAttribute("id", "a").withAttribute("id2", "b")
assertThat(xml1).node("some").node("nested").node("withattr").isEqualTo("foo").withAttribute("id", "a").withAttribute("id2", "b")
assertThatXml(xml1).node("some").node("nested").node("anothervalue").isEqualTo(4)
assertThat(xml1).node("some").node("nested").array("withlist").contains("name").isEqualTo("name1")
assertThat(xml1).node("some").node("nested").array("withlist").contains("name").isEqualTo("name2")
assertThat(xml1).node("some").node("nested").array("withlist").contains("name").isEqualTo("name3").withAttribute("id", "10").withAttribute("surname", "kowalski")
assertThat(xml1).node("some").node("nested").array("withlist").isEqualTo(8)
assertThat(xml1).node("some").node("nested").node("json").isEqualTo("with \"val'ue")
assertThat(xml1).node("some", "nested", "json").isEqualTo("with \"val'ue")

Respective XPath expressions:

/some/nested[anothervalue=4]
/some/nested/anothervalue
/some/nested/withattr[@id='a'][@id2='b']
/some/nested[withattr='foo']/withattr[@id='a'][@id2='b']
/some/nested[anothervalue=4]
/some/nested/withlist[name='name1']
/some/nested/withlist[name='name2']
/some/nested/withlist[name='name3']/name[@id='10'][@surname='kowalski']
/some/nested/withlist[number()=8]
/some/nested[json=concat('with "val',"'",'ue')]
/some/nested[json=concat('with "val',"'",'ue')]

More examples

More examples can be found in the XmlAssertionSpec in the test sources

Additional features

AssertJ integration

There is a possibility to use XMLAssert via AssertJ. Regardless of which version you’ll choose you have the same class that you can use to start the fluent assertion.

The standard version

com.toomuchcoding.xmlassert.XmlAssertions.assertThat(Document context);
com.toomuchcoding.xmlassert.XmlAssertions.assertThat(XmlAsString xmlAsString);
com.toomuchcoding.xmlassert.XmlAssertions.assertThat(XmlVerifiable xmlVerifiable);

or the BDD version

com.toomuchcoding.xmlassert.BDDXmlAssertions.then(Document context);
com.toomuchcoding.xmlassert.BDDXmlAssertions.then(XmlAsString xmlAsString);
com.toomuchcoding.xmlassert.BDDXmlAssertions.then(XmlVerifiable xmlVerifiable);

AssertJ 2.x

Just add

testCompile 'com.toomuchcoding.xmlassert:xmlassert-assertj-java7:0.0.2'

AssertJ 3.x

Just add

testCompile 'com.toomuchcoding.xmlassert:xmlassert-assertj-java8:0.0.2'

Contact