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.co...indows/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?