Hi,% username%.
In a number of projects I needed to compare XML data in tests.
Indeed, it happens that the result of the work of your module is XML data. If so, then how they are generated should be checked in accordance with the principles of
TDD . I, in turn, try to stick with them when developing.
')
Under the cut, I will try to tell you how best, in my opinion, is to test the generation of XML in code. I used
XmlUnit as an XML comparison tool.
I need to quickly and conveniently compare XML data in tests. I did not want to reinvent the wheel, and I chose the most popular
library for this purpose. In the beginning I will try to describe the list of problems that I solved.
How it all started
Once working on another project, I broke a colleague's test. When I began to study the test, I found there something like this:
@Test public void testSomeXmlGeneration() {
This is where data is generated and compared with the original from resources. For tests used
JUnit4 . I also note that, ideally, the original file should be written manually by the developer.
What's wrong with this code?I will try to justify the points.
1. Too many gestures to compare two files.
Indeed, there are a lot of movements, and if you have to compare often, then this code is copied back and forth in one form or another, which is often the case. Something to do with this prevents the lack of time.
2. There is no validation check of the generated XML code.
Due to the fact that validity was not checked, another module refused to process non-valid data, although according to tests everything was fine. I wanted to solve this problem at the test debugging stage.
3. Identical in structure and XML data may be different due to different order of tags or attributes.
For example:
Option 1 | Change the order of tags |
---|
<?xml version="1.0" encoding="UTF-8"?> <project> <name>some project</name> <description>desc</description> </project>
| <?xml version="1.0" encoding="UTF-8"?> <project> <description>desc</description> <name>some project</name> </project>
|
or so:
Option 2 | Change the order of attributes |
---|
<?xml version="1.0" encoding="UTF-8"?> <project name=”some project” description=”desc”/>
| <?xml version="1.0" encoding="UTF-8"?> <project description=”desc” name=”some project”/>
|
4. I want XML tests with formatting
In the test presented at the beginning of the article, XML data was presented without spaces or line breaks. Feel the difference:
Option 3 | Remove spaces and line breaks |
---|
<?xml version="1.0" encoding="UTF-8"?> <project> <name>some project</name> <description>desc</description> </project>
| <?xml version="1.0" encoding="UTF-8"?> <project><description>desc</description><name>some project</name></project>
|
5. Automatically processed transfers within the data.
Option 3 | Carry lines within data |
---|
<?xml version="1.0" encoding="UTF-8"?> <project> <name>some project</name> <description>desc</description> </project>
| <?xml version="1.0" encoding="UTF-8"?> <project> <name> some project </name> <description>desc</description> </project>
|
In the test considered at the beginning of the article, the source data was in one line, only tags and attributes were somewhat larger. To plant a mistake there is very simple, and correcting it so that the test passes is long and painful.
All the problems described above, I decided to eliminate the coordinate:
- use any library to compare XML and check its validity;
- rewrite all the tests so that they use this library (since they were still a little more).
After a brief search, my choice fell on
XmlUnit .
Basic ways to connect XmlUnit
The XmlUnit library is primarily a JUnit3 extension.
Its basis is the XMLTestCase class, a successor of the TestCase class from JUnit3.
Here you can see the main examples of using the class.
In practice, XmlUnit is easy to use in other test libraries. For this there is a class Diff.
So let's go
I use maven for my projects. Let's connect XmlUnit as dependence in maven. To do this, open pom.xml and add a new dependency in dependencies.
<dependencies> <dependency> <groupId>xmlunit</groupId> <artifactId>xmlunit</artifactId> <version>1.3</version> </dependency> </dependencies>
We open the test, we write there new comparison
@Test public void testSomeXmlGeneration() {
Run the test ... and does not work. A little more searching on the Internet, I found a solution. It was in the spaces between the tags. To ignore them, you need to add a pre-setting:
@Before public void setUp() throws Exception { XMLUnit.setIgnoreComments(true); XMLUnit.setIgnoreWhitespace(true); }
It seems to be all, you can enjoy the result. However, suppose we made a mistake in XML. Then we need to know exactly which tag is the problem.
The following example will help us solve it:
Notice the showXmlDiff method. In it we get a list of differences and display it.
What else can you do good?
Literature
References on which I scooped information.
UPD: According to the results of the discussion with
Lure_of_Chaos, I added another link to the list of references. There you can read about the validation of XML and about other beautiful chips, which for some reason are not written in the official documentation.
Once again, I note that XmlUnit allows you to check the validity of XML by
DTD and
XSD schemes.
As
Lure_of_Chaos correctly
pointed out , in the XSD schemes, you can require the
order in which the elements are specified . Testing this in tests is critical.
UPD2 : corrected the last
test example . Thanks,
Colwin .
That's all, thank you for your attention.