5,666,979 members and growing! (18,493 online)
Email Password   helpLost your password?
Enterprise Systems » Microsoft BizTalk Server » General     Intermediate

BizUnit Context Tutorial

By Santosh Benjamin

This article explains how to use the Context object , a key part of the BizUnit framework
Windows, .NET 1.1, .NET, Visual Studio, Architect, Dev, QA

Posted: 19 Nov 2006
Updated: 5 May 2007
Views: 20,205
Bookmarked: 12 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
3 votes for this Article.
Popularity: 2.10 Rating: 4.40 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
1 vote, 33.3%
4
2 votes, 66.7%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

BizUnit is a very extensible testing framework. One of the core elements of BizUnit is the Context object. Unfortunately the documentation does not explain how users can take advantage of it and it is left to developers to try and understand it from some of the code snippets provided in the NDoc documentation.

This tutorial starts with a brief note on BizUnit and then goes on to introduce the Context object and explains how it can be used in BizUnit based testing. It uses examples from the official documentation wherever applicable and supplements it where the information in the documentation is not very clear. It will not replicate the list of methods and properties etc, so for an exhaustive reference, please refer back to the documentation. The three main context loader steps are explained here and future articles will explore custom steps as well as advanced uses of the context in unit and system testing.

Please note that some of the file paths refer to the structure of the BizUnit source code and the functional tests (for instance, the TestData folder is a specific folder in the set of unit tests that accompany the source) so I am assuming you have the code and can follow along.

(Author's note: 23-11-2006: Based on feedback received, i have updated the article to include a section on the basics of Bizunit)

(Update on 24-March-2007: For those who havent come across the project yet, i have started the BizUnitExtensions open source project and you can download bugfixes to the BizUnit core as well as a load of additional steps)

(Update on 05-May-2007: Kevin has moved BizUnit to CodePlex and has put some new releases with bug fixes and enhancements. The Context has now got some large number of enhancements which will be documented shortly. The Extensions project will no longer be releasing the Core as part of its regular releases to avoid confusion in the community as to which source code should be used)

BizUnit - The Basics

BizUnit is a unit testing tool intended for Biztalk. It is also an extensible framework and allows developers to write more tests to enrich the functionality that is out of the box. It makes use of NUnit.

For an introduction to BizUnit , you can read this article, written by Kevin Smith, the guy who wrote the tool. You can also take a look at Naveen's article here on CodeProject.

Basically, BizUnit works in a black-box mode. Lets assume we have an orchestration that takes data from a file location and then submits it to a Queue or a webservice and then to a database. Now if we wanted to manually test it ,we would have to create a sample file, place it in the folder corresponding to the orchestrations 'receive location' and then check that it arrived on the queue and finally at the database (and if the webservice itself logged the SOAP request, we can check for the presence of an entry in the appropriate log file).

With BizUnit, we can automate the steps that we have done manually. We can create a folder with all our sample files (which is a pre-requisite manual step) and write BizUnit Steps to copy the files to the recieve locations, and to check the queues, log files and databases.

It turns out that since most of the steps involve copying files, posting to SOAP endpoints, checking queues, databases and event logs, this tool can be used to test non Biztalk projects as well. We can simply ignore the steps that pertain to Biztalk such as BAMQueryStep.

(Note: There isnt actually a LogFileReader step because we all have different log file formats, but it is possible to write one or if we have a fixed format we can use the XmlContextLoader or RegExLoader to pull up the content from the file and check it)

As with all automated testing, when you have to do this step once or twice, it is easy enough to do manually, but when data conditions start to grow and you need an automated test as part of your automated build and release process, then this becomes invaluable. Further, when you do integration testing and need to verify the flow of messages between various services and components, manual testing is simply not sustainable.

The issue with it is that for large test scripts, the BizUnit scripts can soon become unwieldy. For example, if you had a test case where data was picked up from a specified source file, loaded into a target, then validated and perhaps moved somewhere else, (maybe to an MSMQ queue or database), you may find that the filenames and folder names are duplicated across the test steps. Further, if you already have this data (folder names, filenames, connection strings etc) in a configuration file which you are using, say, for some NUnit tests that exercise non Biztalk artefacts), then it is quite unnecessary to hardcode all of them in the test xml file and as the test library grows it becomes very hard to maintain.

This is where the 'Context' object proves to be a great help.

The Context Object

The Context object represents a state object that is passed between BizUnit test steps. Inside the BizUnit system , the context object is passed to each individual test step. It cannot be initialised and used in the TestFixture class but is available for use in custom steps. In the Xml file corresponding to the test case, the context can be read and manipulated using the specified steps (prewritten or custom).

Inside the BizUnit system, state may be written to or read from the context. The context also provides helper methods for test steps to read their configuration, and to log information, warnings, errors and data in a consistent manner. When a test is executed, the detailed information available in the output window is produced by using the Context class. So if you are writing a custom step, you would be expected to log exceptions, errors and warnings etc using the methods provided in the Context class.

