Click here to Skip to main content
15,885,985 members
Articles / Web Development / ASP.NET

Using Workflow Foundation and Visual Studio 2008 for Testing Automation

Rate me:
Please Sign up or sign in to vote.
4.90/5 (26 votes)
6 May 2008CPOL10 min read 88.4K   844   80  
How to employ Windows Workflow Foundation for testing processes. Let's design tests on a visual diagram and automate its execution!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Diagnostics;
using System.Threading;

namespace TestflowFramework
{
	public class TestflowHost
	{
		private static WorkflowRuntime workflowRuntime;
		public static WorkflowRuntime WorkflowRuntime
		{
			get { return workflowRuntime; }
		}
		private static Form form;
		internal static TestflowLogger logger;
		private static string test;

		public static void RunTest(Form mainForm, string testAssemblyName, string testName, string logFile)
		{
			form = mainForm;
			logger = new TestflowLogger(logFile);
			test = testName;
			Assembly testAssembly = LoadTestAssembly(testAssemblyName);
			if (testAssembly != null)
			{
				Type testType = FindTypeInAssembly(testAssembly, testName);
				if (testType != null)
				{
					if (testType.IsSubclassOf(typeof(System.Workflow.ComponentModel.Activity)))
					{
						RunTest(testType);
						Application.Run(form);
					}
					else
						logger.Write("Error", "Test " + testName + " must be inherited from Activity class");
				}
				else
					logger.Write("Error", "Test " + testName + " not found");
			}
			else
				logger.Write("Error", "Testing assembly '" + testAssemblyName + "' not found. Test '" + testName + "' was not run.");
		}
		
		static Assembly LoadTestAssembly(string testAssemblyName)
		{
			try
			{
				string p = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, testAssemblyName);
				return Assembly.LoadFile(p);
			}
			catch (Exception)
			{
				return null;
			}
		}

		static IEnumerable<Type> GetTests(Assembly assembly)
		{			
			foreach (Type type in assembly.GetTypes())
			{
				if (type.IsSubclassOf(typeof(SequentialWorkflowActivity)))
					yield return type;
			}
		}
		 
		static Type FindTypeInAssembly(Assembly assembly, string testName)
		{
			foreach (Type type in GetTests(assembly))
			{
				if (string.Compare(type.Name, testName, true) == 0)
					return type;
			}
			return null;
		}

		private static void RunTest(Type type)
		{
			workflowRuntime = new WorkflowRuntime();

			ExternalDataExchangeService dataExchangeService = new ExternalDataExchangeService();
			workflowRuntime.AddService(dataExchangeService);
			workflowRuntime.WorkflowAborted += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowAborted);
			workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(workflowRuntime_WorkflowCompleted);
			workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(workflowRuntime_WorkflowTerminated);

			Guid workflowId = Guid.NewGuid();

			WindowsApplicationService winService = new WindowsApplicationService(workflowId);
			dataExchangeService.AddService(winService);

			WorkflowInstance workflowInstance =	workflowRuntime.CreateWorkflow(type, null, workflowId);

			workflowRuntime.StartRuntime();
			workflowInstance.Start();
		}

		static void workflowRuntime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)
		{		
			logger.Write("Failure", test + ". Reason: " + e.Exception.Message);
			CloseApp();
		}

		static void workflowRuntime_WorkflowAborted(object sender, WorkflowEventArgs e)
		{
			
			logger.Write("Failure", test);
			CloseApp();
		}

		static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
		{
			logger.Write("Success", test);
			//CloseApp();
		}
		
		static void CloseApp()
		{
			if (Process.GetCurrentProcess().CloseMainWindow())
			{
				Thread.Sleep(1000); // give application a chance to close gracefully
			}
			Process.GetCurrentProcess().Close();
			Process.GetCurrentProcess().Kill();	
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions