posted on Saturday, November 18, 2006 1:17 PM by Benjy

BizUnit Context - A Tutorial

0         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 NDoc samples scattered around in the documentation.

This tutorial introduces the Context object and 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. This is the first in a series of articles on BizUnit.

1         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.

2         Where can we use the Context ?

As indicated above, when writing a custom step, you would use the context to log information. 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).

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.

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.

3         Using the Context : Basics

A simple way to think about Context is that it can be used like Nant properties, where you 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 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).

3.1             Which steps support context configuration data?

Actually all the steps 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 = ” 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.
      
            
            
      
 

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.

3.2             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.

 

4         XmlContextLoader

4.1             Summary

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

4.2             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.xmlsourcefilename>

      <targetfilename>c:\temp\testtarget.xmltargetfilename>

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

      <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.

    /*[local-name()='Variables']/*[local-name()='sourcefilename']

    /*[local-name()='Variables']/*[local-name()='targetfilename']

 

4.3             Bugs and Fixes

There are a couple of bugs in the 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;

5         RegEx Context Loader

5.1             Summary

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

5.2             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.

    /def:html/def:body/def:p[2]/def:form
    /def:html/def:body/def:p[2]/def:form/def:input[3]
    /def:html/def:body/def:p[2]/def:form/def:input[4]
    /def:html/def:body/def:p[2]/def:form/def:input[2]

 

6         TextContextLoader

6.1             Summary

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.

6.2             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"
 

Here we are using a TextContextLoader and adding in various items into the context.

 

 

 

 

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 BLOCKED EXPRESSION.

6.3             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.

 

 7         ContextManipulatorStep

7.1             Summary

The ContextManipulator is used to manipulate BizUnit context fields. It maybe used to create a new field from one or more existing fields.

7.2             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>

 

 

7.3             Issue

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. I will be writing an extension step with a complete revision for this soon

Comments

# re: BizUnit Context - A Tutorial

Wednesday, February 06, 2008 2:26 PM by Andrew Morris
Santosh,

Thanks for a great article. However it looks like you are missing the code examples (I can't see any, just empty spaces). Could you post them?

Regards,
Andrew

# re: BizUnit Context - A Tutorial

Friday, March 07, 2008 3:50 PM by Benjy
Andrew,
Thank you for your comment. I moved away from this blog awhile ago to (http://santoshbenjamin.wordpress.com) so i just saw this post and your feedback when skimming through this site. I think the skin for the blog has caused the code to disappear. could you take a look at http://www.codeproject.com/KB/biztalk/BizUnitContext.aspx
to see if that helps, or ping me on my new blog and i will try to help.

thanks
benjy