@@ -413,64 +413,6 @@ XPath expression assertions
413413 # ...
414414
415415
416- XML documents comparison assertion
417- ----------------------------------
418-
419- .. py :method :: XmlTestMixin.assertXmlEquivalent(got, expect)
420-
421- :param got: XML as text or Element node
422- :param expect: XML as text
423-
424- Asserts both XML are equivalent. The comparison ignores spaces within nodes
425- and namespaces - if any - may be associated to diffrerent prefixes.
426-
427- If a difference is found, a :class: `AssertionError ` is raised. You can have
428- the detailed mismatch in ``str(exc) ``, ``exc `` being the raised exception.
429-
430- .. rubric :: Example
431-
432- ::
433-
434- # ...
435-
436- def test_custom_test(self):
437- # Same XML (with different spacings placements and attrs order)
438- got = b"""<?xml version="1.0" encoding="UTF-8" ?>
439- <root>
440- <tag foo="bar" bar="foo">foo</tag>
441- </root>"""
442- got_root = self.assertXmlDocument(got)
443- expected = b"""<?xml version="1.0" encoding="UTF-8" ?>
444- <root><tag bar="foo" foo="bar"> foo </tag></root>"""
445-
446- self.assertXmlEquivalent(got, expected)
447- self.assertXmlEquivalent(got_root, expected)
448-
449- # Same XML, but with different namespace prefixes
450- got = b"""<?xml version="1.0" encoding="UTF-8" ?>
451- <root xmlns:foo="mynamespace">
452- <foo:tag>foo</foo:tag>
453- </root>"""
454- got_root = self.assertXmlDocument(got)
455- expected = b"""<?xml version="1.0" encoding="UTF-8" ?>
456- <root xmlns:bar="mynamespace">
457- <bar:tag>foo</bar:tag>
458- </root>"""
459- self.assertXmlEquivalent(got, expected)
460- self.assertXmlEquivalent(got_root, expected)
461-
462- # Check comparison failure
463- got = b"""<?xml version="1.0" encoding="UTF-8" ?>
464- <root xmlns:foo="mynamespace">
465- <foo:tag> difference here </foo:tag>
466- </root>"""
467- got_root = self.assertXmlDocument(got)
468- with self.assertRaises(self.failureException):
469- self.assertXmlEquivalent(got, expected)
470- with self.assertRaises(self.failureException):
471- self.assertXmlEquivalent(got_root, expected)
472-
473-
474416XML schema conformance assertion
475417--------------------------------
476418
@@ -648,3 +590,78 @@ your own schema objects in these various schema languages.
648590 """
649591 root = test_case.assertXmlDocument(data)
650592 self.assertXmlValidRelaxNG(root, filename=relaxng_filename)
593+
594+
595+ XML documents comparison assertion
596+ ----------------------------------
597+
598+ Sometimes, one may want to check a global XML document, because he know exactly
599+ what is expected, and can rely on a kind of "string compare". Of course, XML
600+ is not a simple string, and requires more than just an
601+ ``assert data == expected ``, because order of elements can vary, order of
602+ attributes, etc.
603+
604+ In these cases, one can use the powerful - also dangerous - feature of `LXML
605+ Output Checker `. See also the documentation of the module
606+ `doctestcompare <http://lxml.de/api/lxml.doctestcompare-module.html >`_ for
607+ more information on the underlying implementation.
608+
609+ And as always, remember that the whole purpose of this :py:mod: `xmlunittest `
610+ is to **not ** compare XML formated string. But, whatever, this function could
611+ help. May be.
612+
613+ .. py :method :: XmlTestMixin.assertXmlEquivalentOutputs(data, expected)
614+
615+ :param string data: XML formated string to check
616+ :param string expected: XML formated string used as reference
617+
618+ Asserts both XML formated string are equivalent. The comparison ignores
619+ spaces within nodes and namespaces may be associated to diffrerent prefixes,
620+ thus requiring only the same URL.
621+
622+ If a difference is found, an :py:exc: `AssertionError ` is raised, with the
623+ comparison failure's message as error's message.
624+
625+ .. note ::
626+
627+ The name ``assertXmlEquivalentOutputs `` is cleary a way to prevent user
628+ to missunderstand the meaning of this assertion: it checks only similar
629+ **outputs **, not **document **.
630+
631+ .. note ::
632+
633+ This method only accept ``string `` as arguments. This is an opinionated
634+ implementation choice, as the purpose of this method is to check
635+ the result outputs of an XML document.
636+
637+
638+ .. rubric :: Example
639+
640+ ::
641+
642+ # ...
643+
644+ def test_custom_test(self):
645+ """Same XML (with different spacings placements and attrs order)"""
646+ # This XML string should come from the code one want to test
647+ data = b"""<?xml version="1.0" encoding="UTF-8" ?>
648+ <root><tag bar="foo" foo="bar"> foo </tag></root>"""
649+
650+ # This is the former XML document one can expect, with pretty print
651+ expected = b"""<?xml version="1.0" encoding="UTF-8" ?>
652+ <root>
653+ <tag foo="bar" bar="foo">foo</tag>
654+ </root>"""
655+
656+ # This will pass
657+ test_case.assertXmlEquivalentOutputs(data, expected)
658+
659+ # This is another example of result, with a missing attribute
660+ data = b"""<?xml version="1.0" encoding="UTF-8" ?>
661+ <root>
662+ <tag foo="bar"> foo </tag>
663+ </root>
664+ """
665+
666+ # This won't pass
667+ test_case.assertXmlEquivalentOutputs(data, expected)
0 commit comments