Peter Goodman bio photo

Peter Goodman

A developer living in Auckland building software using all sorts of bits and pieces I find along the way. Originally from Northern Ireland.

Twitter Google+ LinkedIn Github

I’m a big believer in using TestContext in MSTest or Console.WriteLine, Debug.WriteLine etc in your favourite Unit Testing framework to give context to passed or failed tests. Especially if you do CI and have only the test results to look at from the build server to try to understand why a build went wrong.

Taking this into account I use a TestContext Tracking Participant to get more visibility into my workflow unit tests. This enables me to see what tracking records have been raised against my invoked workflows. In only a few lines of code you can quickly enable extra logging.

public class TestContextTrackingParticipant : TrackingParticipant {
    private readonly TestContext testContext;

    public TestContextTrackingParticipant(TestContext testContext) {
        this.testContext = testContext;

    protected override void Track(TrackingRecord record, TimeSpan timeout) {
        testContext.WriteLine(string.Format("- {0}", 
            .Replace("{", "{{")
            .Replace("}", "}}")));


The only issue is that our invoker code from the previous post is a little more verbose.

public void ExecuteConvertsTimeToTargetCity() {

    DateTime currentLocalTime = DateTime.Now;
    string cityName = "London";

    TimeZoneInfo timeZoneInfo =
            timeZone => timeZone.DisplayName.ToUpperInvariant().Contains(cityName.ToUpperInvariant())).First();

    GetCityTime activity = new GetCityTime() {
                                                    City = cityName,
                                                    LocalTime = new InArgument<DateTime>(currentLocalTime)
    WorkflowInvoker invoker = new WorkflowInvoker(activity);

    invoker.Extensions.Add(new TestContextTrackingParticipant(TestContext));

    DateTime result = (DateTime)invoker.Invoke()["Result"];

    Assert.AreEqual(TimeZoneInfo.ConvertTime(currentLocalTime, timeZoneInfo), result);