Advanced WPF automation – memory usage

Last Updated on by

Post summary: Highlight eventual memory issue when using Telerik Testing Framework and TestStack White for desktop automation.

Memory is an important aspect. When you have several test cases it is not a problem. But on large projects with many tests memory turn out to be a serious issue.

Reference

This post is part of Advanced WPF desktop automation with Telerik Testing Framework and TestStack White series. The sample application can be found on GitHub.

Problem

Like every demo on certain technology automating WPF applications looks cool. And also like every technology problems occur when you start to use it on a large scale. Problem with WFP automation with Telerik Testing Framework and TestStack White is the memory. When your tests’ number grows frameworks start to use too much memory. By too much, I mean over 1GB which might not seem a lot but for a single process actually is. Increasing RAM of test machine is an only temporary solution and is not one that can be scaled.

Why so much memory

I have a project with 580 tests and 7300 verification points spread in 50 test classes. I’ve spent lots of hours debugging and profiling with several .NET profiling tools. In the end, all profilers show that a large amount of memory used is in unmanaged objects. So generally there is nothing you can do. It seems like some of the frameworks or both have memory issues and do not free all memory they use.

Solution

The solution is pretty simple to suggest but harder to implement – run each test class in the separate process. I’m using a much more enhanced version of NTestsRunner. It is running each test class in separate windows process. Once the test is finished results are serialized in results directory, the process is exited and all memory and object used for this test are released.

Conclusion

The memory could be a crucial factor in an automation project. Be prepared to have a solution for it. At this point, I’m not planning to put running tests in a separate process in NTestsRunner. If there is demand it is a pretty easy task to do it.

Related Posts

Read more...

Advanced WPF automation – read dependency property

Last Updated on by

Post summary: What is dependency property in .NET and how to read it from Telerik Testing Framework.

In this post, I’ll show an advanced way of getting more details from an object and sophisticate your automation.

Reference

This post is part of Advanced WPF desktop automation with Telerik Testing Framework and TestStack White series. The sample application can be found in GitHub SampleAppPlus repository.

Dependency property

Dependency properties are an easy way to extend available in .NET framework functionality. In SampleAppPlus there is CustomControl defined. Purpose of this control is to store text and visualize this text as image. The text is stored in dependency property.

public partial class CustomControl : UserControl
{
	public static readonly DependencyProperty MessageProperty =
			DependencyProperty.Register("Message",
									typeof(string), typeof(CustomControl),
									new PropertyMetadata(OnChange));

	...

	public string Message
	{
		get { return (string)GetValue(MessageProperty); }
		set { SetValue(MessageProperty, value); }
	}

	...

}

Read dependency property

In order to be able to properly automate something, you have to know the internal structure of the application. Generally, you will try to locate and read the element and it will not work in the ways you are used working with elements. At this point, you have to inspect the source code of application under test and see how it is done internally. Most important if dependency property is used you should know its name. Once you know the name reading is easy.

public class MainWindow : XamlElementContainer
{
	...

	private UserControl CustomControl_Image
	{
		get
		{
			return Get<UserControl>(mainPath + "CustomControl[0]");
		}
	}

	public Verification VerifyCustomImageText(string expected)
	{
		string actual =
			CustomControl_Image.GetAttachedProperty<string>("", "Message");
		return BaseTest.VerifyText(expected, actual);
	}
}

GetAttachedProperty

GetAttachedProperty is a powerful method. Along with reading dependency properties, you can read much more. In some cases, WPF elements are nested in each other or in tooltip windows. In other cases, some object is bound to WPF element. In such situations you can try to access the elements and method will return you FrameworkElement object. From this object, you can again get GetAttachedProperty to access some class specific property. In all cases, you will need access to the application under test code to see how it is working internally.

FrameworkElement tooltip = wpfElement.
	GetAttachedProperty<FrameworkElement>("", "ToolTip");
string value = tooltip.GetAttachedProperty<string>("", "SomeSpecificProperty");

Conclusion

GetAttachedProperty is a powerful method. Once you get stuck with normal processing of elements you can always try it. I would say definitely give it a try.

Related Posts

Read more...

Advanced WPF automation – page objects inheritance

Last Updated on by

Post summary: re-use of page objects code through inheritance.

Inheritance is one of the pillars of object-oriented programming. It is a way to re-use functionality of already existing objects.

Reference

I’ve started a series with details of Advanced WPF desktop automation with Telerik Testing Framework and TestStack White. The sample application can be found in GitHub SampleAppPlus repository.

Abstract class

An abstract class is one that cannot be instantiated. An abstract class may or may not have abstract methods. If one method is marked as abstract then its containing class should also be marked as abstract. We have two similar windows with text box, save and cancel button that is shown on both of them. AddEditText class following Page Objects pattern. It is marked as abstract thought. It has an implementation of all three elements except TextBox_Text.

public abstract class AddEditText : XamlElementContainer
{
	protected string mainPath =
		"XamlPath=/Border[0]/AdornerDecorator[0]/ContentPresenter[0]/Grid[0]/";
	public AddEditText(VisualFind find) : base(find) { }

	protected abstract TextBox TextBox_Text { get; }
	private Button Button_Save
	{
		get
		{
			return Get<Button>(mainPath + "Button[0]");
		}
	}
	private Button Button_Cancel
	{
		get
		{
			return Get<Button>(mainPath + "Button[1]");
		}
	}

	public void EnterText(string text)
	{
		TextBox_Text.Clear();
		TextBox_Text.User.TypeText(text, 50);
	}

	public void ClickSaveButton()
	{
		Button_Save.User.Click();
		Thread.Sleep(500);
	}

	public void ClickCancelButton()
	{
		Button_Cancel.User.Click();
	}
}

Add Text page object

The only thing we have to do in Add Text window is to implement TextBox_Text property. All other functionality has already been implemented in AddEditText class.

public class AddText : AddEditText
{
	public static string WINDOW_NAME = "Add Text";
	public AddText(VisualFind find) : base(find) { }

	protected override TextBox TextBox_Text
	{
		get
		{
			return Get<TextBox>(mainPath + "TextBox[0]");
		}
	}
}

Edit Text page object

In Edit Text page object we have to implement “TextBox_Text” property. Also on this window, there is one more element which needs to be defined.

public class EditText : AddEditText
{
	public static string WINDOW_NAME = "Edit Text";
	public EditText(VisualFind find) : base(find) { }

	private TextBlock TextBlock_CurrentText
	{
		get
		{
			return Get<TextBlock>(mainPath + "TextBlock[0]");
		}
	}

	protected override TextBox TextBox_Text
	{
		get
		{
			return Get<TextBox>(mainPath + "TextBox[1]");
		}
	}

	public Verification VerifyCurrentText(string text)
	{
		return BaseTest.VerifyText(text, TextBlock_CurrentText.Text);
	}
}

Conclusion

Inheritance is a powerful tool. We as automation engineers should use it whenever possible.

Related Posts

Read more...

Advanced WPF desktop automation

Last Updated on by

Post summary: In this series of posts I’ll expand the examples and ideas started in Automation of WPF applications series.

Telerik Testing Framework and TestStack White are powerful tools for desktop automation. You can automate almost everything with a combination of those frameworks. This series of posts will give more details how to automate more complex applications.

Reference

Code samples are located in GitHub SampleAppPlus repository. Telerik Testing Framework requires installation as it copies lots of assemblies in GAC.

SampleAppPlusThere is SampleAppPlus which is actually a dummy application with only one purpose to be used to demonstrate automation principles. With this application, you can upload an image file. Once uploaded image is visualized. The image path is listed in a table. The image path is also visualized as an image in a custom control in the bottom of the main window. The user is able to add more text which is added to the table as long as editing already existing text. Add and edit are reflected on custom image element.

Topics

  • Page objects inheritance of similar windows
  • Working with WinForms grid
  • Windows themes and XamlPath
  • Read dependency property
  • NTestsRunner in action
  • Extension methods
  • Memory usage