You can also use it to store information such as name-value pairs which help in the logic of the custom step. (Of course, this is not mandatory. Since the custom step is merely your own class, you can define and use your own private member variables as you wish).

As I mentioned in the "basics" section above, large scripts can soon become unmaintainable and so another important use for the context is to store configuration data that is used across test steps. For very simple test cases where we utilise only a couple of steps, this may not seem very useful, but as the test cases get bigger and when data gets duplicated, the storing of parameters in the context becomes crucial.

Using the Context : Basics

A simple way to think about Context is that it can be used like Nant properties. In NAnt we would declare a property variable with a specific name and store a value in it. Then in all the tasks you simply refer to the property using ${propertyname} and the system picks up the appropriate value.

In BizUnit, out of the box, we would first create a FileValidate step to point to our configuration data file. This step loads the file into memory (to avoid losing the file, set the <DeleteFile> to false). After this we can use the XmlContext Loader, TextContextLoader or RegExContextLoader to extract data from the source file.

The choice of context loader depends on the format of the data. The XmlContextLoader expects you to supply XPath expressions that allow it to navigate the source data and extract the values. The RegEx context loader expects to be supplied a regular expression to be applied to the source data (and strictly speaking, as long as the regular expression is correct it does not matter if the file is Xml or Text). The TextContextLoader is slightly different. It works like the Substring() method and the old VB6 Mid$() functions and looks for a specified pattern, index and string length to retrieve data from the file. (See below for a detailed example).

Which steps support context configuration data ?

Most of the steps (one notable exception being the DotNetObjectInvoker) support configuration data. This is not very clear in the documentation (although there are some hints here and there). In the Xml node (corresponding to any element in the step) , we need to use the attribute "takeFromCtx = <contextkeyname>" and the system will look up the context when it executes the step.

For example, consider the following FileCreateStep. Here the context has already been loaded using the appropriate context loader.

<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.FileCreateStep">
<SourcePath takeFromCtx="sourcefilename"> </SourcePath>
<CreationPath takeFromCtx="targetfilename"> </CreationPath>
</TestStep>

In the SourcePath and CreationPath elements we use the takeFromCtx attribute and give it the context key name that the system should look up. The system then substitutes this at runtime.

Where it differs from Nant

A very important limitation of the context variables is that there is no run time 'macro expansion' behaviour beyond a simple context lookup.

For instance, in a Nant task, we can concatenate various properties together (along with system properties) so if we wanted a full file name, we could use something like

${source.path}\${file.name}.${file.extension}

The system would then substitute the property names with the appropriate values and use the supplied symbols such as the \ and the period (before the file extension) to arrive at the full file name. At this point in time this cannot be done in BizUnit, although it could be done by overloading the methods in the Context class to apply a macro expansion when the appropriate symbols such as $ and {} are detected.

XmlContextLoader

Overview

The XmlContextLoader evaluates an XPath expression to the source data and adds the value into the context.

Example

The following shows an example of the Xml representation of this test step. In this example, the existence of file has been validated using the file validate step(not shown) and this file contains all the context variables.

The actual file used in this example is included along with the source code in the TestData folder. The file name is XmlContextData.xml. The contents are shown below

<Variables>

<sourcefilename>c:\temp\test.xml</sourcefilename>

<targetfilename>c:\temp\testtarget.xml</targetfilename>

<connectionstring>Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local);Connect Timeout=30</connectionstring>

<sourcefolder>c:\temp\</sourcefolder>

<targetfolder>c:\temp\</targetfolder>

</Variables>

Now when we use the ContextLoader we can load all the contents of the file into the context by using the correct type of context loader such as an XmlContext Loader or a RegEx context loader

Here we are using the XmlContext loader and the XPath expressions represent the navigation path to the data in the source file (i.e) 'Variables' is the top level element and 'sourcefilename' and 'targetfilename' are the elements which contain the values we want to load into the context Each of these XPath context key elements will result in the equivalent Context.Add(key,object) being executed.

<ContextLoaderStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.XmlContextLoader">

