Microsoft has made their internal Silverlight unit testing framework available for all developers. It provides an extensible testing solution for applications, controls and class libraries. This page goes over the basics of unit testing for Silverlight applications and how to set up test projects, but does not go over unit testing methodology.
To get started, you must first download the Silverlight Unit Test Framework. You can also download the Visual Studio 2008 project templates for Visual Basic and C#.
The source code for the testing framework is available as part of the Silverlight Toolkit on CodePlex.
Test projects are commonly added to the same solution where your main application or library resides. This makes it easier to reference the project with the classes being tested and also helps remind that unit testing is a core task before and during development.
At this point it is recommended to verify that the project namespace matches your naming conventions. A common naming pattern is to use your main project's namespace appended with Test or Testing. For example if your main project has the namespace Yahoo.Samples.Silverlight, the namespace for the tests would be Yahoo.Samples.Silverlight.Testing.
Finally, add a project reference to each project you are testing.
At this point you should have a test project created with a stub test class and references to the projects you are testing. To verify everything was set up correctly, you can simply run the test project as you would any other project. However, running the test project in debug mode will result in Visual Studio breaking into debug mode for every inconclusive and failed test, along with every expected exception. The avoid this you have several options:
Writing unit tests is similar to writing the actual code for your project. In both cases you create a project and classes that use various objects. As such, you should take the same care in writing and documenting your tests as you do with the actual code. The main difference is that test classes and methods are marked with special attributes to inform the testing framework of various aspects about the code and provide contextual information in the test results.
The following table lists the most common attributes used when writing tests.
||Specifies that the class contains methods to run during a test.|
||Specifies that the method is a test.|
||The given exception should happen during the test for the test to be considered successful.|
||The test has completed only after the
||Marks a test as belonging to the named group. Multiple tags can be applied to a single class/method. Tags are also automatically generated with names in the format "namespace + name".|
||Describes the test to give more context when viewing the test results.|
||Describes a known issue and flips the test result.|
Assert class methods are used to compare values in a test against the expected results. The following table lists the most common methods.
||Verifies that the given values are/are not equal.|
||Verifies that the given variables refer to the same / different objects.|
||Fails the test.|
||Test was inconclusive. Often used to mark that the test hasn't been implemented yet.|
||Verifies the condition is
||Verifies the given object is / is not of a specified type.|
||Verifies the given object is / is not
The following example shows a basic test class with a simple test method. This test will fail since it has been
marked with the
Bug attribute with the
Fixed property set to
The bug would then be fixed later and the
Fixed property set to
true and the test would pass.
The test framework has basic support for testing asynchronous scenarios such as events, UI tasks and multi-threaded operations.
Performing asynchronous tests involves pushing tasks into a queue and calling the
TestComplete method to
notify the test framework that the test has completed.
The following shows an example of testing for an asynchronous event. A timer is created to wait two seconds and an event handler is hooked up to signal that the event was raised. Tasks are then queued up to trigger the event, In this case tasks include starting the timer, waiting for the event to be raised, and finally checking an additional value that should have been set.
NOTE: Currently the
Timeout attribute is not implemented and the test runner will hang if the event isn't raised. You
may wish to add a custom timer to avoid this situation, especially if you are running tests as part of an automated process.
Here are some general tips for writing tests:
Related information on the web is listed below.