Page objects inheritance

It is common to have similar windows in an application. Each window is modeled as page object in automation code. If windows are also similar in terms of internal structure it is efficient to re-use similar part and avoid duplications. Re-use is achieved with inheritance. Given SampleAppPlus application has very similar windows for adding and editing text. Code examples show how to optimize your effort and re-use what is possible to be re-used. More details can be found in Advanced WPF automation – page objects inheritance post.

Working with WinForms grid

As mentioned before Telerik Testing Framework is not very good with WinForms elements. This is the main reason to use TestStack White. It is not very likely to have WinForms elements in WPF application but in order to complete the big picture I’ve added such grid in a SampleAppPlus application. Code examples show how to manage WinForms grid. More details can be found in Advanced WPF automation – working with WinForms grid post.

Windows themes and XamlPath

In given examples elements are located with exact XamlPath find expression. This approach has a serious problem related to Windows themes. For complex user interfaces, XamlPath could be different on a different theme. Windows Classic theme sometimes produces different XamlPath in comparison with standard Windows themes. Yes, it is no more available from Windows 8 but Server editions are working only with Windows Classic theme. So one and the same tests could have differences. I couldn’t find a way to automatically detect which is current theme. The solution is to have different XamlPath for both standard and classic themes. Once you have it you can switch them manually with some configuration or you can try to automate the switch by locating element for which you know is different and save variable based on its location result.

Read dependency property

A dependency property is a way in C# to extend the standard provided functionality. It can happen in a real application that developers use such functionality. Given SampleAppPlus application has a special element with dependency property. Code examples show how to extract property value and use it in your tests. More details can be found in Advanced WPF automation – read dependency property post.

NTestsRunner in action

I’ve introduced NTestsRunner which is a custom way for running functional automated tests. Code samples show how to use it and create good tests that are run only with this tool.

Extension methods

Extension methods are one extremely good feature of .NET framework. I personally like them very much. I assume everyone writing code in C# is aware of them. Still, in code examples show how they can be used.

Memory usage

Memory is not a problem on small projects. But when the number of tests continue to grow it actually becomes a problem. More details can be found in Advanced WPF automation – memory usage post.

Related Posts

Read more...

WPF automation – running the tests

Last Updated on by

Post summary: How to sell your automation to management. Guide for running the tests unattended.

References

This post is part of Automation of WPF applications with Telerik Testing Framework and TestStack White series. The sample application can be found in GitHub SampleApp repository.

Test frameworks need mouse and keyboard

As you have noticed when running the examples it is not possible to do anything else while tests are running because both Telerik Testing Framework and TestStack White are using mouse and keyboard in order to click and type text. This is how both frameworks are designed and work. It doesn’t seem very effective if you are wasting your time watching tests running on your workstation instead of doing something productive. This is not a good argument when advocating your automation.

The essence of automation is being effective

This topic is not about Automation vs. Manual testing so I will not go in that direction. I’ll just say that still there are companies lacking management willpower to support and embrace automation. So we need to be good salesmen!

How to drive your automation to success

As I said we need to be wise when promoting our automation to get more time and resources. Sales strategy is pretty easy and straightforward not requiring huge investments:

  • Free to use and pretty easy to work with frameworks.
  • Some enthusiasm to make the first automation. Remember, be smart and first automate most repeating scenarios. This will show real results and help you buy some time for further automation.
  • Virtual (or real) machine with test running on it during the night
  • Mail with results is sent to management with results in the morning

Run the tests unattended

You get the machine, set up the framework, set up scheduled tasks for deploying the latest application under test and latest test code. Run the tests and get into trouble. Tests do not run! This is because there are special requirements to schedule unattended run. There must be an active Windows session in order mouse and keyboard to be used. Once the session is interrupted tests stop. This is detailed KB article on the topic with several possible solutions.

Working solution

You can try solutions in the article to see which works best for you. For me, the solution is to have a remote desktop in remote desktop. This requires Windows Server installation. The only server provides two simultaneous remote desktop sessions. There are unofficial patches for non-server versions which I haven’t tried and cannot comment. Two local users are needed on the Windows Server with no desktop locking or screen saver (domain users most likely will have desktop locked after a time). Log from your machine to test machine with the first user. From first user’s session log to same testing machine with the second user. Tests are started from second user’s session. Once tests are started you can freely close desktop (not log out!). You can create a scheduled task which runs only when the user is logged in and just wait for results in the morning. If two accounts are overhead there is an option to use software that prevents your computer to lock. See prevent screen lock thread if something works for you.

Conclusions

Automation is an exciting field of career development for test engineers. This blog is dedicated to automation testing. You will find very useful and interesting topics in it. I would definitely encourage you just to give it a try. Good luck!

Related Posts

Read more...

WPF automation – using the elements

Last Updated on by

Post summary: Use already created Page Objects and build up test framework.

References

This post is part of Automation of WPF applications with Telerik Testing Framework and TestStack White series. The sample application can be found in GitHub SampleApp repository.

Page Objects holder

Below is App.cs which is a representation of application under test.

using ArtOfTest.WebAii.Wpf;
using White.Core;
using White.Core.UIItems.WindowItems;

namespace SampleApp.Tests.Framework.Elements
{
	public class App
	{
		public WpfApplication ApplicationWebAii { get; private set; }
		public Application ApplicationWhite { get; private set; }

		public App(WpfApplication webAiiApp, Application whiteApp)
		{
			ApplicationWebAii = webAiiApp;
			ApplicationWhite = whiteApp;
		}

		public MainWindow MainWindow
		{
			get
			{
				return new MainWindow(ApplicationWebAii
					.WaitForWindow(MainWindow.WINDOW_NAME).Find);
			}
		}

		public OpenFile OpenFile
		{
			get
			{
				return new OpenFile(GetWindowByName("Open"));
			}
		}

		public MessageBox MessageBox
		{
			get
			{
				return new MessageBox(GetWindowByName(""));
			}
		}

		private Window GetWindowByName(string windowName)
		{
			// Workaround as method GetWindow(string title) is not working
			foreach (Window window in ApplicationWhite.GetWindows())
			{
				if (windowName.Equals(window.Name))
				{
					return window;
				}
			}
			return null;
		}
	}
}

The constructor takes an instance of Telerik Testing Framework’s application (WpfApplication) and TestStack White’s application (Application). Those are stored in the App instance.

Access the Page Objects

Each window in a real application is represented by a property in the App class. When accessed a new object of this page object class is created and its elements can be accessed.

WPF page objects require VisualFind in order to be instantiated. It is obtained by first locating the window with Telerik’s

public WpfWindow WaitForWindow(string caption);

From the located window we need only the VisualFind which is used internally to locate elements on that particular window.

WinForms page objects require White’s Window instance in order to be instantiated. The window is located by

public virtual Window GetWindow(string title);

I found this method not always working so I’ve made a workaround method

private Window GetWindowByName(string windowName);

New Page Objects vs. Cached Page Objects

In the example above every time, an action is required a new page object is instantiated. In some cases instantiating the object may require longer time or you might need some properties in this object preserved during tests. In such cases, you may use Singleton design pattern and instantiate only one object.

private MessageBox messageBox = null;
public MessageBox MessageBox
{
	get
	{
		if (messageBox == null)
		{
			messageBox = new MessageBox(GetWindowByName(""));
		}
		return messageBox;
	}
}

Both approaches have pros and cons. In case of new page object, you always work with a fresh instance without any previous state saved. This might require more time to instantiate the objects and you are not able to save previous states. Cached objects may be much faster as a performance but having internal state may lead to unexpected bugs in your automation.

Base test

Finally to make all work we need an instance of App. The instance is created in BaseTest.cs class.

using ArtOfTest.WebAii.Core;
using SampleApp.Tests.Framework.Elements;
using White.Core;

namespace SampleApp.Tests.Framework.Tests
{
	public class BaseTest
	{
		protected App App { get; set; }
		private string applicationPath =
			"C:\\SampleApp\\SampleApp\\bin\\Debug\\SampleApp.exe";

		protected void Start()
		{
			if (App == null)
			{
				Application appWhite = Application.Launch(applicationPath);
				Manager manager = new Manager(false);
				manager.Start();
				App = new App(
					manager.ConnectToApplication(appWhite.Process), appWhite);
			}
		}

		protected void Stop()
		{
			if (App != null && App.ApplicationWhite != null)
			{
				App.ApplicationWhite.Kill();
			}
			App = null;
		}
	}
}

All tests inherit from the base test class. Initialise and clean up code is added in the base test. In our case Start() method is the initializer. It must be called in order to instantiate App class. App property is protected so every extending class has access to it.

Initialise the frameworks

In order to start the application under test, we need the full path to the exe file. In this example, this is hardcoded but in real life, it will be configurable. Start the application with White:

public static Application Launch(string executable);

Once started then connect to it with Telerik framework by creating a Manager and use its

public WpfApplication ConnectToApplication(Process proc, string pid = null);

The process is obtained out of White Application.Process property. Opposite launch order is not working. White is not able to Attach to running process.

Use page objects

Once Start() method is called, the application under test is started and both frameworks are connected to it you can simply do in your test:

App.MainWindow.ClickBrowseButton();

This will find and create a new instance of MainWindow and then it will find and click Browse button. Your framework defines the actions on elements which are later used in actual tests. Once all the work on framework has been done it is that simple to build your tests.

Clean up

Stop() method is called at the end of the test in order to close the application under test by killing the underlying process.

The tests

This is unit test created with MS Unit Testing Framework in order to demonstrate real testing on the application.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using SampleApp.Tests.Framework.Tests;

namespace SampleApp.Tests
{
    [TestClass]
    public class UnitTest1 : BaseTest
    {
		[TestInitialize]
		public void Initialise()
		{
			Start();
		}

		[TestMethod]
		public void OpenFile_OnCancel_GivesMessage()
		{
			App.MainWindow.ClickBrowseButton();
			App.OpenFile.ClickCancelButton();
			Assert.AreEqual("Problem occured, try again later",
				App.MessageBox.GetText());
			App.MessageBox.ClickOkButton();
		}

		[TestMethod]
		public void OpenFile_OnAttachFile_GivesMessageAndFileIsShown()
		{
			string filePath = @"C:\SampleApp\SampleApp\bin\Debug\HappyFace.jpg";
			App.MainWindow.ClickBrowseButton();
			App.OpenFile.EnterFileName(filePath);
			App.OpenFile.ClickOpenButton();
			Assert.AreEqual("Successfully done", App.MessageBox.GetText());
			App.MessageBox.ClickOkButton();
			Assert.AreEqual(filePath, App.MainWindow.GetFilePathAtIndex(1));
		}

		[TestCleanup]
		public void CleanUp()
		{
			Stop();
		}
    }
}

Unit testing frameworks

Unit testing frameworks are designed to run tests in random order. Before each test method annotated with [TestInitialize] is run. In our case application is started. After each test method annotated with [TestCleanup] is run. In our case application is stopped. For this simple application running tests with a unit testing framework is OK. We are not doing unit tests but functional once. So for bigger and more complex tests unit testing frameworks are not very convenient. I’ve created very simple tests runner. This post describing the need of such tests runner.

This post shows how to build up the framework based on page objects. Next post is WPF automation – running the tests.

Related Posts

Read more...

WPF automation – locating and structure of WPF elements

Last Updated on by

Post summary: Guide how to locate WPF elements with Telerik Testing Framework.

References

This post is part of Automation of WPF applications with Telerik Testing Framework and TestStack White series. The sample application can be found in GitHub SampleApp repository.

MainWindow Page Object

MainWindow.cs class is a representation of the main window of our sample application which is WPF. Note that code here is shortened. The full code can be found in GitHub repository.

using ArtOfTest.WebAii.Controls.Xaml.Wpf;
using ArtOfTest.WebAii.Silverlight;
using ArtOfTest.WebAii.TestTemplates;
using System.Threading;

