Profiling NUnit Tests in the .NET Framework 4

Everyone probably came across application profiling, but how often did you have to profile tests?
As my personal experience has shown, in order to successfully complete this task for an assembly assembled under the .NET Framework 4 , it is necessary to perform a series of actions, for the search of which I had to spend some time. Therefore, I decided to generalize the gained experience into a single compilation and make it available so that others could avoid the rake that I had to step on.
The task was quite real - it was necessary to measure the memory consumption when lifting a large number of tests - in order to remove memory leaks.
In the working draft, NUnit 2.4 was used as a test environment , and was selected as a profiler.NET Memory Profiler 4.0.
Test data
Let's make an assembly containing an example test.
To do this, in Visual Studio 2010, create a new WPF User Control Library project , add nunit.framework.dll to the references , and create a TestClasses file for tests.

Fig. 1 References and the composition of the project.

Fig. 2. Project options window.
We will write one single test, the code of which is given below:
using System;
using NUnit.Framework;
using System.Windows.Controls;
using System.Windows;
namespace WpfClassLibrary {
[TestFixture]
public class MyTests {
[Test]
public void TestForProfiling() {
TextBox textBlock = new TextBox();
textBlock.Text = "UIElement Test";
Assert.IsTrue(textBlock.Text.Length > 0);
MessageBox.Show("Ready for Collect Snapshot...");
}
}
}
In this example, I added code to the test to send a message. This will show more clearly that the test code was indeed called. To take snapshots at different stages of the selected test, arranging such messages can also be very useful - this will allow you to make the necessary pause during the test.
Profiler Setup
How to start profiling a test?
Launch the profiler and specify the console version of NUnit as the launched application. To do this, specify the file nunut-console.exe (in my case, it was located in the following path: C: \ Program Files (x86) \ TestDriven.NET 3 \ NUnit \ 2.4 \ ).
Now it remains to set the arguments. It is enough to run nunut-console.exe with the key "/?" to get the list of interest to us. The file launch format looks like this:
NUNIT-CONSOLE [inputfiles] [options]
That is, you must specify the path to the assembly with the tests, specifying options. We will be interested in only one:
/ run = STR Name of the test to run
I want to note that the full name must be specified as the test name !path to the test method, including the namespace.
Come to the fact that prescribe the following string as an argument for the profiler:
the C: \ the Sandbox \ WpfClassLibrary \ WpfClassLibrary \ bin directory \ the Debug \ WpfClassLibrary.dll /run=WpfClassLibrary.MyTests.TestForProfiling

Figure 3 Profiler window settings to run the test
seems to be all ready, but under the given conditions the test fails. It's time to figure out why this is so ...
How to let NUnit run builds compiled in VS2010?
Let's try to run our test using nunit-console.exe, and not the profiler.
As a result, we get the error System.BadImageFormatException :
Unhandled Exception:
System.BadImageFormatException: Could not load file or assembly 'C: \ Sandbox \ WpfClassLibrary \ WpfClassLibrary \ bin \ Debug \ WpfClassLibrary.dll' or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.
File name: 'C: \ Sandbox
\ WpfClassLibrary \ WpfClassLibrary \ bin \ Debug \ WpfClassLibrary.dll' Since that our assembly is built under Framework 4, it cannot be loaded to run the test.
We find the file nunit-console.exe.configlocated next to the console version of NUnit. On my machine, it is located here:
"C: \ Program Files (x86) \ TestDriven.NET 3 \ NUnit \ 2.4 \ nunit-console.exe.config"
We are looking for the startup section , in which the description tells us:
The startup section may be used to specify the runtime versions
supported in the order that they will be used if more than one
is present.
-->
* This source code was highlighted with Source Code Highlighter.This section contains information about support for the .NET Framework versions 1 and 2, but not at all 4.
We create our startup section (or modify the existing one) and add a line there to support the launch of building the 4th framework. The line to add looks like this:
* This source code was highlighted with Source Code Highlighter.The first problem is resolved - NUnit can now run tests compiled under the .NET Framework 4.
Configure the start of the assembly with tests in the STA
Let's get back to our test. It launches and runs fine if you run it directly from Visual Studio 2010 using the integrated TDD tools. If you try to run a test from nunit.exe or its console version (for the console, do not forget to specify the test assembly as the parameter), the following error will occur:
MyTestLib.MyTests.TestForProfiling:
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.

Fig. 4 Error when starting a test in NUnit
From the message and call stack, it becomes obvious that it is necessary to run tests in the STA streaming apartment. Those interested can read the details here or here .
Running tests for WinForms or ASP.NET may differ from the example considered by WPF, but, nevertheless, there are a number of restrictions (such as OLE drag-n-drop, working with clipboards, etc.) that will require running tests in STA .
In the newer version of NUnit 2.5, there is even a special RequiresSTAAttribute attribute for these purposes.
For those who are limited to using NUnit version 2.4, you can use the configuration files .
For the assembly under test, create such a file indicating the need to run tests in the STA. I want to note that it must have a name that matches the assembly name and the postfix config , and should be located next to it.
Create a file with the nameWpfClassLibrary.dll.config as follows:
* This source code was highlighted with Source Code Highlighter.
The second problem has been resolved - the test build file now has a configuration file that determines the correct way to start from NUnit.
Profile test
It's time to check the result. Run the profiler and make sure that the test has been called.

Fig.5 Test profiling.
The problem is solved - the assembly with the test is loaded correctly and the test is running.
In addition, I want to say that there is another option for launching the profiler. The essence of the method is that you can tell the system to start a specific process (for TDD it is ProcessInvocation86.exe) under a debugger (profiler). This is done by registering the Image File Execution Options key in the registry .
But this is a topic for a separate article ...
That's all! I hope that this information will be useful and save time on a similar task.
Successful testing and profiling!