Vadim's Weblog

Never stop learning.

MbUnit 3.2 makes it easier to work with Xml

Posted by Vadim on July 18, 2010

In my previous article I mentioned about upcoming new release of Gallio /  MbUnit.  Feel free to download the Release Candidate and try it for yourself.  In this post I’ll talk about another new feature.

Not everybody like XML but everyone had to work with it. It’s used for many different purposes. Most people use it for configuration like web.config or .csproj / .vbproj. Some people use this format for data, others for communication. I believe that it’s going to be very hard to find a .NET developer that didn’t work with XML. If you do work with XML and you like to unit test your code, than I have good news for you. With new upcoming version 3.2 of MbUnit you are going to get better support to unit test your XML code. The Gallio team gives us three new Assert methods to test XML:

  • Assert.Xml.AreEqual
  • Assert.Xml.Exists
  • Assert.Xml.IsUnique

Assert.Xml.AreEqual

Let start by showing a simple and probably very obvious example:

        [Test]
        public void TestXmlAreEqualWithString()
        {
            const string xmlString =
                "<Books>" +
                "  <Book title='C# in Depth' />" +
                "  <Book title='Learing C#' />" +
                "</Books>";

            Assert.Xml.AreEqual(xmlString, XElement.Load(new StringReader(xmlString)).ToString());
        }

In the example above we’re comparing XML strings.  There’s another overload that instead of strings takes TextReader objects.

        [Test]
        public void TestXmlAreEqualWithTextReader()
        {
            const string xmlString =
                "<Books>" +
                "  <Book title='C# in Depth' />" +
                "  <Book title='Learing C#' />" +
                "</Books>";

            TextReader textReaderXml = new StringReader(xmlString);
            Assert.Xml.AreEqual(
                new StringReader("<Books><Book title='C# in Depth'/><Book title='Learing C#'/></Books>"),
                textReaderXml);
        }

As you can see, the formatting of XML is different, but our test still succeeds since it represents the same XML.

Let’s now make a small test.  We know that XML is case-sensitive  language.  What is going to happen if you we mismatch case?  Let’s make expected value for one of the book title ‘Learning c#’ instead of ‘Learning C#’.

        [Test]
        public void TestXmlAreEqualWithString()
        {
            const string xmlString =
                "<Books>" +
                "  <Book title='C# in Depth' />" +
                "  <Book title='Learing C#' />" +
                "</Books>";

            Assert.Xml.AreEqual(
                "<Books><Book title='C# in Depth'/><Book title='Learing c#'/></Books>",
                XElement.Load(new StringReader(xmlString)).ToString());
        }

After executing this test, we will see the following error that conveniently highlights the problem area:

AreEqual_error

Wait a second.  But what if in my application I don’t care about case-sensitivity for my data?  Well, in this case guys from the Gallio team provided us with an optional parameter of type XmlOptions.  Therefore, if we add XmlOptions.Loose parameter to our Assert.AreEqual, our test is going to pass.

            Assert.Xml.AreEqual(
                "<Books><Book title='C# in Depth'/><Book title='Learing c#'/></Books>",
                XElement.Load(new StringReader(xmlString)).ToString(), 
                XmlOptions.Loose);

You can find more information on XmlOptions in the Gallio Wiki site.

 

Assert.Xml.Exists

This assertion method checks if an element or an attribute can be found in a specific XML document.

  • The first parameter of Assert.Xml.Exists method is an Xml document.   Like in Assert.Xml.AreEqual method you can represent Xml document as a string or a TextReader object. 
  • The second parameter is an Xml Path that can be either a string in format “/element[/element]:attribute” or an object that implements IXmlPathLoose interface.
  • The third parameter is already familiar to us XmlOptions object.

Let’s look at a specific example where will check if Book element exists. 

        [Test]
        public void TestXmlExistsForElement()
        {
            const string xmlString =
                "<Books>" +
                "  <Book title='C# in Depth' />" +
                "  <Book title='Learing C#' />" +
                "</Books>";

            // Xml Path as a string
            Assert.Xml.Exists(xmlString, "/Books/Book", XmlOptions.Default);
            // Xml Path as a IXmlPathLoose
            Assert.Xml.Exists(xmlString, XmlPath.Element("Books").Element("Book"), XmlOptions.Default);
        }

For completeness let’s show a separate example where we will be looking for title attribute.

        [Test]
        public void TestXmlExistsForElement()
        {
            const string xmlString =
                "<Books>" +
                "  <Book title='C# in Depth' />" +
                "  <Book title='Learing C#' />" +
                "</Books>";

            // Xml Path as a string
            Assert.Xml.Exists(xmlString, "/Books/Book:title", XmlOptions.Default);
            // Xml Path as a IXmlPathLoose
            Assert.Xml.Exists(xmlString, XmlPath.Element("Books").Element("Book").Attribute("title"), XmlOptions.Default);
        }

In case an element or an attribute not found, Gallio will produce an error message similar to the one below:

Exists_error

Assert.Xml.IsUnique

This method takes the same parameters as Assert.Xml.ExistsAssert.Xml.IsUnique fails if an element is encountered more than once in Xml document.  I expect that you will not utilize this method as much as other two methods.

The following code is going to fail because we have two Book elements in out Xml.

        [Test]
        public void TestXmlIsUnique()
        {
            const string xmlString =
                "<Books>" +
                "  <Book title='C# in Depth' />" +
                "  <Book title='Learing C#' />" +
                "</Books>";

            // Xml Path as a string
            Assert.Xml.IsUnique(xmlString, "/Books/Book", XmlOptions.Default);
            // Xml Path as a IXmlPathLoose
            Assert.Xml.IsUnique(xmlString, XmlPath.Element("Books").Element("Book"), XmlOptions.Default);
        }

Here’s our error message:

IsUniqe_error

Last words.

I hope you find it useful and I didn’t waste mine and your time because my wife and kids never going get this hour back.

 Gallio wiki site is a great place to learn more about XML AssertionsGallio / MbUnit is an open source project and they always looking for new contributors.  If you consider joining the project, click here to learn how.

kick it on DotNetKicks.com

About these ads

3 Responses to “MbUnit 3.2 makes it easier to work with Xml”

  1. [...] See the new documention on this feature and this post by it’s author.   Hash code acceptance contract verifier     Also see this [...]

  2. [...] (go from v2.4 to v3.2) The lastest version of MBUnit makes it easier to work with XML – see MbUnit 3.2 makes it easier to work with Xml In particular for database unit testing that is a new inbuilt test method – [...]

  3. [...] (from v2.4 to v3.2). The latest version of MBUnit makes it easier to work with XML – see MbUnit 3.2 makes it easier to work with Xml For example it has an inbuilt test method – Assert.Xml.AreEqual. The advantage of using this [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: