Giter Club home page Giter Club logo

xmlunit's Introduction

XMLUnit for Java 2.x

Maven Central

Build Status XMLUnit 2.x for Java Coverage Status

XMLUnit is a library that supports testing XML output in several ways.

XMLUnit 2.x is a complete rewrite of XMLUnit and actually doesn't share any code with XMLUnit for Java 1.x.

Some goals for XMLUnit 2.x:

  • create .NET and Java versions that are compatible in design while trying to be idiomatic for each platform
  • remove all static configuration (the old XMLUnit class setter methods)
  • focus on the parts that are useful for testing
    • XPath
    • (Schema) validation
    • comparisons
  • be independent of any test framework

XMLUnit 1.x is no longer maintained, you can still find the old forum over at sourceforge and we still use the sourceforge provided mailing list.

Documentation

Help Wanted!

If you are looking for something to work on, we've compiled a list of known issues.

Please see the contributing guide for details on how to contribute.

Latest Release

The latest releases are available as GitHub releases or via Maven Central.

The core library is

<dependency>
  <groupId>org.xmlunit</groupId>
  <artifactId>xmlunit-core</artifactId>
  <version>x.y.z</version>
</dependency>

SNAPSHOT builds

We are providing SNAPSHOT builds from Sonatypes OSS Nexus Repository, you need to add

<repository>
  <id>snapshots-repo</id>
  <url>https://oss.sonatype.org/content/repositories/snapshots</url>
  <releases><enabled>false</enabled></releases>
  <snapshots><enabled>true</enabled></snapshots>
</repository>

to your Maven settings.

Examples

These are some really small examples, more is available as part of the user guide

Comparing Two Documents

Source control = Input.fromFile("test-data/good.xml").build();
Source test = Input.fromByteArray(createTestDocument()).build();
DifferenceEngine diff = new DOMDifferenceEngine();
diff.addDifferenceListener(new ComparisonListener() {
        public void comparisonPerformed(Comparison comparison, ComparisonResult outcome) {
            Assert.fail("found a difference: " + comparison);
        }
    });
diff.compare(control, test);

or using the fluent builder API

Diff d = DiffBuilder.compare(Input.fromFile("test-data/good.xml"))
             .withTest(createTestDocument()).build();
assert !d.hasDifferences();

or using Hamcrest with CompareMatcher

import static org.xmlunit.matchers.CompareMatcher.isIdenticalTo;
...

assertThat(createTestDocument(), isIdenticalTo(Input.fromFile("test-data/good.xml")));

or using AssertJ with XmlAssert of the xmlunit-assertj module

import static org.xmlunit.assertj.XmlAssert.assertThat;
...

assertThat(createTestDocument())
            .and(Input.fromFile("test-data/good.xml"))
            .areIdentical();

or using AssertJ with XmlAssert of the xmlunit-assertj3 module

import static org.xmlunit.assertj3.XmlAssert.assertThat;
...

assertThat(createTestDocument())
            .and(Input.fromFile("test-data/good.xml"))
            .areIdentical();

Asserting an XPath Value

Source source = Input.fromString("<foo>bar</foo>").build();
XPathEngine xpath = new JAXPXPathEngine();
Iterable<Node> allMatches = xpath.selectNodes("/foo", source);
assert allMatches.iterator().hasNext();
String content = xpath.evaluate("/foo/text()", source);
assert "bar".equals(content);

or using Hamcrest with HasXPathMatcher, EvaluateXPathMatcher

assertThat("<foo>bar</foo>", HasXPathMatcher.hasXPath("/foo"));
assertThat("<foo>bar</foo>", EvaluateXPathMatcher.hasXPath("/foo/text()",
                                                           equalTo("bar")));

or using AssertJ with XmlAssert of the xmlunit-assertj module

import static org.xmlunit.assertj.XmlAssert.assertThat;
...

assertThat("<foo>bar</foo>").hasXPath("/foo");
assertThat("<foo>bar</foo>").valueByXPath("/foo/text()").isEqualTo("bar");

or using AssertJ with XmlAssert of the xmlunit-assertj3 module

import static org.xmlunit.assertj3.XmlAssert.assertThat;
...

assertThat("<foo>bar</foo>").hasXPath("/foo");
assertThat("<foo>bar</foo>").valueByXPath("/foo/text()").isEqualTo("bar");

Validating a Document Against an XML Schema

Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
v.setSchemaSources(Input.fromUri("http://example.com/some.xsd").build(),
                   Input.fromFile("local.xsd").build());
ValidationResult result = v.validateInstance(Input.fromDocument(createDocument()).build());
boolean valid = result.isValid();
Iterable<ValidationProblem> problems = result.getProblems();

or using Hamcrest with ValidationMatcher

import static org.xmlunit.matchers.ValidationMatcher.valid;
...

assertThat(createDocument(), valid(Input.fromFile("local.xsd")));

or using AssertJ with XmlAssert of the xmlunit-assertj module

import static org.xmlunit.assertj.XmlAssert.assertThat;
...

assertThat(createDocument()).isValidAgainst(Input.fromFile("local.xsd"));

or using AssertJ with XmlAssert of the xmlunit-assertj3 module

import static org.xmlunit.assertj3.XmlAssert.assertThat;
...

