Main idea for this sprint would be to integrate a small Silverlight control and have it unit and UI tested.
In order to make it testable, it is a good idea to start with MVVM right from the start. Good and short entry on MVVM for Silverlight is: http://development-guides.silverbaylabs.org/Video/Model-View-View-Model---Silverlight-2#videolocation_0
As for testing tools Silverlight 4 unit testing framework is the way to go, it is contained inside the Silverlight 4 Tools for VS2010Beta 2 (http://www.microsoft.com/downloads/details.aspx?familyid=68A158AF-9BB8-4855-A724-D09D196EAAF3&displaylang=en) and giving an error screen when trying to install with VS2010RC. Not a problem though, here is the link how get around it: http://sorokoletov.com/2010/02/hate-2-wait-silverlight-4-beta-2-vs-2010-rc/ or translated to English version http://translate.google.com/translate?hl=en&sl=auto&tl=en&u=http%3A%2F%2Fsorokoletov.com%2F2010%2F02%2Fhate-2-wait-silverlight-4-beta-2-vs-2010-rc%2F
After implementing the workaround Silverlight 4 tools become first class citizen in VS2010RC:
To actually using Silverlight 4 tools for testing I found the following link as most useful http://www.jeff.wilcox.name/2009/11/november-walkthrough/
I needed to mock some dependencies and Silverlight version of Moq was 100% helpful with that. I needed all of the dlls inside the release archive to be referenced. |
I was really pleased with informative messages Silvelight testing framework provides for exceptions:
And then at the end I was able to craft one unit test and one UI test:
It was a bit of a fight, but all worked at the end if I forget Browser-only running of Silverlight tests. Probably I’ll revert from Gallio and just go with plain VSTests runner. Though fascinating, I have not seen that much of extra value brought to me by Gallio. I better have some uniform consistent approach that works across everything including Silverlight tests.
Providing test code for the reference. UI test:
[TestClass]
public class UITest : SilverlightTest
{
[TestMethod]
[Asynchronous]
public void Should_ShowEventGrid()
{
var sourceMoq = new Moq.Mock<IEventSource<EventBase>>();
var events = new List<EventBase>{
new EventBase{Id = "2", Text = "test"}};
// Setup mock events source
sourceMoq.Setup(es => es.GetEvents()).Returns(events);
// And use it in the view model
var eventsViewModel = new EventsViewModel(sourceMoq.Object);
// Add user control to the test panel
var testPanel = this.TestPanel;
var page = new Advaton.EventViewer.Silverlight.Main.MainPage();
testPanel.Children.Add(page);
var e = (FrameworkElement)page.FindName("LayoutRoot");
e.DataContext = eventsViewModel;
var dataGrid = (System.Windows.Controls.DataGrid)page.FindName("eventsDataGrid");
var count = dataGrid.ItemsSource.OfType<object>().Count();
Assert.AreEqual(1, count);
EnqueueDelay(2000);
// if EnqueueConditional is not used here then addition happens immediately.
EnqueueCallback(() =>
eventsViewModel.Events.Add(new EventBase { Id = "333", Text = "Adding event after a delay." }));
EnqueueCallback(() =>
{
count = dataGrid.ItemsSource.OfType<object>().Count();
Assert.AreEqual(2, count);
});
EnqueueDelay(2000);
// If you would not call EnqueueTestComplete the test never ends.
EnqueueTestComplete();
}
}
And simple unit test for a ViewModel:
[TestClass]
public class EventsViewModelTest
{
[TestMethod]
public void Should_ProvideEventsViaGet()
{
var sourceMoq = new Moq.Mock<IEventSource<EventBase>>();
var events = new List<EventBase>{
new EventBase{Id = "1", Text = "test"}};
sourceMoq.Setup(es => es.GetEvents()).Returns(events);
var evm = new EventsViewModel(sourceMoq.Object);
Assert.IsNotNull(evm.Events);
Assert.AreEqual(1, evm.Events.Count);
Assert.AreEqual("1", evm.Events[0].Id);
Assert.AreEqual("test", evm.Events[0].Text);
}
}
Next: Structure out the Silverlight part for regions and dependency injection.
Previous: Approaching unit/UI testing of ASP.NET MVC2 RC with Gallio/MbUnit.
Platform and tools: Windows 7, VS2010RC, ASP.NET MVC2 RC, Gallio, MbUnit, NUnit, Moq, Silverlight 4.0 Beta
P.S. Just forgot for one specific issue when you integrate SL into ASP.NET MVC project. You should change the source parameter to have a leading slash for your silverlight content to be loaded, from:
<param name="source" value="ClientBin/MySilverlightApp.xap"/>
To:
<param name="source" value="/ClientBin/MySilverlightApp.xap"/>
More info: http://blog.kellybrownsberger.com/archive/2009/12/10/71.aspx
No comments:
Post a Comment