Author: AutomatedQA Corp.
Last updated: March 23, 2010
Applied to: TestComplete 7
Introduction
In this article we explain unit testing of Silverlight applications with TestComplete. This kind of testing requires that the tested Silverlight application be prepared in a special way using the HTML Bridge technology. The article also contains a simple example of a Silverlight application and explains how you can make its classes and their members accessible to TestComplete in order to perform unit testing.
Basic Concepts
One of the main requirements for successful unit testing of Silverlight applications is the ability to get access to classes of Silverlight applications and to call methods and properties of these classes externally. This capability is provided by the HTML Bridge technology that lets you call Silverlight managed code from a client JavaScript code located in a web page. Therefore, by using this technology, you can also call Silverlight code from TestComplete scripts and perform unit testing of your Silverlight-based applications.
In order to make Silverlight classes and their members accessible to scripts, HTML Bridge provides the ScriptableType and ScriptableMember attributes used for making the needed Silverlight data types and members available to scripts. Also, the needed Silverlight class must be registered as a scriptable object with the use of the HtmlPage.RegisterScriptableObject method.
Note that HTML Bridge is a documented technology and you can find additional information about it in the MSDN Library.
Description of the Tested Object
We will consider a simple Silverlight application — NameExtractor. To download a sample project, use the hyperlinks from the menu in the top right corner of the page.
The application contains a class of the same name — NameExtractor. This class with its members is used as a tested object in our application. NameExtractor takes an input string containing an English/American proper name (i.e. “Mr. John Smith”) and then provides the ability to get separate name components extracted from this full name.
Let’s take a look at the definition of the class (not all members are shown below):
//C#
namespace NameExtractor
{
class NameExtractor
{
public NameExtractor()
{ ... }
public String FullName
{
get { ... }
set { ... }
}
public String Title
{
get { ... }
}
public String FirstName
{
get { ... }
}
public String MiddleName
{
get { ... }
}
public String LastName
{
get { ... }
}
public String Suffix
{
get { ... }
}
...
}
}
As you can see, the NameExtractor class contains a number of public properties. The FullName property takes an input full name. The Title, FirstName, MiddleName, LastName and Suffix read-only properties return the title, first name, middle name, last name and suffix part, correspondingly, extracted from the full name.
Also, there are a few private and protected properties and helper methods in the class. We will not give a full description of them here in the article, because we’d rather take an interest in testing the class and calling testing functions from TestComplete than in the implementation of the class to be tested. For the full implementation of the NameExtractor class, see the “NameExtractor.cs” source code file in the NameExtractor sample project.
In the next section we will discuss the UnitTestDriver class that is used to implement unit tests for our NameExtractor Silverlight class.
Creating Unit Tests
We will create unit tests for the NameExtractor class as methods of the UnitTestDriver class in the “UnitTestDriver.cs” source code file of our Silverlight project. Before creating the unit tests, we will implement a couple of helper methods in the UnitTestDriver class: the UnitTestDriver method is a constructor that creates an instance of the NameExtractor class to be tested by the UnitTestDriver class; the CheckEquals method compares two strings and throws an exception with the appropriate message if the strings are not equal. Here is the implementation of these methods:
// C#
namespace NameExtractor
{
public class UnitTestDriver
{
//an object of the tested class NameExtractor
private NameExtractor nameExtractor;
public UnitTestDriver()
{
nameExtractor = new NameExtractor();
}
private void CheckEquals(String Expected, String Actual, String Msg)
{
if (Expected != Actual)
{
String exceptionMsg = String.Format("{0} : expected {1}, but was: {2}", Msg, Expected, Actual);
Exception exception = new Exception(exceptionMsg);
throw exception;
}
}
}
}
Now, we can add our unit tests for the NameExtractor object to the UnitTestDriver class. For simplicity, we will implement two unit tests that will check two business rules of the tested object: the Test1 method checks whether the NameExtractor object can break the full name into a word list, and the Test2 method checks whether the words in the list have a strict order (the Title, the First Name, the Middle Name, the Last Name and the Suffix). For more information on the business rules defined for the NameExtractor tested object, see the Unit Testing - TestComplete Example article.
// C#
//tests
public void Test1()
{
nameExtractor.FullName = "Mr John Greench Brown, PhD";
CheckEquals("Mr", nameExtractor.Title, "Title is not correct");
CheckEquals("John", nameExtractor.FirstName, "First Name is not correct");
CheckEquals("Greench", nameExtractor.MiddleName, "Middle Name is not correct");
CheckEquals("Brown", nameExtractor.LastName, "Last Name is not correct");
CheckEquals("PhD", nameExtractor.Suffix, "Suffix is not correct");
}
public void Test2()
{
nameExtractor.FullName = "John Brown";
CheckEquals("", nameExtractor.Title, " Title is not correct");
CheckEquals("John", nameExtractor.FirstName, " First Name is not correct");
CheckEquals("", nameExtractor.MiddleName, " Middle Name is not correct");
CheckEquals("Brown", nameExtractor.LastName, " Last Name is not correct");
CheckEquals("", nameExtractor.Suffix, " Suffix is not correct");
nameExtractor.FullName = "Mr. John Brown";
CheckEquals("Mr", nameExtractor.Title, " Title is not correct");
CheckEquals("John", nameExtractor.FirstName, " First Name is not correct");
CheckEquals("", nameExtractor.MiddleName, " Middle Name is not correct");
CheckEquals("Brown", nameExtractor.LastName, " Last Name is not correct");
CheckEquals("", nameExtractor.Suffix, " Suffix is not correct");
nameExtractor.FullName = "John Brown, PhD";
CheckEquals("John", nameExtractor.FirstName, " First Name is not correct");
CheckEquals("Brown", nameExtractor.LastName, " Last Name is not correct");
CheckEquals("PhD", nameExtractor.Suffix, " Suffix is not correct");
}
Now, when you have a class to be tested and a class that will perform testing of the first one, you can access managed code of your Silverlight application from external script code from TestComplete scripts.
Preparing Silverlight Code for Unit Testing
As stated above, we will test the NameExtractor class via the UnitTestDriver helper class. So, we need to make the UnitTestDriver class accessible from scripts in order to run unit tests from TestComplete. This is where the HTML Bridge technology will help you in your unit testing. We need to perform the following steps:
- Register a Silverlight class as a script object by using the
HtmlPage.RegisterScriptableObject method (in our case, we will provide scriptable access to the methods of the UnitTestDriver class). - Mark the whole class or certain members as script objects by using the
ScriptableTypeAttribute or ScriptableMemberAttribute attributes.
In order to use a class outside of a Silverlight application, you should create an instance of the class and register it as a scriptable type (see the MSDN Library for detailed information). You can do this by calling the HtmlPage.RegisterScriptableObject method, provided by the HTML Bridge. It is recommended to call this method upon startup of your Silverlight application so that the class can be accessible from scripts when your application is running. For instance, you can call this method from the body of the Application_Startup method of the App class. This class encapsulates your Silverlight application and the Application_Startup method is the Startup event handler that performs initialization of the application. Open the “App.xaml.cs” source code file that contains the implementation of the App class in the NameExtractor project and modify the Application_Startup method in the following way:
// C#
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
HtmlPage.RegisterScriptableObject("unitTestDriver", new UnitTestDriver());
}
This code creates an instance of the UnitTestDriver class and registers it as a scriptable object with the unitTestDriver name upon the application’s startup. Now, you can use the unitTestDriver script object in client scripts of your Silverlight application.
However, more is needed to call the object’s methods, properties and events from outside of your Silverlight application. First, you can use only public members of your Silverlight class in a script. Furthermore, you must specify which members of the class will be accessible in scripts. For this purpose, HTML Bridge provides two special attributes — System.Windows.Browser.ScriptableTypeAttribute and System.Windows.Browser.ScriptableMemberAttribute. You can mark the UnitTestDriver class with the ScriptableTypeAttribute attribute:
// C#
using namespace System.Windows.Browser;
namespace NameExtractor
{
[ScriptableType] //Provides scriptable access to the entire class
public class UnitTestDriver
{
…
}
}
In this case, all public members of UnitTestDriver will be accessible from scripts. If you do not want to provide scriptable access to all public members of your class, you can mark only the needed members with the ScriptableMemberAttribute attribute. We will use this approach in our sample application to provide scriptable access to the Test1 and Test2 methods of the UnitTestDriver class:
// C#
using namespace System.Windows.Browser;
namespace NameExtractor
{
public class UnitTestDriver
{
…
//tests
[ScriptableMember] //Provides scriptable access to Test1
public void Test1()
{
…
}
[ScriptableMember] //Provides scriptable access to Test2
public void Test2()
{
…
}
}
}
It should be noted that the ScriptableMemberAttribute attribute only makes sense for public class members.
Calling Silverlight Code from TestComplete Unit Tests
Since we have provided scriptable access to the Test1 and Test2 methods of the UnitTestDriver class, we can call them from scripts of a web page holding our Silverlight application, and above all — from TestComplete scripts, too. This allows you to perform unit testing of our NameExtractor Silverlight-based application with TestComplete. Let’s take a look at how you can perform this testing.
Build the application and open the resulting web page holding your Silverlight sample application in a web browser. Now, you need to find a web object that corresponds to our Silverlight application in the Object Browser’s Object Tree in order to communicate with the application from TestComplete. For this purpose, you can use the Object Properties window of TestComplete. Select Object Properties from the Object Browser’s context menu in TestComplete to display the window. Using the Finder tool (the
glyph at the bottom of the window), select the needed object in the web browser’s window as it is illustrated on the image below:

Figure 1 – Selecting the web object that corresponds to the Silverlight application
Then, in the FullName property of the selected object, you can see the Object Tree path to the object. This property is displayed in the Object Properties window after you selected the object with the Finder tool:

Figure 2 – Exploring the path to the object via the Object Properties window
In our case, the Object Tree path to the web object is the following:
// JScript
Sys.Process("IEXPLORE", 2).Page("file:///C:/MyProjects/NameExtractor/Bin/Debug/TestPage.html").Form("form1").Panel("silverlightControlHost").Object(0)
Note that the path may differ in your own Silverlight applications.
Let’s create a helper script routine that will return an object corresponding to our Silverlight application in a TestComplete script:
// JScript
function GetSlObject()
{
return Sys.Process("IEXPLORE", 2).Page("file:///C:/MyProjects/NameExtractor/Bin/Debug/TestPage.html").Form("form1").Panel("silverlightControlHost").Object(0);
}
The object returned by this routine contains the Content property that provides access to the registered scriptable objects of the tested Silverlight application. Using the Content.unitTestDriver code snippet, we can get access to the unitTestDriver scriptable object which we have registered earlier with the HtmlPage.RegisterScriptableObject method (see the Preparing Silverlight Code for Unit Testing section above in this article) and then use this object for unit testing of the application. In your TestComplete script, you can write the following code to obtain the unitTestDriver object:
// JScript
var slObject = GetSlObject();
var unitTestDriver = slObject.Content.unitTestDriver;
Note that the name of the property which we get from the Content object is unitTestDriver, not UnitTestDriver. That is, we use the name passed through the first parameter of the HtmlPage.RegisterScriptableObject method when we called this method to register the UnitTestDriver class as the unitTestDriver scriptable object.
Now, since we have retrieved the object needed for performing the unit testing of our NameExtractor application, we can call the object’s testing methods — Test1 and Test2 (we have marked these methods as scriptable members of the UnitTestDriver class). For instance, we can launch unit tests from a TestComplete script in the following way:
// JScript
function Main()
{
var slObject = GetSlObject();
var unitTestDriver = slObject.Content.unitTestDriver;
Test1(unitTestDriver);
Test2(unitTestDriver);
}
function Test1(unitTestDriver)
{
try
{
unitTestDriver.Test1();
Log.Message("Test1 passed.");
}
catch(ex)
{
Log.Error("Test1 failed.", ex.description);
}
}
function Test2(unitTestDriver)
{
try
{
unitTestDriver.Test2();
Log.Message("Test2 passed.");
}
catch(ex)
{
Log.Error("Test2 failed.", ex.description);
}
}
The Main function in the script above obtains the unitTestDriver scriptable object corresponding to the tested Silverlight application and then calls the Test1 and Test2 helper script functions, one-by-one. Each function gets the unitTestDriver object passed through the function’s parameter and calls the appropriate method of the object to perform unit testing. The calls to the Test1 and Test2 methods of the unitTestDriver object are enclosed in the try … catch statements in order to handle possible errors that may occur during the test execution. So, if the test execution fails due to any errors in the test or in the code being tested, TestComplete posts an appropriate message to the test log:

Figure 3 – Error message in the test log
Then, you can view the test log and make decisions on how the tested Silverlight code works and whether it needs any changes and improvements.
In our example, we have created unit tests right in the Silverlight application and then launched them from a TestComplete script to automate the tests. Note that with the described HTML Bridge technology you can make not only specific testing routines in your Silverlight application scriptable, but you can also provide scripting access to the entire class and to all its members in the same way as described above. In this case, you can create your automated unit tests right in TestComplete, not in the tested Silverlight application.
Conclusion
In this article we have explained how you can get access to internal code of your Silverlight applications from scripts. We have given an overview of the HTML Bridge technology that makes objects and their members in Silverlight applications accessible to TestComplete's test engine. We hope this information will help you test and improve your Silverlight applications with Unit Testing and TestComplete. If you haven’t used the latest version of TestComplete yet, download and try it for free.