assertThat(createDocument()).isValidAgainst(Input.fromFile("local.xsd"));

Requirements

Starting with version 2.8.0 XMLUnit requires Java 7, which has always been the minimum requirement for the AssertJ module. All other modules in versions 2.0.0 to 2.7.0 required Java 6. The xmlunit-assertj3 module requires Java 8 as does AssertJ 3.x itself.

The core library provides all functionality needed to test XML output and hasn't got any dependencies. It uses JUnit 4.x for its own tests.

If you want to use Input.fromJaxb - i.e. you want to serialize plain Java objects to XML as input - then you may also need to add a dependency on the JAXB implementation. For more details see the User's Guide.

The core library is complemented by Hamcrest 1.x matchers and AssertJ assertions. There also exists a legacy project that provides the API of XMLUnit 1.x on top of the 2.x core library.

While the Hamcrest matchers are built against Hamcrest 1.x they are supposed to work with Hamcrest 2.x as well.

Starting with XMLUnit 2.8.1 there are two different AssertJ modules, xmlunit-assertj is the original implementation which is based on AssertJ 2.x and also works for AssertJ 3.x but uses reflection to deal with some changes in later versions of AssertJ. The xmlunit-assertj3 module requires at least AssertJ 3.18.1.

The xmlunit-assertj module depends on an internal package not exported by AssertJ's OSGi module and thus doesn't work in an OSGi context.

Another difference between the two AssertJ modules is the exception thrown if a comparison fails. xmlunit-assertj will try to throw a JUnit 4.x ComparisonFailure if the class is available and thus is best suited for tests using JUnit 4.x. xmlunit-assertj3 will try to throw an Open Test Alliance AssertionFailedError if the class is available and thus is better suited for tests using JUnit 5.x.

Checking out XMLUnit for Java

XMLUnit for Java uses a git submodule for test resources it shares with XMLUnit.NET. You can either clone this repository using git clone --recursive or run git submodule update --init inside your fresh working copy after cloning normally.

If you have checked out a working copy before we added the submodule, you'll need to run git submodule update --init once.

Building

XMLUnit for Java builds using Apache Maven 3.x, mainly you want to run

$ mvn install

in order to compile all modules and run the tests.

xmlunit's People

Contributors

benjaminr-ps avatar benroe89 avatar beresfordt avatar bodewig avatar boiarshinov avatar brabenetz avatar cboehme avatar endrejeges avatar f-lopes avatar jawn avatar keesvandieren avatar krystiankaluzny avatar mariusneo avatar mmathesius avatar mvitz avatar nathanatclarity avatar pascalschumacher avatar phbenisc avatar thunderforge avatar zegveld avatar zheng-wang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xmlunit's Issues

Using custom Element selector I'm still unable to match correct element

Hi,
first of all thank you for this wonderful library, it's really great.

I'm having a problem comparing elements in different order within my xml document. I've developed a custom ElementSelector to use with the NodeMatcher (later the code) but still it seems to check based on element order more than element content.
Let me write an example

Control

<Parent>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email>[email protected]</Email>
</Person>
<Person>
<FirstName>Mickey</FirstName>
<LastName>Mouse</LastName>
<Email>[email protected]</Email>
</Person>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email />
</Person>
</Parent>

Test

<Parent>
<Person>
<FirstName>Mickey</FirstName>
<LastName>Mouse</LastName>
<Email>[email protected]</Email>
</Person>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email>[email protected]</Email>
</Person>
<Person>
<FirstName>John</FirstName>
<LastName>Doe</LastName>
<Email />
</Person>
</Parent>

How I made the Diff

Diff diff = DiffBuilder.compare(refSource)
                            .withTest(testSource)
                            .checkForSimilar()
                            .ignoreWhitespace()
                            .normalizeWhitespace()
                            .withNodeMatcher(new DefaultNodeMatcher(selector))
                            .build();

How I created the ElementSelector selector

ElementSelector selector = ElementSelectors.conditionalBuilder()
                            .whenElementIsNamed("Person").thenUse(new PersonNodeMatcher())
                            .defaultTo(ElementSelectors.byNameAndText).build();

How is actually implemented the PersonNodeMatcher

public class PersonNodeMatcher extends BaseElementSelector {

    @Override
    protected boolean canBeCompared(Element control, Element test) {

        String controlFirstName = control.getElementsByTagName("FirstName").item(0).getTextContent();
        String controlLastName  = control.getElementsByTagName("LastName").item(0).getTextContent();

        Node controlEmailNode = control.getElementsByTagName("Email").item(0);
        String controlEmail = null;
        if ( controlEmailNode != null) {
            controlEmail = controlEmailNode.getTextContent();
        }


        String testFirstName = test.getElementsByTagName("FirstName").item(0).getTextContent();
        String testLastName  = test.getElementsByTagName("LastName").item(0).getTextContent();


        Node testEmailNode = test.getElementsByTagName("Email").item(0);
        String testEmail = null;
        if (testEmailNode != null) {
            testEmail = testEmailNode.getTextContent();
        }

        return bothNullOrEqual(controlFirstName,testFirstName) &&
                  bothNullOrEqual(controlLastName,testLastName) &&
                  bothNullOrEqual(controlEmail,testEmail);

    }

The routine is still checking the nodes in order, so they will never match.
I thought that providing a node custom node matcher I would be able to check all the Element with the tagName provided.

Am I doing something wrong or simply is not possible?

Default to not fetching DTDs from the network

I found us having to workaround this one:

