We say an xml is "Well Formed", if just the syntax of the xml is correct. But, let's assume you are providing a tool/framework and want users to use it in an opinionated way for easy consumption of your library, especially the xml file that the users have to create to use your tool/framework. You need to have, kind of schema, that you want users to follow, that is where DTD comes handy by providing both "Well Formed" and "Valid" xml
Since, we are talking about testng (which is a Testing framework and stands for Test Next Generation), let's take a simple tetng.xml as below.
<?xml version="1.0" encoding="UFT-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" > <suite name="Suite1" verbose="1" > <test name="Nopackage" > <classes> <class name="NoPackageTest" /> </classes> </test> <test name="Regression1"> <classes> <class name="test.sample.ParameterSample"/> <class name="test.sample.ParameterTest"/> </classes> </test> </suite>
The first line represents what xml version and encoding type we want our testng.xml to be compatible with.
- Suite in Testng is represented by tag, and can have multiple attributes passed. It can contain one or more tests, here we have two tests.
- Test tag in Testng is represented by and can contain one or more TestNG classes.
- Classes is a Testng tag represented by and holds a list of objects
- Class of Testng is a Java class that contains at least one TestNG annotation and is represented by the tag and can contain one or more test methods.
Now, comes the most important part, as per the subject of discussion of this post i.e.,
All the xml tags that we have seen above are guided by the principles defined in the Testng DTD file.
Note: It's hard to read the html file, so use a Html viewer to read through the DTD file
As part of this blog post, let's cover the small part from the original Testng's DTD file
<!-- A suite is the top-level element of a testng.xml file --> <!ELEMENT suite (listeners|packages|test|parameter|method-selectors|suite-files)* > <!-- Attributes: --> <!-- @attr name The name of this suite (as it will appear in the reports) @attr junit Whether to run in JUnit mode. @attr verbose How verbose the output on the console will be. This setting has no impact on the HTML reports. @attr parallel Whether TestNG should use different threads to run your tests (might speed up the process) @attr configfailurepolicy Whether to continue attempting Before/After Class/Methods after they've failed once or just skip remaining. @attr thread-count An integer giving the size of the thread pool to use if you set parallel. @attr annotations If "javadoc", TestNG will look for JavaDoc annotations in your sources, otherwise it will use JDK5 annotations. @attr time-out The time to wait in milliseconds before aborting the method (if parallel="methods" ) or the test (parallel="tests") @attr skipfailedinvocationCounts Whether to skip failed invocations. @attr data-provider-thread-count An integer giving the size of the thread pool to use for parallel data providers. @attr object-factory A class that implements IObjectFactory that will be used to instantiate the test objects. --> <!ATTLIST suite name CDATA #REQUIRED junit (true | false) "false" verbose CDATA #IMPLIED parallel (false | methods | tests | classes) "false" configfailurepolicy (skip | continue) "skip" thread-count CDATA "5" annotations CDATA #IMPLIED time-out CDATA #IMPLIED skipfailedinvocationCounts (true | false) "false" data-provider-thread-count CDATA "10" object-factory CDATA #IMPLIED >
We define xml comments between
<!ELEMENT suite (listeners|packages|test|parameter|method-selectors|suite-files)* >Defines that the
suiteelement must contain one or all of the elements i.e., listeners, packages etc., Let's look at another example -
<!ELEMENT test (method-selectors?,parameter*,groups?,packages?,classes?) >, in this case the element
testcan contain one or more of the mentioned elements i.e., method-selectors, parameter (or parameters), groups, packages and/or classes.
@attr - Defines the attributes that can be passed onto the
suitetag. Let's see a couple of them.
@attr nameis an attribute with name and what is the data type it can hold is defined under
<!ATTLIST test >i.e., with
name CDATA #REQUIREDwhich defines that this is of type string through
#REQUIREDwe specify that this is a mandatory attribute, we can also have
#IMPLIEDinstead if the attribute isn't mandatory.
Let's look another example,
junit (true | false) "false"here we are specifying the attribute as junit and it can have a value of either true (or) false, with default value as false.
That's it, you are now master at understanding any DTD, and most importantly you now know why you get weird errors when you don't include a DTD at the top of your xml document.
If i missed anything or you want to see part 2 of this post on specific topics of DTD, do let me know in the comments. Thanks again for reading through this (not so very interesting ;) ) article.