Visual Studio Team System Testing tools and multithreading

by Miha Markič 28. August 2007 11:43

If you've been doing testing with Visual Studio Team System (VSTS) you have probably noticed that each test might be run in different thread. And the same is valid for set up and clean up methods. This feature might be a good one generally but not if you are testing UI.

I worked a scenario where I start application's main form within ClassInitializeAttribute decorated MyClassInitialize method. Then I do various tests in sequence (I use ordered tests) and finally I close the application in ClassCleanupAttribute decoreated MyClassCleanup method.

Here is a how my code looks (simplified):

private MainFrm mainFrm; // Form derived class [ClassInitialize()] public static void MyClassInitialize(TestContext testContext) { mainFrm = new MainFrm(); mainFrm.Show(); } [ClassCleanup()] public static void MyClassCleanup() { mainFrm.Dispose(); mainFrm = null; } [TestMethod] public void SomeTest() { // do some test with mainFrm }

Since I am using an ordered test to executes tests in sequence I would expect that tests are run in the same thread. However this is not the case nor you can force VSTS to use a single thread. Why is it important anyway? Because all operations to the UI have to be done within the thread that created UI control. Any access from different thread should and probably would cause an exception at best. Ouch, that's sounds like a showstopper for UI testing (besides the fact that VSTS doesn't support UI testing). To tell you the truth I was really surprised that an option to run tests in a single thread is missing.

So I start considering switching to NUnit (and TestDriven.net perhaps) since my tests weren't that many so far. The switch would cause me more work and more administration and I wasn't that happy to take NUnit path. Then I found the solution, which is really very simple. You have to execute all operations on UI thread and Control.Invoke method does exactly that. Here is modified code:

private MainFrm mainFrm; [ClassInitialize()] public static void MyClassInitialize(TestContext testContext) { // this method remains same - this thread creates UI mainFrm = new MainFrm(); mainFrm.Show(); } [ClassCleanup()] public static void MyClassCleanup() { // if thread is not one that created the form then excute an // Invoke call to switch thread if (mainFrm.InvokeRequired) mainFrm.Invoke(new MethodInvoker(MyClassCleanup)); else { mainFrm.Dispose(); mainFrm = null; } } [TestMethod] public void SwitchToFootball() { // if thread is not one that created the form then excute an // Invoke call to switch thread // Do the same if clause for any test that has to interact with UI classes // (indirectly or directly) if (mainFrm.InvokeRequired) mainFrm.Invoke(new MethodInvoker(SwitchToFootball)); else SwitchTo(BetCategoryCode.Football); }

Basically, before each test execution you have to make sure it executes in correct thread (the one that created UI objects). You do that by first checking whether the current thread has to be switched by checking Control.InvokeRequired property (both this property and Invoke method are thread safe). If this property is true you have to switch threads by invoking Control.Invoke method with a delegate to the method to execute (which is the same in this case) otherwise no switch is required. And you don't even have to create different delegate types since a test method has to be a parameterless method and thus System.Windows.Forms.MethodInvoker delegate is good for all methods.

And that's it. Happy UI testing.

Tags:

.net

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

Miha Markic

About me
Righthand
 
Microsoft MVP
 
Developer Express' DXSquad
INETA Country Leader for Slovenia
INETA Country Leader for Slovenia

Slovene Developer Users Group Lead
Friends of Red-Gate
LLBLGenPro Partner

Miha currently works as a free lance consultant and software developer specialized in .net area.
He graduated in Computer and information science at the University of Ljubljana, Slovenia. He has accumulated experience in various programming languages such as Java, Visual Basic 3-6 (MCP), Visual C++, Delphi, C# and VB.Net through years.
He has experience in practically all (technical) stages of project development, including planning, framework development, user interface, business processes, as well as testing and documenting. He has worked on big and small projects in Slovenia and abroad (e.g. participated in completing level 3 IS for the Nucor steel plant, Hertford, USA).
Currently he enjoys programming in .net environment using C#. Since 2000 he has been active in Developer Express' DX Squad and has been ECDL trainer and tester. He also gives lectures on conferences and other events in Slovenia.

Month List

Tag cloud

Most comments

Paulius Paulius
1 comments
us United States
Meh Meh
1 comments
us United States
bart dm bart dm
1 comments
nl Netherlands

RecentComments

Comment RSS