        // This is to disable DTD lookups on the internet
        DocumentBuilderFactory dbf = XMLUnit.getControlDocumentBuilderFactory();
        dbf.setFeature("http://xml.org/sax/features/validation", false);
        dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
        dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

I think that by default, at least loading external DTDs should be disabled, since I prefer to have my tests reliably pass without external factors being able to trigger failures. (I don't particularly mind validation being left turned on for DTDs which are local... and am not entirely sure why we are disabling that as well.)

Problem with choosing the proper node matcher for xml with different order of elements.

Hi,

I'm new to XMLUnit. Currently I'm trying to make a comparison of two xml documents. Their structure is similar to xml1:

<root>
<test>
<node>
<child1>test1</child1>
<child2>test2</child2>
</node>
<node>
<child1>test3</child1>
<child2>test4</child2>
</node>
</test>
</root>

and xml2:

<root>
<test>
<node>
<child2>test4</child2>
<child1>test3</child1>
</node>
<node>
<child2>test2</child2>
<child1>test1</child1>
</node>
</test>
</root>

As you can see the content is the same however the order of 'nodes' and their children differs. Currently I'm using .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.conditionalBuilder().whenElementIsNamed("test").thenUse(new ByNameAndTextRecSelector()).elseUse(ElementSelectors.byName). With this node matcher I got information about comparison with NULL. I'd like to get no differences. Can you suggest a better way how to compare this kind of content? Thank you in advance for your help!

Kind regards,
deckertm

Better difference description when using ElementSelectors.byNameAndAttributes

It'd be useful if difference description for a node that used node matcher with specific attributes, like this:
.withNodeMatcher(new DefaultNodeMatcher(
ElementSelectors.conditionalBuilder()
.whenElementIsNamed("SomeElem").thenUse(ElementSelectors.byNameAndAttributes("Attr1", "Attr2"))
.elseUse(ElementSelectors.byName).build()

would also have those attributes' values, like this:
Expected child 'SomeElem' but was 'null' - comparing <SomeElem Attr1="theValue1" Attr2="theValue2"...> at /RootElem[1]/SomeElem[16] to (DIFFERENT)

ComparisonFormatter set via DiffBuilder not used by Difference

Hello.

The the javadoc on method DiffBuilder.withComparisonFormatter(..) says:

"Sets a non-default formatter for the differences found."

My understanding is that the formatter given there will be used to format the output of all the Difference in the Diff. This is not the case, it is only used by the Diff.toString() but not by all the Differences within the Diff.

I have looked at the code and I have noticed that the "problem" is that the Difference class do not have any construction that allows to change its default formattter, When the Difference are created by class CollectResultsListener in the DiffBuilder, the non default formattter given via DiffBuilder.withComparisonFormatter(..) can not be used to replace the formatter used internally by the Difference object created.

Method Difference.toString() always use the default formatter:

@OverRide
public String toString(){
return toString(new DefaultComparisonFormatter());
}

I think it would be useful to modify the Difference class to allow setting a non default formatter in the constructor and to modify the Difference.toString() method to use it if it is given (same way as it is done for the Diff)

Is it this an issue or is it a designed decision?

If you consider it needs to be changed I could do it myself.

Cheers

Felipe

PS: Thanks for making the enter project. it is very useful :-)

Allow injection of DTD set into documents

This is a follow up ticket for the discussion started in xmlunit/user-guide#9

It would be nice to have an API that allowed the DTD of a document to get manipulated or to inject an internal DTD. The legacy module contains an support for replacing a DTD in https://github.com/xmlunit/xmlunit/blob/master/xmlunit-legacy/src/main/java/org/custommonkey/xmlunit/DoctypeInputStream.java

One approach could be a custom Source implementation inside the input package. I'm not convinced we'd need support inside the Input builder.

Port org.custommonkey.xmlunit.XMLAssert to v2 of xmlunit

With the release 2.0.0 of xmlunit the class org.custommonkey.xmlunit.XMLAssert is not anymore available.

Facility operations like :

  • assertXMLEqual
  • assertXMLNotEqual
  • assertXpathExists
  • ...

have to be written now by hand in the tests of each of the project where they are used.
It would make sense to have this class ported to a future minor release of xmlunit v2 library.
If this makes sense not only for me, I could port the XMLAssert utility class (and its corresponding tests) from xmlunit-legacy to xmlunit-core library.

`byXpath` context is unexpected

An XPath expression of "." does not select the current element but rather the document instance of a DOM document who's root element is the current element. This is not what one would expect.

Detecting new and missing elements and attributes

As part of my Testing framework project I am now at the point of having multiple blobs of XML test reports that I need to diff and report back on.

It would be useful if the XmlUnit Library could detect new and missing differences, as far as I can see it just looks for match or a difference.

Perhaps it would be useful to extend ComparisonResult to include the states new and Missing?

DocumentBuilderFactory configuration is being ignored

I am trying to compare two XHTML documents using XMLUnit 2.2.0. However, it is taking too long. I guess the library is downloading DTD files from Internet.

I thought I could disable DTD validation setting a document builder factory using the method DiffBuilder.withDocumentBuilderFactory().

I am using the following test code:

public class Test {
        public static void main(String args[]) throws ParserConfigurationException {

            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

            dbf.setValidating(false);
            dbf.setFeature("http://xml.org/sax/features/validation", false);
            dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
            dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

            Diff d = DiffBuilder.compare(
                    Input.fromString(
                         "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \n"
                        +"     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
                        +"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
                        +"     <head></head>\n"
                        +"     <body>some content 1</body>\n"
                        +"</html>")).withTest(
                    Input.fromString(                   
                         "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \n"
                        +"     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
                        +"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
                        +"     <head></head>\n"
                        +"     <body>some content 2</body>\n"
                        +"</html>")).withDocumentBuilderFactory(dbf).ignoreWhitespace().build();
            if(d.hasDifferences()) 
                for (Difference dd: d.getDifferences()) {
                    System.out.println(dd.toString());
                }
        }
}

It did not work. My code runs fast just when I remove the DOCTYPE definition from the XHTML snippets.

I have posted this issue to SO too How to disable XMLUnit DTD validation?

Different functionality in asserting XML equality between xmlunit-core and xmlunit-legacy

The pursose of this issue report is that I'd like to have a easy way to assert XML equality between the Strings :

  • "<myRootElement></myRootElement>"
  • "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><myRootElement></myRootElement>"
    when using xmlunit-core / xmlunit-matchers.

Take the following test (with xmlunit-legacy) which runs successfully

        @Test
    public void demoXMLUnitLegacySuccess() throws Exception{
        assertXMLEqual("Invalid result", "<myRootElement></myRootElement>",
                "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><myRootElement></myRootElement>");
    }

And now take the following tests (based on xmlunit-core/xmlunit-matchers):

    @Test
    public void demoXMLUnitCoreFailure(){
        assertThat("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><myRootElement></myRootElement>",
                isSimilarTo("<myRootElement></myRootElement>"));
    }

    @Test
    public void demoXMLUnitCoreWorkaroundFailure(){
        Diff diffSimilar = DiffBuilder.compare("<myRootElement></myRootElement>")
                .withTest("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><myRootElement></myRootElement>")
                .withComparisonController(new ComparisonController() {
                    @Override
                    public boolean stopDiffing(Difference difference) {
                        if (ComparisonType.XML_STANDALONE.equals(difference.getComparison().getType()) ||
                                ComparisonType.XML_ENCODING.equals(difference.getComparison().getType()) ||
                                ComparisonType.XML_VERSION.equals(difference.getComparison().getType())){
                            return false;
                        }

                        return difference.getResult().ordinal() >= ComparisonResult.DIFFERENT.ordinal();
                    }
                })
                .checkForSimilar()
                .build();
        assertFalse("Differences: " + diffSimilar.toString(), diffSimilar.hasDifferences());
    }

    @Test
    public void demoXMLUnitCoreSuccess(){
        assertThat("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><myRootElement></myRootElement>",
                isSimilarTo("<myRootElement></myRootElement>"));
    }


After investigating in detail why do the tests fail I came across a few findings :

  • in the test demoXMLUnitCoreFailure I am using CompareMatcher's isSimilarTo() method, which is syntax sugar for building a Diff via DiffBuilder
  • in the test demoXMLUnitCoreWorkaroundFailure, I've tried to naively reproduce what was done in xmlunit-legacy with ComparisonController2ComparisonController in order to skip inequality issues produced by xml_standalone inequality (by default in xmlunit-core's DiffBuilder, the StopComparisonController is used). DiffBuilder sets also a DifferenceListener , which collects the differences found, so diffSimilar.hasDifferences()will return true causing the test to fail (in xmlunit-legacy there is only a compListener IsBetweenDocumentNodeAndRootElement used).

change the control order in which nodes are pickde for compariosn

I am looking for a way to change the order in which a node is picked up for comparison.
For example,
control: <root> <a></a> <b></b> <c></c> </root>
test: <root><a></a><b></b><c></c></root>

I want the comparison to start from the node of control rather than the node. Please let me know if there is a library in xmlunit 2 for this requirement.

DiffBuilder withNamespaceContext typo

In DiffBuilder.java there is a small typo :

public DiffBuilder withNamespaceContext(Map<String, String> uri2Prefix)

should be

    public DiffBuilder withNamespaceContext(Map<String, String> prefix2Uri) {

PR follows shortly.

Untyped collections mean casting is required

Within several classes in xmlunit-legacy there are untyped collections, for example DetailedDiff.

public class DetailedDiff extends Diff {
    private final List allDifferences;
    ...
    public List getAllDifferences() {
    ...

This means users of the class will need to cast their uses of getAllDifferences - as can be seen in the unit tests in test_DetailedDiff eg:

    public void testCompareUnmatched() throws Exception {
        String control = ...;
        String test = ...;
        DetailedDiff d = (DetailedDiff) buildDiff(control, test);
        List l = d.getAllDifferences();
        assertEquals(1, l.size());
        Difference diff = (Difference) l.get(0);

As xmlunit-legacy is being compiled to 1.6, which supports generics, the collections can be typed - removing the casting burden from users of the library

(in some places in xmlunit-legacy typed collections are already being used, for example Jaxp13XpathEngine.NodeListForIterable)

Ignore tree segments in comparison

I am trying to figure out how to ignore segments of the XML structure preferably by defining a list of XPath statements to individual values or entire structures. I tried using withNodeFilter but it seems to only apply the filter to the document being compared. Causing "Expected child nodelist length" errors.
If expected result is:

<a>
<b>value1</b>
<c>value2</c>
<d>value3</d>
</a>
Ignore paths /a/b (ignore b and any children) and ignore /a/d/text() (ignore the text value of d)
Then the following document would be similar.
<a>
<c>value2</c>
<d>other text</d>
</a>
Any thoughts on how to approach this?
Brett

Not running combined with Saxon

Hey, I run into trouble after importing Saxon 9 HE.
The code works without importing the jar of Saxon. After importing it thows the exception.
It is only if I try to use ignoreWhitespace.
Any idea for a workaround. Or is this an issue?

Thanks for your help!

Diff diff_list = DiffBuilder.compare(Input.fromString(controlstr)).withTest(Input.fromString(teststr)) .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)) .checkForSimilar().**ignoreWhitespace**().ignoreComments() .withComparisonController(ComparisonControllers.Default) .build();

java.lang.ClassCastException: net.sf.saxon.value.ObjectValue cannot be cast to net.sf.saxon.om.NodeInfo at net.sf.saxon.s9api.DocumentBuilder.wrap(DocumentBuilder.java:509) at net.sf.saxon.s9api.XsltTransformer.setSource(XsltTransformer.java:214) at net.sf.saxon.jaxp.TransformerImpl.transform(TransformerImpl.java:89) at org.xmlunit.transform.Transformation.transformTo(Transformation.java:186) at org.xmlunit.transform.Transformation.transformToDocument(Transformation.java:220) at org.xmlunit.input.CommentLessSource.<init>(CommentLessSource.java:45) at org.xmlunit.builder.DiffBuilder.wrap(DiffBuilder.java:389) at org.xmlunit.builder.DiffBuilder.build(DiffBuilder.java:368) at org.artdecor.TemplateDifference.compare(TemplateDifference.java:118)

ignoreNamespacePrefix

Is there some setting that would suppress differences in namespace prefixes?
Expected namespace prefix 'env' but was 'SOAP-ENV' - comparing env:Envelope... at /Envelope[1] to SOAP-ENV:Envelope... at /Envelope[1]

Brett

How to ignore Doctype-Declarations

I use the DiffBuilder to compare two XML-Sources. The Sources do have a Doctype-Declaration at the beginning.

Is there any possibility to tell the DiffBuilder not to ignore any Schema-References, nor it should not validate any XMLs?

Thanks

Dieter

P.S.: using XMLUnit 2.1.1

XMLUnit 2 API to specify XSD for similarity for ATTR_VALUE_EXPLICITLY_SPECIFIED

Hello, I'm trying to compare two XML documents for which "control" implies a default attribute, while "test" make the attribute explicit with default value.

I have noted the DifferenceEvaluators.Default specifies for ComparisonType.ATTR_VALUE_EXPLICITLY_SPECIFIED the outcome is indeed ComparisonResult.SIMILAR as I would expected.

However I'm unable to obtain the desired output while using XMLUnit 2 API, as it does not appear to be a way to specify the XSD schema where this definition (attribute is optional with default value) is actually specified.

This is my XSD:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/schema/" targetNamespace="http://www.example.org/schema/">
    <element name="myelement">
      <complexType>
        <attribute name="myAttribute" type="string" default="myDefaultValue" use="optional"></attribute>
      </complexType>
    </element>
</schema>

This is "control" xml which implies a default attribute:

<?xml version="1.0" encoding="UTF-8"?>
<myelement  xmlns="http://www.example.org/schema/" />

This is "test" xml where the attribute is explicit with default value:

<?xml version="1.0" encoding="UTF-8"?>
<myelement  myAttribute="myDefaultValue"
            xmlns="http://www.example.org/schema/" />

I would have expected if I XMLUnit Diff-them, they should be "similar", but result actually is "different".

Here is snippet my JUnit test inlined for convenience:

@Test
public void testInline() {
    final String XSD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
            "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" xmlns:tns=\"http://www.example.org/schema/\" targetNamespace=\"http://www.example.org/schema/\">\n" + 
            "    <element name=\"myelement\">\n" + 
            "      <complexType>\n" +
            "        <attribute name=\"myAttribute\" type=\"string\" default=\"myDefaultValue\" use=\"optional\"></attribute>\n" + 
            "      </complexType>\n" + 
            "    </element>\n" + 
            "</schema>"; 

    final String explicitXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
            "<myelement  myAttribute=\"myDefaultValue\"\n" + 
            "            xmlns=\"http://www.example.org/schema/\" />";

    final String implicitXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
            "<myelement  xmlns=\"http://www.example.org/schema/\" />";

    validateAgainstXSD(XSD, explicitXML);
    validateAgainstXSD(XSD, implicitXML);

    Diff myDiff = DiffBuilder.compare( Input.fromString( implicitXML ).build() )
            .withTest( Input.fromString( explicitXML ).build() )
            .ignoreWhitespace()
            .checkForSimilar()
            .build()
            ;
    for (Difference diff : myDiff.getDifferences()) {
        System.out.println(diff);
    }
    Assert.assertFalse(myDiff.toString(), myDiff.hasDifferences());


}

private void validateAgainstXSD(final String xsdContent, final String xmlContent) {
    Validator v = Validator.forLanguage(Languages.W3C_XML_SCHEMA_NS_URI);
    v.setSchemaSource( Input.fromString( xsdContent ).build() );
    ValidationResult r = v.validateInstance( Input.fromString( xmlContent ).build()  );
    if (!r.isValid()) {
        for (ValidationProblem p : r.getProblems()) {
            System.err.println(p);
        }
    }
    assertTrue(r.isValid());
}

Both XML file validate against the XSD Schema, however test fails with result "different".

I've also checked with included JUnit test suite of XMLUnit, but the only relevant test case I found is DefaultComparisonFormatterTest.testComparisonType_ATTR_VALUE_EXPLICITLY_SPECIFIED() here: https://github.com/xmlunit/xmlunit/blob/master/xmlunit-core/src/test/java/org/xmlunit/diff/DefaultComparisonFormatterTest.java#L409
however this test is using DTD.

Is it possible to achieve the same result instead of DTD by using the XSD schema as described above, please?

ps: thank you for XMLUnit is great ! =)

Only one evaluation possible when Source is created by Input#fromString

This test:

@Test
public void test() {
    Source xml = Input.fromString("<a><b>bvalue</b><c>cvalue</c></a>").build();

    JAXPXPathEngine xpath = new JAXPXPathEngine();

    Assert.assertEquals(xpath.evaluate("//a/b", xml), "bvalue");
    Assert.assertEquals(xpath.evaluate("//a/c", xml), "cvalue");
}

fails with

org.xmlunit.XMLUnitException
at org.xmlunit.xpath.JAXPXPathEngine.evaluate(JAXPXPathEngine.java:72)
at com.tses.outcore.scaffolding.Tester.test(Tester.java:23)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: javax.xml.xpath.XPathExpressionException
at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:481)
at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:521)
at org.xmlunit.xpath.JAXPXPathEngine.evaluate(JAXPXPathEngine.java:70)
... 24 more
Caused by: java.io.IOException: Stream closed
at java.io.StringReader.ensureOpen(StringReader.java:56)
at java.io.StringReader.read(StringReader.java:90)
at org.apache.xerces.impl.XMLEntityScanner.load(Unknown Source)
at org.apache.xerces.impl.XMLEntityScanner.skipString(Unknown Source)
at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
at org.apache.xpath.jaxp.XPathImpl.evaluate(XPathImpl.java:474)
... 26 more

It works for Input#fromFile and Input#fromJaxb.

Detecting extra namespace declaration

Hello. I am using XMLUnit Java 2.4.0.

I have one control XML

<NS1:Root xmlns:NS1="http://www.example.com"/>

and two test XMLs

<NS1:Root xmlns:NS1="http://www.example.com" xmlns:NS2="http://www.mycompany.com"/>

<NS1:Root xmlns:NS1="http://www.example.com" xmlns="http://www.mycompany.com"/>

Below code outputs [identical].

Diff diff = DiffBuilder.compare(control).withTest(test).build();
System.out.println(diff);

Is there any way in XMLUnit to determine that the control XML and the test XMLs are different? I'd like to use it in unit testing to ensure the code under test does not generate garbage namespace declarations.

2.1.0 release date

Hello.

There is some 2.1.0 version release date?
I wouldlike to use some of new features without need to compile the project.

Thanks!

hamcrest required library version

What version of the hamcrest dependency is required for compiling and using xmlunit?
Compiling fails with current hamcrest 2 library because of missing BaseMatcher package,

XPathEngine#setNamespaceContext question

In the definition of the class org.xmlunit.xpath.XPathEngine I've found the following method

/**
     * Establish a namespace context.
     *
     * @param prefix2Uri maps from prefix to namespace URI.
     */
    void setNamespaceContext(Map<String, String> prefix2Uri);

which takes a Map<String, String> and internally builds (along with a helper method) a namespace context out of it.

In the definition of org.custommonkey.xmlunit.XpathEngine interface (xmlunit-legacy) the namespace context setter looked like this :

    /**
     * Establish a namespace context.
     */
    void setNamespaceContext(NamespaceContext ctx);

My question here is why was the change towards Map<String, String> from NamespaceContext parameter for the setter made during the migration from xmlunit 1.x to xmlunit 2.x ?
It seems to me that the previous setter was more appropriate for its purpose.

Difference functionality in asserting XML (with custom declaration) equality between xmlunit-core and xmlunit-legacy

Take the following test :

@Test
    public void testXMLUnitCoreExtraDeclarationFailure() throws Exception{
        String control = "<?pi content?>" +
                "<root xmlns='namespace'>" +
                "<prefix:child xmlns:prefix='namespace2'>content</prefix:child>" +
                "</root>";
        String test = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<root xmlns=\"namespace\">" +
                "<prefix:child xmlns:prefix=\"namespace2\">content</prefix:child>" +
                "</root>";

        assertThat(test, isSimilarTo(control));
    }

NOTE in the control XML the presence of <?pi content?> declaration.
The test fails when being runned with xmlunit-core.

On the other hand with xmlunit-legacy it runs successfully :

    public void testXMLUnitLegacySuccess() throws Exception{
        String control = "<?pi content?>" +
                "<root xmlns='namespace'>" +
                "<prefix:child xmlns:prefix='namespace2'>content</prefix:child>" +
                "</root>";
        String test = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<root xmlns=\"namespace\">" +
                "<prefix:child xmlns:prefix=\"namespace2\">content</prefix:child>" +
                "</root>";

        assertXMLEqual(test, control);
    }

The stacktrace of the testcase above is :

java.lang.AssertionError: 
Expected: Expected child nodelist length '2' but was '1' - comparing <root...> at / to <?xml version="1.0" encoding="UTF-8"?><root...> at /:
<root xmlns="namespace">
  ...
     but: result was: 
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="namespace">

What would be in this case the appropriate option to have the test done with xmlunit-core not taking into account the CHILD_NODELIST_LENGTH difference for the document node?

CompareMatcher throws NPE when used in combination with other matcher, and the other matcher does not match

A simple JUnit Test:

assertThat("not empty", both(Matchers.isEmptyString()).and(CompareMatcher.isIdenticalTo("")));

And this throws an NPE:

java.lang.NullPointerException
at org.xmlunit.matchers.CompareMatcher.firstComparison(CompareMatcher.java:336)
at org.xmlunit.matchers.CompareMatcher.describeTo(CompareMatcher.java:307)
at org.hamcrest.BaseDescription.appendDescriptionOf(BaseDescription.java:24)
at org.hamcrest.BaseDescription.appendList(BaseDescription.java:94)
at org.hamcrest.BaseDescription.appendList(BaseDescription.java:85)
at org.hamcrest.core.AllOf.describeTo(AllOf.java:38)
at org.hamcrest.BaseDescription.appendDescriptionOf(BaseDescription.java:24)
at org.hamcrest.core.CombinableMatcher.describeTo(CombinableMatcher.java:25)
at org.hamcrest.BaseDescription.appendDescriptionOf(BaseDescription.java:24)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:14)
at org.junit.Assert.assertThat(Assert.java:956)
at org.junit.Assert.assertThat(Assert.java:923)