namespace SampleApp.Tests.Framework.Elements
{
	public class MainWindow : XamlElementContainer
	{
		public static string WINDOW_NAME = "MainWindow";
		private string mainPath =
			"XamlPath=/Border[0]/AdornerDecorator[0]/ContentPresenter[0]/Grid[0]/";
		public MainWindow(VisualFind find) : base(find) { }

		private Button Button_Browse
		{
			get
			{
				return Get<Button>(mainPath + "Button[0]");
			}
		}

		public void ClickBrowseButton()
		{
			Button_Browse.User.Click();
			Thread.Sleep(500);
		}
	}
}

MainWindow is following Page Object design pattern. Elements are private Properties. Actions on elements are public methods that are the actual building blocks of the tests. Do not just add action methods for the sake of adding them. Add them if only the tests need such action.

If the element is used in only one action then it could be inside the action method, but if the element is used more than one it is mandatory to keep it as separate property. The main idea is to avoid duplications in order to improve maintainability. Remember to stay DRY: one element must be defined in only one place.

MainWindow class extends XamlElementContainer which comes from the framework. The constructor takes VisualFind object and passes it to XamlElementContainer‘s constructor. This allows us to use framework’s methods for location of elements. In our case

public TControl Get<TControl>(params string[] clauses)
	where TControl : ArtOfTest.WebAii.Controls.Xaml.IFrameworkElement;

This is the strategy used by the Test Studio generated tests and I prefer it.

A different approach for MainWindow

Another element structure could be not to extend XamlElementContainer but pass a VisualFind object through MainWindow’s constructor and use it internally to locate elements.

using ArtOfTest.WebAii.Controls.Xaml.Wpf;
using ArtOfTest.WebAii.Silverlight;
using System.Threading;

namespace SampleApp.Tests.Framework.Elements
{
	public class MainWindow
	{
		public static string WINDOW_NAME = "MainWindow";
		private string mainPath =
			"XamlPath=/Border[0]/AdornerDecorator[0]/ContentPresenter[0]/Grid[0]/";
		private VisualFind visualFind;
		public MainWindow(VisualFind find)
		{
			visualFind = find;
		}

		private Button Button_Browse
		{
			get
			{
				return visualFind.ByExpression(
					new XamlFindExpression(mainPath + "Button[0]")).
					CastAs<Button>();
			}
		}

		public void ClickBrowseButton()
		{
			Button_Browse.User.Click();
			Thread.Sleep(500);
		}
	}
}

How to locate elements is described in finding page elements article.

XamlPath

As you can see I’m using exact XamlPath find expression in order to locate my elements because I find it consistent and easy to maintain. XamlPath syntax is pretty similar to XPath. The difference is its indexes are zero-based (Button[0] is the first element) and it doesn’t provide predicates and axes. The hard part is to get the XamlPath. I have found this lovely tool WPF Inspector. It gives a lot of information about the structure of WPF application.

WPF Inspector

WPF Inspector

This is a screenshot of the XamlPath for Browse button. In more complex UIs even with this great tool, it is not that easy to get the XamlPath. If you find it hard you may consider other find expressions.

All elements on MainWindow are only WPF thus an instance of White is not needed. In case of WinForms content hosted inside WPF, you can pass an instance of White through elements’ constructor and use it in actions inside.

public MainWindow(VisualFind find, Application applicationWhite) : base(find)
{
	appWhite = applicationWhite;
}

Having an instance of White inside the class you can work with it as explained in WPF automation – locating and structure of WinForms elements post.

Related Posts

Read more...

WPF automation – projects structure

Last Updated on by

Post summary: How to structure projects in the course of WPF automation.

References

This post is part of Automation of WPF applications with Telerik Testing Framework and TestStack White series. The sample application can be found in GitHub SampleApp repository.

Overview

