Most people don't know that you can use the .Net Unit Testing studio for your Silverlight functions! This includes the ability to run tests without a web server. In fact, you don't even need to run the silverlight in a browser to see the test results. If that's not enough, your test results will also be able to integrate with Studio and even TFS Team Build if you need them to. Sound good? Read on...

Quick note, I apologise for my long absence since we've had a recent edition to my family. Hopefully I can contribute some pointers over the next few months.

To demonstrate how to set up unit testing I have created a Silverlight project called "SilverlightTestedApp" and a corresponding SilverlightTestedApp.Web project to host it using Visual Studio 2010 (I'm doing this demo using Silverlight 4.0 In-browser but out of browser and other versions should all work fine).



I am going to go ahead and modify the project to hold 2 basic TextBox elements for input and a TextBlock element to show the output. We are going to display the output based on user input, so I have added the following code and event handlers:



When I run the project I can see the output as a combination of the 2 input fields. I have simulated a common UI scenario where the client-side front-end is required to make a decision and modify the data so that it can be displayed without locking up the UI. In this case, the text components should not exceed 20 characters. If they do, take the first 17 and append an ellipse ("...") to the end of that component. The 2 components are shown side by side in the output text box separated by a semicolon.



In order to do a unit test on this project, I would first want to refactor my code into 1 method. The following section is an example of how the code could be simplified and made reusable:



Now we can use this method throughout the class to convert any string to a Display Name (max 20 characters) using our conversion algorithm. It is simple, but functional. You may think that this method is too simple to unit test but I will show you how easily it can fail. Let's get started writing some unit tests...

I'm going to create 2 projects: AppFunctions and AppFunctions.Silverlight. AppFunctions will hold our functions, and this project should be of type .Net Class Library (Not Silverlight!).

scr5

I am next going to add the AppFunctions.Silverlight project. This should be a Silverlight class library. My IDE also asked me the version, which I specified as Silverlight 4.0.



Your solution now contains 4 projects. The source code we write is required to build twice. It should build once as a .Net 4.0 Class Library for unit tests and once as a Silverlight Class Library for the runtime app. To set this up, put the methods you want to test in the .Net project. In my case I have a new code file called "NameFunctions" with the GetDisplayName method inside (I also deleted the "Class1.cs" files that were created by default.) as shown:



Note that the class and method are made public. The next step is to right click your AppFunctions.Silverlight project, click "Add" -> "Existing Item" and browse to the NameFunctions.cs file. When you have selected the file do not click "Add". Instead, click the arrow on the right of the "Add" button and select "Add As Link".



We also need to wire this up to the Silverlight App. Right click the original project, click "Add Reference" and choose the "Projects" tab in the dialog. Then choose the AppFunctions.Silverlight project. In the code file you must add a Using reference to the AppFunctions namespace and create a NameFunctions object as shown: Finally, use this object to invoke the method you need to call.



This could be done using static methods as well, and I don't see any problem with that. Build your solution and confirm that the stack is functioning as it was before we moved the code to a different project.

Time to recap:

What are we attempting to do:
   *  Separate logical methods into a different assembly
   *  Link the assembly so that it can be used in silverlight, but tested in .Net
   *  Write and perform tests using Visual Studio

All that's left to do now is the Unit Tests. To do this, right click your solution and click "Add New Project". In the dialog, select the "Test" grouping and select "Test Project". I have named mine AppFunctions.Test.



Next, Right Click the Test Project and select Add -> New Test to create a unit test. Your test project requires reference to the assembly you want to test. In my case I have added a project reference to "AppFunctions" and referenced it to write the following test class:

namespace AppFunctions.Test
{
    [TestClass]
    public class NameFunctionsTest
    {
        [TestMethod]
        public void GetDisplayNameNullTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string output = funcProvider.GetDisplayName(null);
            Assert.AreEqual(output, null);
        }

        [TestMethod]
        public void GetDisplayNameShortTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string testString = "abc";
            string output = funcProvider.GetDisplayName(testString);
            Assert.AreEqual(testString, output);
        }

        [TestMethod]
        public void GetDisplayNameLongTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string output = funcProvider.GetDisplayName("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
            Assert.AreEqual(20, output.Length);
        }

        [TestMethod]
        public void GetDisplayNameFormatTest()
        {
            NameFunctions funcProvider = new NameFunctions();
            string output = funcProvider.GetDisplayName("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
            Assert.IsTrue(output.EndsWith("..."));
        }
    }
}

Remember to build the solution to make sure no errors have been introduced. Now that the tests are written, running them in the IDE is quite easy. My preference is to go to Test -> Windows -> Test View



If the project has been built you can run the tests straight away in the test view by selecting the names of the tests and pressing the "Run" button.



I have intentionally created a test that will fail! passing Null into my method would causes an exception. Now by simply changing the basic function we can make this test pass. Below is a sample of improving a basic string function to cater for a null parameter value:

        public string GetDisplayName(string textInput)
        {
            string result = null;
            if (textInput != null)
            {
                if (textInput.Length < 20)
                    result = textInput;
                else result = textInput.Substring(0, 17) + "...";
            }
            return result;
        }

This will cause the GetDisplayNameNullTest to pass!

I hope that these simple examples will help someone to set up a few unit tests for their code and hopefully improve their whole Silverlight solution.

Happy coding!

Zero Gravity Chimp