Unable to ignore element order

hello,

I am using the version 2.0.0-alpha-03.
I want to compare two XML that contain the same data in a different order.
Example:

Test:


value1
value2


value3
value4

Control:


value3
value4


value1
value2

I have the same objects in my list of objects, therefore I expect to obtain a similar comparison result, as the order does not matter in my case.
My problem is that I can not find a way to achieve this result.
I always get this error: "Expected text value 'value3' but was 'value1'"
Is it possible to provide a way to easily ignore the order in such a case?

Thank's

Improve org.xmlunit.builder.Input type safety

Hi,

Do you think it makes sense to replace the conditionals in Input.from() with overloaded methods?

Builder from(Source source);

Builder from(Builder builder);

// etc.

This way, Input.fromX() methods can be eliminated and we don’t emulate polymorphism with conditional branches.

ByNameAndTextRecSelector and element order

I'm trying to do matching where the element order of elements with different names may vary. In xmlunit 1 I used RecursiveElementNameAndTextQualifier, perhaps wrongly. In xmlunit 2, I thought the user guide is saying that ByNameAndTextRecSelector should work analogously, but I'm not successful. Here's a short test. Am I reading the user guide wrong, or perhaps it could use a clarification?

import java.io.IOException;
import org.custommonkey.xmlunit.examples.RecursiveElementNameAndTextQualifier;
import org.xml.sax.SAXException;
import org.xmlunit.builder.DiffBuilder;
import org.xmlunit.builder.Input;
import org.xmlunit.diff.ByNameAndTextRecSelector;
import org.xmlunit.diff.DefaultNodeMatcher;

public class Test {

    public static void main(String[] args) throws SAXException, IOException {

        final String xml1 = "<root><a/><b/></root>";
        final String xml2 = "<root><b/><a/></root>";  // Flip <a/> and <b/>

        // xmlunit 1
        org.custommonkey.xmlunit.Diff diff1 = new org.custommonkey.xmlunit.Diff(xml1, xml2);
        diff1.overrideElementQualifier(new RecursiveElementNameAndTextQualifier());
        System.out.println("diff1.similar(): " + diff1.similar());

        // xmlunit 2
        org.xmlunit.diff.Diff diff2 = DiffBuilder
                .compare(Input.fromString(xml1))
                .withTest(Input.fromString(xml2))
                .checkForSimilar()
                .withNodeMatcher(new DefaultNodeMatcher(new ByNameAndTextRecSelector()))
                .build();
        System.out.println("diff2.hasDifferences(): " + diff2.hasDifferences());
        diff2.getDifferences().forEach(difference -> System.out.println(difference));
    }
}

xmlunit-core fails to match XMLs with changed element order

Take the unit test done with xmlunit-legacy which runs successfully :

    public void testXMLUnitLegacyElementOrderChangedSuccess() throws Exception{
        String test = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<feed xmlns=\"http://www.w3.org/2005/Atom\">" +
                "   <title>title</title>" +
                "   <entry>" +
                "       <title>title1</title>" +
                "       <id>id1</id>" +
                "   </entry>" +
                "   <entry>" +
                "       <title>title2</title>" +
                "       <id>id2</id>" +
                "   </entry>" +
                "</feed>";

        String control = "<feed xmlns=\"http://www.w3.org/2005/Atom\">" +
                "<title>title</title>" +
                "<entry><id>id1</id><title>title1</title></entry>" +
                "<entry><id>id2</id><title>title2</title></entry>" +
                "</feed>";
        XMLUnit.setIgnoreWhitespace(true);
        assertXMLEqual(test, control);
    }

The following unit test done with xmlunit-matchers doesn't run successfully :

    @Test
    public void demoXMLUnitCoreElementOrderChangedFailure(){
        String test = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                "<feed xmlns=\"http://www.w3.org/2005/Atom\">" +
                "   <title>title</title>" +
                "   <entry>" +
                "       <title>title1</title>" +
                "       <id>id1</id>" +
                "   </entry>" +
                "   <entry>" +
                "       <title>title2</title>" +
                "       <id>id2</id>" +
                "   </entry>" +
                "</feed>";

        String control = "<feed xmlns=\"http://www.w3.org/2005/Atom\">" +
                "<title>title</title>" +
                "<entry><id>id1</id><title>title1</title></entry>" +
                "<entry><id>id2</id><title>title2</title></entry>" +
                "</feed>";
        assertThat(test, isSimilarTo(control).ignoreWhitespace());
    }

The exception logged is the following :

java.lang.AssertionError: 
Expected: Expected element tag name 'id' but was 'title' - comparing <id...> at /feed[1]/entry[1]/id[1] to <title...> at /feed[1]/entry[1]/title[1]:
<id xmlns="http://www.w3.org/2005/Atom">id1</id>
     but: result was: 
<title xmlns="http://www.w3.org/2005/Atom">title1</title>