For better maintainability and good design, automation testing is separated into two projects. One is the so-called framework project. It has knowledge about third used party frameworks (Telerik Testing Framework, TestStack White, Selenium, Watij, etc.). It operates on elements via those third-party frameworks. Framework exposes actions that are building blocks of the tests. The other project is the tests. It doesn’t know anything about used automation frameworks. It uses methods exposed by an internal framework and builds the tests with them. The idea is that one team/person with development knowledge can be responsible for the internal framework, others can be responsible for writing well-designed tests using the internal framework only. Another benefit of two projects is the ability to completely change internal framework project without affecting test logic at all. Here is the structure of my sample projects:

Projects structure

Projects structure

SampleApp – This is the application under test. Generally, it is not in the test project, you receive it from developers or from nightly build or from some other place. For the purpose of this demo, I’ve created a very basic application that uploads an image and shows it inside. There is attached image (HappyFace.jpg) that is used in the tests.

SampleApp.Tests – Here is the most important artifact – the tests, the purpose of all this fuss. In the demo, this is made as UnitTest with MS Unit Testing Framework. You can use whatever run strategy you like – another unit testing framework (xUnit, nUnit, etc.) or you can build your own tests runner. I have built my own tests running because by definition unit tests should be independent of each other thus MS Unit Testing Framework runs them in random order. It might be possible to manage order, but this will require managing of some sort of external files. It gives too much overhead to me.

SampleApp.Tests.Framework – This is where the interesting part is. Here are the elements – main application form (WPF), message boxes shown on success or error (WinForms) and open file dialogue (WinForms). MainWindow is manipulated with Telerik Testing Framework, other two are manipulated with White. App.cs is a holder which represent application itself and elements are accessible through it. BaseTest holds an instance of App. It is extended by UnitTests and App and its elements are accessible.

Next post is WPF automation – locating and structure of WPF elements in the code.

Related Posts

Read more...

Automation of WPF applications

Last Updated on by

Post summary: Overview how to successfully automate WPF application with Telerik Testing Framework and TestStack White.

I’ve spent lots of time in automation of a WPF application. Nowadays the world is dealing with web application and desktop application are fading away. Nevertheless, desktop applications still have their own private space and I hope these series of posts will be useful to someone.

Preface

An application under test is created with WPF but has WinForms grids included on different windows presenting lots of information. Performance is the main reason to use WinForms grids inside a WPF application. WPF grid with 40 columns and 100 rows lags a lot. After research and proof of concept of commercial and open source tools and frameworks, two were chosen: Telerik Testing Framework and TestStack White. They provide flexibility and maintainability which is so vital in a fast-changing application. Both are used with C#. Every one has its own weaknesses and strengths but both made a perfect synergy to provide you the possibility to automate almost everything.

Telerik Testing Framework

Extremely powerful and free to use framework. You can purchase additional support which is at reasonable prices. Telerik also provides Test Studio, a tool and MS Visual Studio plug-in, build on top of the framework. This is also an option, but for me using a tool gives more restrictions than benefits. Their framework is the best available for testing WPF applications. It is very easy to use. Elements are easily located by XamlPath (very similar to XPath). Of course, there are other locate options. The framework provides very rich API with lots of operations over the elements. Still, its powerfulness is limited to WPF. It is not that good with WinForms elements. Telerik Testing Framework requires installation as it copies lots of assemblies in GAC.

TestStack White

Extremely powerful open source framework. Build as a wrapper of Microsoft UI Automation framework you can automate almost everything with it. But this comes at a price. It is hard to locate elements. I use it only where Telerik Testing Framework is not capable to do the work – WinForm grids, context menus, closing windows with small X in the top right corner?! Yes, those are WPF inside but are hosted in operation system window and Telerik has no access to it.

In GitHub, I have uploaded an MS Visual Studio 2013 project with very simple application taken from this example. I have added very basic tests to it to illustrate how it is done. With upcoming posts, I’ll explain in details the idea and implementation.

Below is a list of posts included in the series:

  1. Introduction (current post)
  2. WPF automation – projects structure
  3. WPF automation – locating and structure of WPF elements
  4. WPF automation – locating and structure of WinForms elements
  5. WPF automation – using the elements
  6. WPF automation – running the tests

Related Posts

Read more...