Monday, March 1, 2010

ASP.NET MVC2RC in VS2010RC– Adventures of the plain old beginner. Part 3 – Integrating Silverlight and Silverlight tests.

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:

 image

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/

image 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.

 

Not sure if this is an implication of having Gallio runner installed with integration to VS2010 or just some quirk of SL4 tools in VS2010RC after the hack install, but I was not able to run Silverlight unit tests internally in VS. Only via web browser. image

I was really pleased with informative messages Silvelight testing framework provides for exceptions:

image

And then at the end I was able to craft one unit test and one UI test:

image

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: