Geeks With Blogs

News View Michael Stephenson's profile on BizTalk Blog Doc View Michael Stephenson's profile on LinkedIn
Michael Stephenson keeping your feet on premise while your heads in the cloud

Overview

Continuing the series of posts about testing for BizTalk, this post will discuss our approach to testing Maps.  Again like with schema the normal approach used for testing maps is to use the Visual Studio menu to test the map with different instances against the map.  In my opinion this approach has some limitations:

1. It needs to be done manually and can not easily be automated

2. The output from the map is normally only validated by the developers eye

3. Changes to the map may not be regression tested effectively

Aim of our approach

In our approach to testing maps the aim is as follows:

1. For each test case for the map we will have an input message and an expected file which is exactly how the output from the map should look.  The test will compare the output with this expected result

2. We will develop MsTest/Nunit style tests which will execute the maps

3. The tests will be ran as part of a continuous integration process

The aim is that by testing the maps thourghly outside of BizTalk we know they will work before they are used within a larger process where defects are more difficult to identify.

The Example

In the example (available below) I have created a small solution which contains a simple map based on two schemas.  The map will use a helper component developed in C#.  The helper component is there to demonstrate how to make your maps run outside of BizTalk when they use external assemblies.

The key points of the sample are as follows:

1. The utilities project has an msbuild task that will GAC the assembly during the build.  This ensures it is available for use by the map.

2. The test project uses the MapTestingHelper class which wraps up the interaction with the map

3. The test project will reference the maps project from where you can access the maps as a class which derives from TransformBase

The following picture demonstrates the code sample for a test method which will test a map:

In the sample you can see we have the paths to the input, output and expected file.  we then have 2 choices of method to call on the MapTestingHelper.  We can use:

  • ExecuteInMemory - Which uses the traditional way of mapping by passing in the input as an XPathDocument
  • ExecuteMapScalable - Which uses the scalable transform method of the BtsXsltTransform class.  This is recommended for larger input files

You can also see above that I pass in an instance of the Input_To_Output class which is the map from within the Maps assembly.

When the map has been executed the Helper class also provides a ValidateMapOutput method which you can provide the output and expected file paths.  This method will then compare the two files to identify where there may be any differences.

Note:  

I developed the sample on a BizTalk 2006 R2 machine.  I think the signature of the BtsXsltTransform class has changed between versions as to get the helper to work on a standard BizTalk 2006 (non R2) machine I had to change the transform line within the helper to the below signature.

mapInstance.StreamingTransform.Transform(inputStream, mapInstance.TransformArgs, outputStream, resolver);

Posted on Sunday, March 30, 2008 12:14 AM BizTalk , BizTalk Testing | Back to top


Comments on this post: BizTalk Testing Series - Testing Maps

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
An alternative option to consider is using the MapExecutingStep step in the BizUnitExtensions project on codeplex. However, this looks like it may be more work to setup than your approach.
Left by Charlie on May 22, 2008 5:24 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
My map uses scripted functoids. I was hoping to isolate my map tests from these calls to C# methods. RhinoMocks is not an option as you cannot mock a sealed class (TransformBase). I added a ExcludeCheckRange[] parameter to your ValidateMapOutput method, but it is a bit ugly. Do you have any better suggestions?
Left by Charlie on Sep 22, 2008 3:01 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
I think this would be difficult to do as you want, but there are probably a couple of approaches you might consider, but they would all involve a bit of work and be just as dirty.

For components that only do simple things I probably wouldnt worry about isolating the map from them, but for complex things I would consider the following:

You could have two assemblies which would end up with the same strong name one for real purposes and one with the same interface but just a basic implementation to support your test cases. You could then replace which one is referenced from the gac depending on which kind of tests you are doing. your map would then think its calling the right assembly but not know that its just returning a simple test value rather than doing the complex logic you might normally do.

Note I havent tried the above off the top of my head I think it should work

Let me know how you get on
Mike
Left by Mike on Sep 22, 2008 3:38 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
Another idea which a mate and I were discussing over coffee would be using a facade patten between your map and the C# component and then initially in the C# facade using something like castle or spring.net to use dynamic proxies to work out which object to really use. This would allow you to use different assemblies for different purposes.

The downside to this approach is the additional work required and also having to manage a bunch of configuration settings for it.

I think again if you use it for some special cases but not simple ones it is probably more effective as using it for every external call maybe quite timeconsuming

HTH
Mike
Left by Mike on Sep 22, 2008 4:38 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
Many thanks for the suggestions. My preference, as you suggest, is to avoid the extra configuration required by an IOC container.

I've modified my original ExcludeCheckRange[] parameter approach to instead use Regex replacements on the xml actual output. This ensures the pattern of an element value matches, but not does not care about the exact value (e.g. dates, integers). This is working well and the test code is clearer.

I also tinkered with using XmlDiff and XmlUnit to compare the XML values. This would have meant the expected XML could be formatted, so easier to read and maintain. XMLDiff could also show all differences. However, the error messages were not great. I much preferred the error messages produced by your code showing exactly where the first character is different.
Left by Charlie on Oct 07, 2008 12:08 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
Are the samples available for download? The link doesnt work.
Left by Scott on Dec 02, 2008 4:05 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
If your map uses custom XSLT, you have an alternative unit testing option. See the article "Unit testing XSLT" by Ron Jeffries : http://www.xprogramming.com/xpmag/acsXSLTexperiments.htm
Left by Charlie on Jan 11, 2009 9:28 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
how can i download sample code ? link provided don't work.
Left by adam raheem on Feb 11, 2009 11:51 AM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
Will this approach work when the map has Scripting functoids in with Inline C# code ?
Left by Steve Culshaw on May 17, 2009 11:56 AM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
Hi Steve,

It should work fine with inline C#. I think we already run some tests on my project which have inline C#.

If you reference any external assemblies you just need to ensure they are in the GAC and that bit will work too.

HTH
Mike
Left by Michael Stephenson on May 19, 2009 3:04 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
Michael,

wasn't sure if the reason it was failing was because my original map was a multiple input message, so did some testing ...
- a one-to-one map with a single Scripting functoid in
- multiple input without scripting
- etc.

What seems to have sorted it was removing the assemblies from the GAC and just running the tests against the local copy !!
Left by Steve Culshaw on May 30, 2009 1:03 PM

# re: BizTalk Testing Series - Testing Maps
Requesting Gravatar...
Hi Mike

I'd been doing this long hand and running an running an xpath against the output. Your method is so much quicker to code and of course will work against flat files.

Just one thing for others to avoid. I'd created a copy of my expected output buy running test map from Visual Studio. This produced an xml file on a single line, so I quickly ran a pretty print on it to make it easier to read. I used this as my file to be compared against the test output. It took me a little while to figure out why the test was failing, all those extra CR/LFs - doh!

Thanks again for another Gem!

Rob.
Left by Rob Bowman on Nov 16, 2012 3:55 AM

Your comment:
 (will show your gravatar)


Copyright © Michael Stephenson | Powered by: GeeksWithBlogs.net