Hi Remco,
After steadfastly refusing to unit test Microsoft's UI code for them in the past and working only in the ViewModel and Model tiers, I find myself wanting to write a custom control and therefore test that it works correctly. Which is nice, but also means that some of the time it has to be shown.
Lets say that I am doing the following
[Test]
public void ShouldHaveCells()
{
GameGrid gameGrid = null;
OnUIThread(() =>
{
gameGrid = new GameGrid();
gameGrid.DataContext = new GridViewModel(new Model.Grid(3, 3));
BuildWindowFor(gameGrid);
});
var actualGrid = gameGrid._theGrid;
actualGrid.ColumnDefinitions.Count().ShouldEqual(3);
actualGrid.RowDefinitions.Count().ShouldEqual(3);
}
private static void OnUIThread(Action action)
{
var setup = Task.Factory.StartNew(() =>
{
action();
}, CancellationToken.None, TaskCreationOptions.None, new StaTaskScheduler(1)); //From Nuget Package MSFT.ParallelExtensionExtras 1.2.0
Task.WaitAll(setup);
}
private static void BuildWindowFor(object content, [CallerMemberName] string callerName = null)
{
var window = new Window() { Title = "This window was started for " + callerName };
window.Content = content;
window.Show();
window.Activate();
}
All is fine but the window pops up (annoyingly) every time I stop making code changes.
If however I try hiding my windows on another desktop (see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682124(v=vs.85).aspx) ....
//Added to the start of BuildWindow above
var openDesktop = User32.OpenDesktop(desktopName, 0, false, User32.ACCESS_MASK.NORMAL);
if (openDesktop == IntPtr.Zero)
{
openDesktop = User32.CreateDesktop(desktopName, null, null, 0, User32.ACCESS_MASK.NORMAL, IntPtr.Zero);
}
var hasSetThread = User32.SetThreadDesktop(openDesktop);
if (!hasSetThread)
{
var error = Marshal.GetLastWin32Error();
var hr = Marshal.GetHRForLastWin32Error();
var exception = Marshal.GetExceptionCode();
Debug.WriteLine(desktopName + ": error=" + error +" HR:"+hr+" Exception:"+exception);
//error.ShouldEqual(0);
}
.... then it works beautifully under VS2013 Test Explorer with NUnitAdpater, but not nCrunch.
From the MSDN documentation it seems that you need the SetThreadDesktop to be before any UI calls are made, so I thought it might be because NCrunch keeps its test runners alive. I tried setting 'Terminate test runner tasks when all test execution is complete' to True and 'Max number of test runner processes to pool' to 0, but to no avail.
Any suggestions?
If you need the full code example with PInvoke just shout, and I'll email it over.
Remco NCrunch Developer
#4733
16 Oct 2013 07:43 UTC
Hi,
Thanks for sharing this issue. I have a feeling that you're probably right in the idea that this may be NCrunch's test runner usage patterns causing this to fail.
There are probably several ways around this. The easiest I can think of would be to adorn the test(s) with IsolatedAttribute. In this way, NCrunch will use a single test runner process for each test, removing the possibility of interference or sequencing issues.
Another option may be to place this code in a SetUpFixture. If the tests are placed within their own specialised project, this could be a clean way to make sure the code is run before any test in the project kicks off.
I'm keen to hear if either of these does the trick. If not, let me know and I'll do some digging to see if something else is going on here.
Cheers,
Remco
Thanks for sharing this issue. I have a feeling that you're probably right in the idea that this may be NCrunch's test runner usage patterns causing this to fail.
There are probably several ways around this. The easiest I can think of would be to adorn the test(s) with IsolatedAttribute. In this way, NCrunch will use a single test runner process for each test, removing the possibility of interference or sequencing issues.
Another option may be to place this code in a SetUpFixture. If the tests are placed within their own specialised project, this could be a clean way to make sure the code is run before any test in the project kicks off.
I'm keen to hear if either of these does the trick. If not, let me know and I'll do some digging to see if something else is going on here.
Cheers,
Remco
Post a reply
Log in to reply.