Version: 0.3.0
A simple plugin for comparing XML files with the pytest framework. The input XML file is modified with a user-defined function and the result is checked against XPath expressions. The XPath expression can also contain namespaces. This pytest plugin was generated with Cookiecutter along with @hackebrot's cookiecutter-pytest-plugin template.
pytest-xmlcomp is a plugin for pytest, which takes a XML file and transforms it with a user-defined hook. Then the script fetches user-expected XPath expressions (optionally with namespaces) from a JSON file and checks if they are available in the transformed XML file.
- pytest
- lxml
You can install pytest-xmlcomp
via pip install
from the GitHub repository:
$ pip install git+https://github.com/openSUSE/pytest-xmlcomp.git@develop
Make sure you have:
- an input XML file
- a hook
pytest_xmlcomp_transform_xml
, which modifies your input XML file into a "result" XML tree - a valid JSON file, which contains the XPath expressions you want to check against the result tree
- (optional: valid namespaces in the JSON and XML file)
--datadir
: directory which contains the XML and JSON files. You can set this insetup.cfg
orpytest.ini
as well.
Overwite the custom hook pytest_xmlcomp_transform_xml
in test/conftest.py
to modify or transform your input XML file (see below).
Define your XPath expressions in a JSON file, which can be found in the data directory. Example:
- list 'ns': contains the namespaces - first column: namespace prefix - second colum: namespace URI
- list 'data': contains the XPath expressions - first column: XPath expression - second column: expected result
{
"ns": [
["d", "http://docbook.org/ns/docbook"],
["xi", "http://www.w3.org/2001/XInclude"],
["xlink", "http://www.w3.org/1999/xlink"]
],
"data": [
["/d:doc", ["<d:doc>"]],
["/d:doc/d:foo", ["<d:foo>"]],
["/d:doc/d:bar", ["<d:bar>"]]
]
}
Note that if different namespace prefixes point to the same namespace, only the last one is used.
Make sure that the JSON file has the same basename as the XML file. An introduction to the JSON file format can be found here: www.json.org.
You can check if your JSON file adheres to its syntax before running pytest-xmlcomp. Just run:
$ python3 -m json.tool foo.json
Here is an example for a directory structure:
tests/conftest.py
(define your custom hook here)tests/data/foo
(you can place you input XML file and your JSON file here)
The hook can look like this:
# give the input XML file to the hook with "xmlfile"
def pytest_xmlcomp_transform_xml(xmlfile):
"""
Hook for transforming XML
:param xmlfile: Input XML file which will be modified
:type xmlfile: str | :class:`py.path.local`
:returns: The modified XML file.
"""
#try to get the tree of the XML file
try:
tree = etree.parse(source=str(xmlfile))
except etree.XMLSyntaxError as error:
print("XML Syntax Error in file %s:\n%s" % (xmlfile, error),
file=sys.stderr)
return None
# --- tree modification here ---
# return the modified XML tree
return tree
Here is an example for the input XML and the accompanying JSON file:
<d:doc xmlns:d="http://docbook.org/ns/docbook">
<d:foo/>
<d:bar/>
</d:doc>
{
"ns": [
["d", "http://docbook.org/ns/docbook"],
["xi", "http://www.w3.org/2001/XInclude"],
["xlink", "http://www.w3.org/1999/xlink"]
],
"data": [
["/d:doc", ["<d:doc>"]],
["/d:doc/d:foo", ["<d:foo>"]],
["/d:doc/d:bar", ["<d:bar>"]]
]
}
- Currently, you can only use a single, global hook function to transforms your XML into your result tree. It is not possible at the moment to have a more fine-granular approach where to have different functions to modify the XML in different ways.
Contributions are very welcome! Tests can be run with tox, please ensure the coverage at least stays the same before you submit a pull request.
Distributed under the terms of the GNU GPL v3.0 license, "pytest-xmlcomp" is free and open source software.
If you encounter any problems, please file an issue along with a detailed description.