One of the challenges in delivering successful and high quality BizTalk solutions is the ability to test the solution. BizTalk is an execution environment which is often treat like a black box making it difficult to test what’s happening inside BizTalk.

Most good development teams will test various BizTalk artefacts such as maps, pipeline components, etc thourghly in isolation before they are used within BizTalk and then deploy the solution to BizTalk and then black box test it with a test framework like BizUnit. Recently there have been a number of projects such as BizMock and BizMonade which have tried to let you test in more detail by isolating things like orchestrations so they can be partially tested in isolation.

There is still a gap! 

When all of your components are deployed together in BizTalk and you attempt to integration test them its very difficult to assert that something actually happened inside of the black box. Take an example where we have an orchestration with a decision shape and two branches. Normally the testing would push a message into BizTalk to cause the orchestration to execute and then test what happened to things around BizTalk (such as event log or application stubs) and then check the message that comes out of BizTalk. The thing we haven’t done is to prove which branch of an orchestration was executed. 

The aim of the BizTalk Testing Trace Monitor is to help address this gap.

What does it do?

If you use the Microsoft BizTalk CAT Teams BizTalk logging framework for instrumenting your BizTalk solution then it will write events to the Windows ETW sub system. The trace monitor will capture these events and provide a pattern where you can check for these events occurring.

In the above example you could write a trace statement on each branch to indicate that you have went to the left or write of the branch. In your automated test you could assert this trace statement occurred which could prove which branch of the orchestration executed.

The result is we now have the ability to make assertions about what is happening inside BizTalk.

 

How does it work?

The BizTalk Testing Trace Monitor is a console application which you can run along side your tests. The trace monitor will detect events published to ETW by the BizTalk logging framework and then publish them onto an MSMQ queue as configured in the console application. Then your tests can check this queue for events which happened and the order in which they happen.

The complexity of this is encapsulated by some BizUnit steps which come with the Trace Monitor which allow you to control it and interact with the events. The process in your BizUnit test would normally be:

 

  1. Trigger your BizTalk process
  2. Check for events coming out via ETW using the BizUnit steps which come with the trace monitor

 

While the trace monitor console application is running it will display the trace messages it has received. Any which appear as red text are determined to not have come from the BizTalk logging framework and are therefore ignored. Ones displayed in green are determined as coming from the BizTalk logging framework and are pushed onto the queue so you can check for these happening.

Example

The below example BizUnit test shows the use of the various tasks to control the trace monitor and to check for events.

You can see how we are checking for messages 1, 2 and 3 being outputted in order.

 

<TestCase testName="Example Test to show Tracing Pattern">

       <TestSetup>

              <!-- Start the event trace-->

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.StartRealtimeEventTrace">

                      <TraceToolPath>..\..\..\BTS.Testing.TraceMonitor\bin\debug\BTS.Testing.TraceMonitor.exe</TraceToolPath>

              </TestStep>

       </TestSetup>

       <TestExecution>

              <!-- Log start event-->

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.ExampleTraceStep">

                      <TraceMessage>message 1</TraceMessage>

              </TestStep>

             

              <!-- Check for event at front of queue-->

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.PollForNextEvent">

                      <DeleteAfterFound>false</DeleteAfterFound>

                      <IncludeBodyCompare>true</IncludeBodyCompare>

                      <QueuePath>.\private$\BTS.Testing.TraceMonitor</QueuePath>

                      <RegEx>message 1</RegEx>

                      <TimeoutSeconds>10</TimeoutSeconds>

              </TestStep>

 

              <!-- Add some more trace messages-->

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.ExampleTraceStep">

                      <TraceMessage>message 2</TraceMessage>

              </TestStep>

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.ExampleTraceStep">

                      <TraceMessage>message 3</TraceMessage>

              </TestStep>

 

              <!-- Check for event anywhere in queue-->

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.PollForEvent">

                      <DeleteAfterFound>false</DeleteAfterFound>

                      <IncludeBodyCompare>true</IncludeBodyCompare>

                      <QueuePath>.\private$\BTS.Testing.TraceMonitor</QueuePath>

                      <RegEx>message 1</RegEx>

                      <TimeoutSeconds>10</TimeoutSeconds>

              </TestStep>

 

              <!-- Check for event next in queue with delete through each event logged-->

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.PollForNextEvent">

                      <DeleteAfterFound>true</DeleteAfterFound>

                      <IncludeBodyCompare>true</IncludeBodyCompare>

                      <QueuePath>.\private$\BTS.Testing.TraceMonitor</QueuePath>

                      <RegEx>message 1</RegEx>

                      <TimeoutSeconds>10</TimeoutSeconds>

              </TestStep>

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.PollForNextEvent">

                      <DeleteAfterFound>true</DeleteAfterFound>

                      <IncludeBodyCompare>true</IncludeBodyCompare>

                      <QueuePath>.\private$\BTS.Testing.TraceMonitor</QueuePath>

                      <RegEx>message 2</RegEx>

                      <TimeoutSeconds>10</TimeoutSeconds>

              </TestStep>

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.PollForNextEvent">

                      <DeleteAfterFound>true</DeleteAfterFound>

                      <IncludeBodyCompare>true</IncludeBodyCompare>

                      <QueuePath>.\private$\BTS.Testing.TraceMonitor</QueuePath>

                      <RegEx>message 3</RegEx>

                      <TimeoutSeconds>10</TimeoutSeconds>

              </TestStep>

       </TestExecution>

       <TestCleanup>

             

              <!-- Stop the event trace-->

              <TestStep assemblyPath="BTS.Testing.TraceMonitor.BizUnitSteps.dll" typeName="BTS.Testing.TraceMonitor.BizUnitSteps.StopRealtimeEventTrace">

              </TestStep>

       </TestCleanup>

 

</TestCase>

Configuring the trace monitor

The trace monitor has some settings in its configuration file as follows:

  1. A queue path which is the queue to which events from the logging framework will be written
  2. A port for the WCF service inside the console application which allows the Bizunit steps to control the trace monitor
  3. A regular expression which is used to filter events to workout which belong to the logging framework

You may need to amend the queue path and WCF port specifically for your environment.

Configuring your test project

You will need to add some details to the config file for your test project for the details of calling the WCF service exposed for controlling the trace monitor.  There is an example of this in the release and you may need to modify the port if you did so in the previous section.

 

Acknowledgements

I used samples from the following community articles and tools to help put together the BizUnit steps used in this project:

Christian Birkl - http://www.codeproject.com/KB/trace/DbMonNET.aspx

Thomas Abraham - http://btscatifcontroller.codeplex.com/

Daniel Vasquez Lopez - http://blogs.msdn.com/b/danielvl/archive/2009/02/02/how-to-consume-etw-events-from-c.aspx

BizTalk CAT Team - http://blogs.msdn.com/b/appfabriccat/archive/2010/05/11/best-practices-for-instrumenting-high-performance-biztalk-solutions.aspx

Last edited May 17, 2011 at 11:22 PM by michaelstephenson, version 2

Comments

No comments yet.