<XPath contextKey="sourcefilename">/*[local-name()='Variables']/*[local-name()='sourcefilename']</XPath>

<XPath contextKey="targetfilename">/*[local-name()='Variables']/*[local-name()='targetfilename']</XPath>

</ContextLoaderStep>

Bugs and Fixes

RegEx Context Loader

Overview

The RegExContextLoader applies a regular expression to the source data and adds the value into the context.

Example

The following shows an example of the Xml representation of this test step. In this example, the existence a file has been validated using the file validate step and this file contains all the context variables.

The actual file used in this example is included along with the source code in the TestData folder. The file name is RegExTestData.txt. The content of the file is shown below

The BizTalk web site is here: http://www.microsoft.com/biztalk, you

can find out more about the product there

Now when we use the ContextLoader we can load all the contents of the file into the context by using the correct type of context loader such as an XmlContext Loader or a RegEx context loader

Here we are using a RegEx context loader and adding in various items into the context. Each of these RegEx context key elements will result in the equivalent Context.Add(key,object) being executed. (For example the context key named HTTP_Url will now contain http://www.microsoft.com/biztalk.

<ContextLoaderStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.RegExContextLoader">
<RegEx contextKey="HTTP_Url">/def:html/def:body/def:p[2]/def:form</RegEx>
<RegEx contextKey="ActionID">/def:html/def:body/def:p[2]/def:form/def:input[3]</RegEx>
<RegEx contextKey="ActionType">/def:html/def:body/def:p[2]/def:form/def:input[4]</RegEx>
<RegEx contextKey="HoldEvent">/def:html/def:body/def:p[2]/def:form/def:input[2]</RegEx>
</ContextLoaderStep>

TextContextLoader

Overview

The TextContextLoader works like the Substring and the old VB6 Mid$ functions It searches through the source data for specified strings and then returns substrings from a specified position and for a specified length.

Example

The following shows an example of the Xml representation of this test step. In this example, the existence a file has been validated using the file validate step(not shown) and this file contains all the context variables. The actual file used in this example is included along with the source code in the TestData folder. The file name is TextContextLoaderDemo.txt. The file contains the following 2 lines

source=c:\temp\test.xml"
target=c:\temp\testtargetnew.xml"

In the following snippet we are using a TextContextLoader and adding in various items into the context.

<ContextLoaderStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.TextContextLoader">

<Item contextKey="sourcefilename" searchString="source" skipNumber="1" stringLength="16" />

<Item contextKey="targetfilename" searchString="target" skipNumber="1" stringLength="25" />

</ContextLoaderStep>

Now what happens is that when setting up the context key named "sourcefilename" , the system looks for the pattern/search string which is "source" and finds its IndexOf value. It then adds that to the skipNumber which is 1, thus making it ignore the "=" symbol in the line of data it then looks for the next 16 characters (which happens to be the full path name) and returns that. The same processing occurs for the next context key "targetfilename" and in this case it takes 25 characters.

This concept could be applied to a big string of parameters in the source file (if you dont want to bother with creating an Xml file and working out the necessary XPath expressions).

Limitation

This step does have one limitation in that the string lengths for the returned value need to be known in advance thus limiting the ability of the developer to easily change the test data. A future version of this step (or another custom step) can be created which allows a flexible loading of an array of context values.

ContextManipulatorStep

Overview

The ContextManipulator is used to manipulate BizUnit context fields. According to the documentation, it maybe used to create a new field from one or more existing fields.

Example

In the following example, a new context key named newsource is created and the value is taken from the existing context key.

<TestStep assemblyPath="" typeName="Microsoft.Services.BizTalkApplicationFramework.BizUnit.ContextManipulatorStep">

<ContextItem contextKey="newsource">

<ItemTest takeFromCtx="sourcefilename"></ItemTest>

</ContextItem>

</TestStep>

Issue

Out of the box, this step does not appear to work no matter what attempt is made. It seems that the code is not written correctly for the step. (We would be better of writing our own step for this). I will be writing a custom step for this shortly and will post it at this site.

Summary

This article provided just a brief overview of how the context works and i hope this has given you the understanding you need to make use of it. In my current integration project we have written a few custom steps and made extensive use of the context to read our app.config and web.config files and it has proved invaluable in eliminating redundant declarations and hard-coding. Please email me if you have any questions and i will try to answer them as soon as possible Good luck (and if you write any custom steps or work out new techniques to use the context, do let the rest of the community know).

There are a couple of bugs in the provided code for this step

Fix 1: Remove the code that creates stream reader and reads to end of data Stream, as data will then not load into XmlDoc (because the pointer is set to the end), and the StreamReader is never used anywhere.

Fix 2: Change the SelectSingleNode code to the following

contextValue = doc.SelectSingleNode( xpathExp ).InnerText;

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Santosh Benjamin


I'm a Solutions Architect working with Agilisys in London U.K. I specialise in the .NET stack especially in the integration space and have been using Biztalk for a few years now.
Occupation: Web Developer
Location: United Kingdom United Kingdom

Other popular Microsoft BizTalk Server articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 8 of 8 (Total in Forum: 8) (Refresh)FirstPrevNext
Generalany Bizunit Best Praticememberstrepan6:13 4 May '07  
AnswerRe: any Bizunit Best PraticememberSantosh Benjamin2:27 5 May '07  
GeneralUnitTesting with WebServicesmemberBizTalkFreak11:22 12 Mar '07  
GeneralRe: UnitTesting with WebServicesmemberSantosh Benjamin4:39 19 Mar '07  
GeneralIs there source code?membermichael.deery14:20 28 Feb '07  
GeneralRe: Is there source code?memberSantosh Benjamin4:44 19 Mar '07  
Generallike it .memberYasir112:26 21 Nov '06  
Generalhamembernoemailz10:56 20 Nov '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 5 May 2007
Editor:
Copyright 2006 by Santosh Benjamin
Everything else Copyright © CodeProject, 1999-2008
Web17 | Advertise on the Code Project