Very small documentation issue

XMLunit is something one really needs when testing against xml-files. Nice piece of work! Just what I was looking for.

I found a very, very minor documentation-only thing:

At
https://github.com/xmlunit/user-guide/wiki/DiffBuilder
in the Basic Example, I guess a not-operator is forgotten before "myDiff.hasDifferences()":

Assert.assertTrue(myDiff.toString(), ! myDiff.hasDifferences());

Also in the api (file:///home/tom/bin/ac2_tools/xmlunit-2.0.0-alpha-03/index.html) the same omission resides.

NodeMatcher that choses match with least amount of differences

Some scenarios would benefit from an NodeMatcher that simply "does what I mean": Try all possible pairings of control/test nodes and pick the permutation that contains the least number of differences (and prefer "similar" over "different").

The ElementSelector interface is not suitable since it only sees pairs of nodes but in order to be useful the implementation needs to see all candidate nodes at once.

Probably such a NodeMatcher would require quite a bit of caching of decisions already made. It would also require knowledge of the DifferenceEngine it belongs, at least to the DifferenceEvaluator. On the other hand it should not use the specified ComparisonController and certainly not inform ComparisonListeners at all while searching for candidate matches.

Of course this option would be way more expensive than carefully chosen ElementSelectors, in particular for big documents with many siblings at more than one level of the tree. Therefore it shouldn't be the default choice.

Provide a way to list child nodelists during a comparison failure of a childe nodelist length

If a comparison failure exists such that comparison.getType() == ComparisonType.CHILD_NODELIST_LENGTH, the toString() message is as follows:

Expected child nodelist length '5' but was '7' - comparing <baz...> at /foo[1]/bar[1]/baz[1] to <baz...> at /foo[1]/bar[1]/baz[1]

However, there is no way to programmatically retrieve the child nodelist from the Comparison object. This would be helpful for more thorough debugging messages, or for handling edge cases where some nodelist differences are acceptable depending on what that nodelist length is.

I would like to request a way to programmatically retrieve a list of child nodelists, from both comparison.getControlDetails() and comparison.getTestDetails()

NPE comparing qname attribute to missing attribute

Found a minor issue today using 2.0.0-SNAPSHOT, here is a unit test that produces an NPE.

    @Test
    public void temp() {
        String str1="<doc xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><effectiveTime xsi:type=\"IVL_TS\"></effectiveTime></doc>";
        String str2="<doc xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><effectiveTime></effectiveTime></doc>";
        Diff d = DiffBuilder.compare(Input.fromString(str1)).withTest(Input.fromString(str2)).build();
    }

Provide parent node XPath in Comparison$Detail

Hello,

In the case of a ComparisonType.CHILD_LOOKUP difference currently one of Comparison#control or Comparison#test has all details (target, xPath, value) "null".
For a merge (or when one wants to visualize differences) it would be nice to know the parent of the "other" side.
So I would suggest to extend Comparison.Detail with a
getParentXPath() method.
and make sure that this does return a non-null value (for all cases where a parent exists).

Note that one cannot use the available xpath from control/test, since on the "other" side the path might be different (e.g. when nodes in a list are not matched by index).

I can provide a pull request for this issue ... just wanted to discuss the solution as I did not dig that deep into this tool. Are there any other better/simpler solutions for this issue?

Thanks, Erwin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.