Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide unordered collection diff support #111

Open
izeye opened this issue Feb 26, 2018 · 8 comments
Open

Provide unordered collection diff support #111

izeye opened this issue Feb 26, 2018 · 8 comments

Comments

@izeye
Copy link

izeye commented Feb 26, 2018

The current implementation of Diff looks to have an assumption that collection is ordered and doesn't look there's any switch to the assumption so that unordered collections can be handled.

It would be nice to provide unordered collection diff based on XML schema.

This is a test to illustrate what I'm trying to suggest: https://github.com/izeye/samples-java-branches/blob/master/src/test/java/learningtest/org/xmlunit/diff/DiffTests.java#L62-L82

@bodewig
Copy link
Member

bodewig commented Feb 27, 2018

XMLUnit is not aware of XML-Schema when it calculates differences, although this would be a great enhancement see also #88 .

If element order is not significant for you, you can tell the difference engine by providing a DifferenceEvaluator. In your example

    .withDifferenceEvaluator(DifferenceEvaluators.chain(
        DifferenceEvaluators.Default,
        DifferenceEvaluators.downgradeDifferencesToSimilar(ComparisonType.CHILD_NODELIST_SEQUENCE)
    ))

should work.

izeye added a commit to izeye/samples-java-branches that referenced this issue Feb 28, 2018
@izeye
Copy link
Author

izeye commented Feb 28, 2018

@bodewig Thanks for the quick feedback!

Global switch for unordered collection will work for my immediate needs but the suggestion didn't work for me. It might be a fault on my end when applying your suggestion as I'm almost new to XMLUnit.

This is what I tried with your suggestion: https://github.com/izeye/samples-java-branches/blob/master/src/test/java/learningtest/org/xmlunit/diff/DiffTests.java#L88-L105

@bodewig
Copy link
Member

bodewig commented Feb 28, 2018

Ah, in your case XMLUnit simply doesn't compare the elements you probably want it to compare.

The person elements are siblings and you tell XMLUnit to match elements by their names and nested text. The person elements haven't got any nested text themselves, so XMLUnit picks them in order and you end up comparing the wrong persons - and thus see differences. I'd recommend using the Hamcrest matchers or include diff.toString() in your assertThat so that you can better see what kind of differences have been detected.

In order to make your test pass you need to help XMLUnit matching the correct persons. It looks as if your person element was defined by the nested text of the id child element. In that case something like

.withNodeMatcher(new DefaultNodeMatcher(conditionalBuilder()
    .whenElementIsNamed("person").thenUse(byXPath("./id", byNameAndText))
    .elseUse(byNameAndText)
    .build())

should work, I haven't tried it. (just assume there was a static import on ElementSelectors so I can save typing :-))

See https://github.com/xmlunit/user-guide/wiki/SelectingNodes for all the details.

izeye added a commit to izeye/samples-java-branches that referenced this issue Feb 28, 2018
@izeye
Copy link
Author

izeye commented Feb 28, 2018

@bodewig Thanks again for the quick response!

I think I understand your first advice now thanks to your second advice and I updated my tests based on it: https://github.com/izeye/samples-java-branches/blob/master/src/test/java/learningtest/org/xmlunit/diff/DiffTests.java#L89-L123

Both work like a charm 👍

I'm happy with the current solution for now but I'd like to keep this issue open for a possible enhancement based on XML schema for ordered and unordered mixed documents diff.

@bodewig
Copy link
Member

bodewig commented Feb 28, 2018

Glad it worked.

Keeping the issue open as an enhancement request is fine with me, I've labeled it accordingly.

@bodewig bodewig added the core label Feb 28, 2018
@michailangelo
Copy link

michailangelo commented Jul 2, 2019

If the strings were like this :

String xml1 = <persons><person><id>1</id><name><firstName>Johnny</firstName></name></person><person><id>2</id><name><firstName>John</firstName></name></person></persons>
String xml2 = <persons><person><id>2</id><name><firstName>John</firstName></name></person><person><id>1</id><name><firstName>John</firstName></name></person></persons>

How would you use multiple selectors to make the comparison?

@bodewig
Copy link
Member

bodewig commented Jul 2, 2019

@michailangelo I think this is a different question, so please open a new issue.

@michailangelo
Copy link

I thought this is relevant to the discussion before but I opened a new issue anyway :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants