Validating Xml with a Schema in an NUnit Test (.NET 3.5/C#)

Recently we decided to make some updates to our web app. The front end website is in ASP.NET/C#, while the back end is all in Java and using REST APIs as the interface. One pair of programmers was assigned the task of updating the web app and the other pair was assigned the task of writing the new REST service used by the web app. To ensure that both sides would be able to talk to each other when completed, we wrote an XML Schema to act as our contract and placed it in an SVN external available to both projects.

In our functional test for the REST client side code (.NET/C#) we used a stub from which we could grab the XML being sent. To test that this XML conformed to the schema (contract) we agreed to, we created the following helper class:

Xml Validator Helper Class

using System;
using System.Xml;
using System.Xml.Schema;
using System.IO;

namespace Test.Helper
{
	public class XmlValidatorTestHelper
	{
		private bool isValidXml = true;
		private string validationError = "";

		public String ValidationError
		{
			get { return "Validation Error: " + validationError; }
			set { validationError = value; }
		}

		public bool IsValidXml
		{
			get { return isValidXml; }
		}

		/// 
		/// Validate an xml document against an xml schema.
		/// 
		public void ValidXmlDoc(XmlDocument xmlDocument, XmlSchema xmlSchema)
		{
			validateParameters(xmlDocument, xmlSchema);
			XmlReader xmlReader = createXmlReader(xmlDocument, xmlSchema);
					
			try
			{
				// validate        
				using (xmlReader)
				{
					while (xmlReader.Read())
					{}
				}
				isValidXml = true;
			}
			catch (Exception ex)
			{
				ValidationError = ex.Message;
				isValidXml = false;
			}
		}

		private static void validateParameters(XmlDocument xmlDocument, XmlSchema xmlSchema)
		{
			if (xmlDocument == null)
			{
				new ArgumentNullException("ValidXmlDoc() - Argument NULL: XmlDocument");
			}
			if (xmlSchema == null)
			{
				new ArgumentNullException("ValidXmlDoc() - Argument NULL: XmlSchema");
			}
		}

		private static XmlReader createXmlReader(XmlDocument xmlDocument, XmlSchema xmlSchema)
		{
			StringReader xmlStringReader = convertXmlDocumentToStringReader(xmlDocument);
			XmlReaderSettings xmlReaderSettings = new XmlReaderSettings 
                        { 
                               ValidationType = ValidationType.Schema 
                        };
			xmlReaderSettings.Schemas.Add(xmlSchema);
			return XmlReader.Create(xmlStringReader, xmlReaderSettings);
		}

		private static StringReader convertXmlDocumentToStringReader(XmlDocument xmlDocument)
		{
			StringWriter sw = new StringWriter();
			xmlDocument.WriteTo(new XmlTextWriter(sw));
			return new StringReader(sw.ToString());
		}
	}
}

Surfacing Validation Errors in your Test

Finding out that the XML our REST client produces matches the contract is great, however when it fails it would save a lot of time if the test just showed WHY validation failed. No problem, in our validation helper class we added a property to allow us to retrieve the validation error message in the event the test failed and output that as the failure message for the test:

XmlValidatorTestHelper xmlSchemaValidator = new XmlValidatorTestHelper();
XmlSchema myXmlSchema = XmlSchema.Read(...);
XmlDocument myXmlDocument = new XmlDocument();
myXmlDocument .Load(...);
xmlSchemaValidator.ValidXmlDoc(myXmlDocument, myXmlSchema);

Assert.IsTrue(xmlSchemaValidator.IsValidXml, "XML does not match Schema: " + xmlSchemaValidator.ValidationError);

The Pitfalls of Local Optimization

Recently I was on a project where our business team came to us and asked us to build a new service (Let’s call it feature X). Our development team immediately got together and started working out the details: what database to use, programming language, service type (e.g., REST), etc. However, during these first few days of discussion there was one question that was bugging all of us developers:

“Where is the business value in building feature X”

Since we were all curious and wanted to have an answer to this question, we finally grabbed some members of our business and marketing teams and posed this exact question. Our business team responded by outlining three key points where feature X would excite our customers and bring great revenue opportunities for our company. The first two points were big wins in terms of adoption of our product in the short term and not having them now was costing us big time. The third point was something that was important to our business strategy in the long term.

The interesting thing was that looking at points one and two the development team immediately saw a very cheap way to offer that functionality within one week. Not a hack, but rather a change to an area of the application where the design was very flexible. Something our business team would not know. This obviously peaked the interests of our business and marketing team (Our stakeholders). So rather than waiting possibly six months for a project that would complete all of points one, two, and three, we were able to deliver one and two now and point three would only be delayed one week over the course of six months.

Simple Estimation: Is it cheap, or is it expensive

Sometimes business decisions get made without the people making the decisions knowing the cost of each option. Grabbing a developer and taking them to a business team brain storming session for the sole purpose of giving “Is it cheap, or is it expensive” feedback can be very useful in prioritizing new work. As a developer you have a responsiblity to provide this feedback.

Don’t be affraid to ask “Why”

As a developer when you are asked to build feature X, rather than just jumping into development of the feature. Put some thought into what it is that business is really looking to get out of the project. Make sure that what has been asked for is actually the best way to deliver the business value your stakeholders want.

This lead some of my co-workers to refer to a problem in software development known as Local Optimization.