NGTweet - Part 2: Authenticate user with Twitter service using OAuth Authentication

 

Background

In the previous post I started with the process of using TweetSharp to connect to Twitter. We saw how to query the tweets from the public timeline. As a Twitter client, we would also want to fetch the tweets from the people whom we are following. Also we need the ability to tweet ourselves and send direct messages or replies to others tweets as well. For all these functionalities to work we need to login to Twitter using the username and password. In this post I’ll demonstrate how to authenticate the user with Twitter service using OAuth authentication mechanism.

Register Twitter App

If you want to access the Twitter API programmatically, you need to register your application with the Twitter. This is done at http://dev.twitter.com. Its a simple process which takes less than 5 minutes. Once you have registered the app, you get two keys which are called Consumer Key and Consumer Secret. These are encrypted values which are used to uniquely identify your application. 

Authenticate user with Twitter service

In order to authenticate a user with Twitter, using Silverlight and TweetSharp API, there are multiple options available.

  • Basic Authentication

We can use basic authentication which passes the user credentials in clear text. This is definitely not the recommended approach.

  • OAuth Authentication

The second option is to use OAuth Authentication. OAuth is an open protocol to allow secure API authorization in a simple and standard method from desktop and web applications. Since Silverlight is a desktop client we can use OAuth for our needs. You can find out more about OAuth from Wikipedia.

When you register the app, you are granted OAuth access based on the options chosen during the registration process.

  • XAuth Authentication

XAuth is another open standard for authenticating user service across web. If we are building mobile clients we can use XAuth authentication. You can find more about XAuth in this article called introducing XAuth.

XAuth is not enabled by default for the newly registered app. If you intent to authenticate users using XAuth, you need to write to Twitter explaining the reasons why you need to authenticate users using XAuth. Only upon validating the details your application will be granted privileges to use XAuth authentication mechanism.

As you would have guessed from the title of the post, I’ll demonstrate how to use OAuth authentication. I have already registered a Twitter app called NGTweet and received the Consumer Key and Consumer Secret keys.

Note : Because these are secure keys and can be used in programmatically accessing Twitter API, I’ll not be sharing them with anyone. If you intend to use the code demonstrated in this series of posts you’ll have to obtain your own keys from twitter.

Build UI to authenticate users using OAuth

The way OAuth works is like a 6 step process.

  1. Create an instance of the TweetSharp’s Twitter service using the Consumer Key and the Consume Secret keys.
  2. Get the OAuthRequestToken based on the Consumer key and secret.
  3. Get the Authorization URI using the request token. This is used to redirect the user to Twitter Sign In page. User is asked to authorize the application “NGTweet” to access to Twitter profile and related details.
  4. Once the user allows the application the access to profile a random number which is called the PIN number is generated and displayed on the screen. This number needs to be inputted into the application which requested for the access.
  5. Using the request token from the 2nd step and the PIN number, an OAuthAccessToken is generated.
  6. Finally the Twitter service is accessed with the OAuthAccessToken

As said above I have the Consumer Key and Consumer Secret with me. At start up I’ll have to ensure that the Silverlight application has the OAuthAccessToken to start interacting with the twitter API. First time when the Silverlight client starts there won’t be any token available with us. So lets start by creating the token. As we did in the previous demo, all the calls to the Twitter API which are routed through TweetSharp will have to be made through our WCF service layer.

The step of authorizing the application to access the Twitter needs to be done only once. Twitter will allow the application access to its resources on subsequent visits provided the same details are supplied in the request. For this purpose, once the user is authenticated, I’ll store the access token locally and attach it to the service request. This will fail only when the user revokes the access to the application.

So lets get started. We’ll start with the UI changes from the previous demo. We haven’t authenticated the user so far. So when the user tries to login, he’ll have to perform the above mentioned steps of entering the PIN number. Lets add a textbox where the user can add the PIN once he authorizes NGTweet to access Twitter.

        <StackPanel Name="verifierPanel">
            <TextBlock Text="Enter the PIN number " />
            <TextBox Name="txtVerifier" />
            <Button Content="Verify"
                   Click="Button_Click" />
        </StackPanel
>

This will need to be shown only if the user has not been authenticated. Once the user authenticates we’ll not go through these steps. So lets look at the mechanism of checking if the user has already granted permission for the application to access Twitter. If so we’ll store the access token for the user in the Silverlight application’s local cache. Silverlight is like a sandbox and cannot access resources on the user local file system. As a result we cannot store the access token directly.


To help the developers use local storage, Silverlight offers a facility called IsolatedStorage. You can read more about IsolatedStorage on MSDN. Its one of the simplest way of storing limited amount of user specific data. I’ll make use of this to store the users access token.



        private const string _accesstoken = "accessToken";


 


        private readonly IsolatedStorageSettings userSettings;


 



        public MainPage()


        {


            InitializeComponent();


 


            userSettings = IsolatedStorageSettings.ApplicationSettings;


 


            Loaded += MainPage_Loaded;


        }


 


 



        private void MainPage_Loaded(object sender, RoutedEventArgs e)


        {


            NGTweetAuthenticationServiceClient authenticationClient = new NGTweetAuthenticationServiceClient();


 


            if (IsValidUser())


            {


                GetTweetsForUser(authenticationClient);


            }


            else


            {


                GetRequestToken(authenticationClient);


            }


        }


In the above code snippet, we have declared a variable of type IsolatedStorage.ApplicationSetting called userSettings. In the Loaded event we check if the user is valid. If so we get the tweets for the user. Otherwise we proceed to get the request token. Lets look at the GetRequestToken first. For the purpose of handling authentication, I have added a NGTweetAuthenticationService to our previous solution. The service contract looks as follows




    [ServiceContract]


    public interface INGTweetAuthenticationService


    {


        [OperationContract]


        LoginResponse Login(LoginRequest request);


 


        [OperationContract]


        GetRequestTokenResponse GetRequestToken();


 


        [OperationContract]


        GetDataResponse GetTweets(OAuthAccessToken access);


    }



We’ll look at the detail implementation of these methods later. For the moment we are interested in the GetRequestToken method. It does not take any input but returns an GetRequestTokenResponse instance. This is inline with the Request-Response Pattern that I had mentioned in the previous example. Lets examine the structure of the response object to see what will be sent as part of the response



    [DataContract]


    public class GetRequestTokenResponse


    {


        [DataMember]


        public OAuthRequestToken RequestToken { get; set; }


 


        [DataMember]


        public Uri AuthorizationUri { get; set; }


    }


This will return us a OAuthRequestToken and the AuthorizationURI. The OAuthRequestToken is a unique token issued by Twitter to each application based on the applications Consumer Key and Consumer Secret. The AuthorizationUri is the Uri to where the user should be redirected. In our case this Uri is used to redirect the user from NGTweet application to the Twitter page which is used to authorize NGTweet to access user details.Its a kind of handshaking mechanism which uses the identity of the application (NGTweet) and that of the Twitter user to allow access to resources using the API.


Once the user is redirected to the Twitter page, he’ll need to login to Twitter and authorize the NGTweet application to access the details. If the user decides to allow access, he’ll be given a PIN which will need to be handed over to the application which requested the access (NGTweet). You’ll be greeted with a screen similar to the screenshot shown below


image


The user will be presented with the same details that you provided at the time of registering your app. You can enter the valid Twitter credentials and click on Authorize App button. The generated PIN will be displayed in the screen. This PIN will need to be passed onto NGTweet.


image


image


Click on the verify button and you’ll be able to get the OAuthAccessToken based on the RequestToken and the PIN number. So lets look at what we did after receiving the request token.



        private void GetRequestToken(NGTweetAuthenticationServiceClient authenticationClient)


        {


            authenticationClient.GetRequestTokenCompleted += authenticationClient_GetRequestTokenCompleted;


            authenticationClient.GetRequestTokenAsync();


        }


The method registers the callback delegate and calls the method GetRequestToken asynchronously.



        void authenticationClient_GetRequestTokenCompleted(object sender, GetRequestTokenCompletedEventArgs e)


        {


            GetRequestTokenResponse getRequestTokenResponse = e.Result;


 


            userSettings["requestToken"] = getRequestTokenResponse.RequestToken;


 


            string javaScript = string.Format("window.open('{0}', '_blank', '', '')", getRequestTokenResponse.AuthorizationUri);


            HtmlPage.Window.Eval(javaScript);


        }


We get the response object and pull out the RequestToken and AuthorizationUri. We store the RequestToken in the user settings for further processing. Becuase of the limitations of Silverlight we cannot directly start a new process and navigate to the Uri. In order to navigate to a different web page it needs to be user initiated by means of clicking a link or a hyperlink button. But in our case we need to programmatically redirect the user to the AuthhorizationUri. We build a JavaScript string and using the HtmlPage.Window.Eval function open a new window which takes the user to Twitter authentication page.


Now lets look at what happens when the user enters the PIN into the NGTweet application.



        private void Button_Click(object sender, RoutedEventArgs e)


        {


            NGTweetAuthenticationServiceClient authenticationClient = new NGTweetAuthenticationServiceClient();


 


            authenticationClient.LoginCompleted += authenticationClient_LoginCompleted;


 


            authenticationClient.LoginAsync(


                new LoginRequest { RequestToken = (OAuthRequestToken)userSettings["requestToken"], Pin = txtVerifier.Text });


        }


 


        void authenticationClient_LoginCompleted(object sender, LoginCompletedEventArgs e)


        {


            LoginResponse loginResponse = e.Result;


 


            userSettings[_accesstoken] = loginResponse.OAuthAccessToken;


        }


We use the PIN entered by the user and using the RequestToken for the NGTweet application make a request to the authentication service’s Login method. Once again this is done asynchronously. And in the callback we retrieve the OAuthAccessToken returned by the service cache it in the user settings. We can close the application now and restart it. We’ll not be asked to enter PIN anymore. We’ll be straight away presented with the tweets from our account as shown below.


image


With almost all things done on the client side, lets look at the service implementation.


 


NGTweet Authentication Service


 



public class NGTweetAuthenticationService : INGTweetAuthenticationService


    {


        private readonly TwitterService _service;


 


        public NGTweetAuthenticationService()


        {


            _service = _service = new TwitterService("YourAppConsumerKeyHere", "YourAppConsumeSecretHere");


        }


 


        public LoginResponse Login(LoginRequest request)


        {


            OAuthAccessToken access = _service.GetAccessToken(request.RequestToken, request.Pin);


 


            _service.AuthenticateWith(access.Token, access.TokenSecret);


 


            return new LoginResponse { OAuthAccessToken = access };


        }


 


        public GetDataResponse GetTweets(OAuthAccessToken access)


        {


            _service.AuthenticateWith(access.Token, access.TokenSecret);


 


            IEnumerable<TwitterStatus> mentions = _service.ListTweetsOnHomeTimeline();


 


            TweeterStatusAdapter adapter = new TweeterStatusAdapter();


 


            return new GetDataResponse { TweeterStatuses = adapter.Convert(mentions) };


        }


 


        public GetRequestTokenResponse GetRequestToken()


        {


            OAuthRequestToken requestToken = _service.GetRequestToken();


 


            Uri uri = _service.GetAuthorizationUri(requestToken);


 


            return new GetRequestTokenResponse { RequestToken = requestToken, AuthorizationUri = uri };


        }


    }


This is a very simple implementation which does the job of transforming the objects between the TweetSharp API and our domain model. Only thing to note there is I haven’t put the actual keys for the consumer key and consumer secret while creating the service.



            _service = _service = new TwitterService("YourAppConsumerKeyHere", "YourAppConsumeSecretHere");


If you want to make use of this code, ensure that you replace these with the appropriate values.


Conclusion















In this post I demonstrated how to use the OAuth authentication mechanism to authorise NGTweet application to get access to Twitter API. The process seems bit tedious. But its inline with the OAuth standards. I built upon the previous demo to integrate authentication into the NGTweet application. In the future posts I’ll demonstrate other features like sending a tweet, retweet someone else’s tweet, set a tweet as favourite tweet, send direct message to users etc which are basic features for any Twitter client application.


As always I have uploaded the complete working solution to dropbox. I have removed the unnecessary files from the TweetSharp dependencies folder to reduce the size of the zip file. If you use NuGet package manager to add TweetSharp reference you’ll find lot more files in your packages folder.


Until next time Happy Programming Smile

spacer

NGTweet : Silverlight client for Twitter

 

Background

Initially when I started with Silverlight learning series, I had mentioned that I’ll create a sample app similar to TweetDeck. In this post I intend to start with a very simple application which attempts to ultimately wind up similar to TweetDeck. I start off with connecting to Twitter using a Silverlight 4 application. I’ll probably add Facebook to it as well later, once Twitter client is stable. This is the first post which shows how to connect to Twitter using a managed C# API called TweetSharp.

 

TweetSharp API

We can develop client applications for Twitter using the Twitter API. Twitter offers different mechanisms to connect using OAuth, xAuth etc. In this post I’ll be consuming the public feed of Twitter and as such will not use any for of Authentication. In the later post I’ll be using the dedicated user to connect to Twitter and we’ll see how to use different Authentication methods.

Instead of building everything from scratch I decided to use an open source API for C# which is called TweetSharp. You can find out more about the TweetSharp here. There is a NuGet package available as well using which you can add the dll to your project. So I made use of it to add reference to the required dll and its dependencies to the project. Lets see how can we make use of this API to connect to Twitter.

 

Connect to Twitter using TweetSharp

I created a new Silverlight 4 application and named it NGTweet. You can say its an acronym for Next Generation Tweet or Nilesh Gule’s Tweets Smile. From this Silverlight application we’ll have to make calls to the Twitter API using TweetSharp. But since Silverlight is a client side technology, we cannot directly make call to Twitter from the Silverlight application.

So I added a WCF service to the solution which will be the mediator between the Silverlight application and Twitter. I named the service project as TweetSharpService. For the time being we’ll have just a single method in the service to fetch the public timeline from Twitter.

    [ServiceContract]

    public interface ITweetSharpService

    {

        [OperationContract]

        GetDataResponse GetTweetsOnPublicTimeline();

    }

I like to encapsulate the request and response of the service using the Request-Response Pattern. Since this method is not taking any input parameter I have avoided creating the request object. But there is a GetDataResponse object which will contain the response from the service method. Lets look at the structure of the response object in little bit more detail.

    [DataContract]

    public class GetDataResponse

    {

        [DataMember]

        public IEnumerable<NGTweeterStatus> TweeterStatuses { get; set; }

    }

There is only one property called TwitterStatuses which is a collection of NGTweeterStatus. I’ll explain in a short while the need for this NGTweeterStatus class. Lets look at the details of NGTweeterStatus.

    [DataContract]

    public class NGTweeterStatus

    {

        [DataMember]

        public string ScreenName { get; set; }

 

        [DataMember]

        public string Tweet { get; set; }

    }

As of now there are only two members for this class, ScreenName and Tweet. Both the members are marked with the DataMember attribute and the class as a whole is marked with the DataContract attribute.

After these basic classes are in place lets look at the service implementation.

    public class NgTweetSharpService : ITweetSharpService

    {

        public GetDataResponse GetTweetsOnPublicTimeline()

        {

            TwitterService service = new TwitterService();

            IEnumerable<TwitterStatus> tweets = service.ListTweetsOnPublicTimeline();

 

            TweeterStatusAdapter adapter = new TweeterStatusAdapter();

 

            return new GetDataResponse { TweeterStatuses = adapter.Convert(tweets) };

        }

    }

As we can see this is the place where the TwitterService is coming into the picture. This is the place from where we instantiate the TweetSharp API’s TwitterService class. We get the list of tweets on the public time line. There is a minor problem here. Some of the properties of TwitterStatus class defined within the TweetSharp API are only getters or only setters. Because we are using WCF service, the objects are serialized. And for the objects to be serialized we need to have the properties as read write properties. Hence I created the wrapper called NGTweeterStatus.

Finally, there is an adapter also coming into the picture called TweeterStatusAdapter. This is a two way adapter which will convert the TweeterStatus from TweetSharp API to NGTweeterStatus and vice versa. At the moment I have implemented only the method which converts TwitterStatus to NGTweeterStatus. Here is an implementation of the adapter.

    public class TweeterStatusAdapter

    {

        public IEnumerable<NGTweeterStatus> Convert(IEnumerable<TwitterStatus> tweets)

        {

            return tweets.Select(twitterStatuse => new NGTweeterStatus { ScreenName = twitterStatuse.User.ScreenName, Tweet = twitterStatuse.Text }).ToList();

        }

    }

Its a very simple implementation of the Adapter pattern which adapts the properties of one object to another. People who are well versed  with Domain Driven Design can make use of the Mapper pattern. In future we can also look the possibility of using AutoMapper. For time being in the context of this demo whatever we have would suffice.

 

Add clientaccess.xml and crossdomain.xml files

If we want to make calls to services outside the domain of the server where the Silverlight application is hosted, we need to add the crossdomain.xml file to the root of the project. And also the clientaccess.xml file. You can read more about these two files on MSDN. At this point you can build the service project and browse the service. You should get the page similar to the one shown below

image

 

Add Service reference to Silverlight project

Once the service is up and running we can add the service reference to the Silverlight application and make call to the service method. I added the reference with name NGTweetSharpService. In the MainPage I am going to use a ListBox to display the ScreenName and Tweet from the public timeline. I modified the ListBox control’s item template and data template to display the data in two TextBlock controls as shown below

    <StackPanel ScrollViewer.VerticalScrollBarVisibility="Auto" Height="500">
        <ListBox Name="lstTweets" Width="400">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Border Background="BlanchedAlmond"  Margin="3" HorizontalAlignment="Stretch">
                        <StackPanel>
                            <TextBlock Text="{Binding ScreenName, Mode=TwoWay}"/>
                            <TextBlock Text="{Binding Tweet, Mode=TwoWay}"/>
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel
>

And the last thing to do is to call the service and set ItemsSource of the listbox as the collection returned from the service.



        public MainPage()


        {


            InitializeComponent();


 


            Loaded += MainPage_Loaded;


        }


 


        private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)


        {


            TweetSharpServiceClient client = new TweetSharpServiceClient();


 


            client.GetTweetsOnPublicTimelineCompleted += client_GetTweetsOnPublicTimelineCompleted;


 


            client.GetTweetsOnPublicTimelineAsync();


        }


 


        private void client_GetTweetsOnPublicTimelineCompleted(object sender, GetTweetsOnPublicTimelineCompletedEventArgs e)


        {


            GetDataResponse response = e.Result;


 


            lstTweets.ItemsSource = response.TweeterStatuses;


        }


The code above is self explanatory. We create a client to the service and call the async method by setting the callback. In the callback we assign the value returned from the service call to the ItemsSource property of the listbox control. If everything goes fine, you should see a screen similar to the one shown below.


image


 


Conclusion


As demonstrated in this example, it is very easy to use the TweetSharp API to connect to Twitter using a Silverlight client application. In the future posts we’ll see how to refine this application. We used a very simple in this post to connect to the public time line of Twitter. As the series goes on we’ll see how to filter tweets based on authenticated user. I hope this was a good starting point.


Note: I have uploaded all the contents of the TweetSharp and its dependent dlls. This has increased the size of the uploaded code by huge margin. Will try to upload only the required files next time.


As usual the source code is available for download at Dropbox.


Until next time Happy Programming Smile

spacer

Silverlight : Unit Test ViewModel

Background

In the previous post I demonstrated how to integrate the MVVMLight toolkit into a Silverlight project. As I said in earlier posts that view models help us in separating the concerns. We can test the view model irrespective of the view. In this post I am going to demonstrate how to unit test the view model. I am going to reuse the example from the previous post and refactor it wherever required.

Silverlight unit testing framework

There are some constraints while working with Unit Tests and Silverlight framework. Visual Studio has built in support for unit testing.By default the Visual Studio test runner uses the framework libraries from the full blown version of .Net. Since Silverlight is a scaled down version of .Net framework we cannot use all the types from the .Net framework. Because of this reason Microsoft came up with the additional unit testing framework and a project template specifically for Silverlight. You can read about it here.

Limitations of Silverlight unit testing framework

When we are doing Test Driven Development (TDD), its important that we know how much code is covered as part of running the unit tests. This helps us to identify the untested pieces of code and is generally referred to as Code Coverage. The normal Visual Studio unit test framework has very good code coverage feature. But its not supported currently in the Silverlight unit testing framework. Due to this reason we cannot gauge the code coverage and it can lead to untested code being pushed to production environment which can result into bugs.

Steps to overcome the limitations of Silverlight Unit Testing Framework

  • Extract view model into a separate assembly

We can tweak the solution and its project structure a bit to get the Visual Studio code coverage working for us. First thing we need to do is to separate the view models into its own assembly. Here again there is a limitation that Silverlight cannot reference assemblies of all types. So we need to create a project of type Silverlight class library. It is in fact one of the best practice to separate view models into their own assembly. This can be helpful in avoiding view specific code like MessageBoxes and Navigation related code slipping into view model unknowingly.

So lets refactor our example for the previous demo. Open the solution and add a new project of type Silverlight class library and name it ViewModels. Move the MainViewModel.cs and IDialogService.cs files to this new project. If you try to build the solution now, you’ll have few build errors. Add the reference to MVVMLight dll to the ViewModels project. Also the Silverlight getting started reference needs to be updated with the ViewModels dll.

Once the references are updated, we need to modify the MainViewModel a little bit. In the current situation the default constructor is passing in a concrete instance of DialogService. Earlier this used to work because all the classes and interface were in the same namespace. Now that the namespaces have changed, we need a way of removing this dependency. We’ll remove the default constructor and keep only the one which takes IDialogService as a parameter. We cannot continue with the default constructor supplying the instance of DialogService as it creates a circular reference between the view and the view model.

That is precisely the reason I have left the implementation of DialogService and the ViewModelLocator within the view layer itself. By doing this we can share the view model between lets say a Silverlight and a Windows Phone 7 applications. Only the view specific things will need to be implemented in the view layer.

Since we removed the default constructor from the view model, there should be some way of passing the DialogService to it. We modify the ViewModelLocator because that is currently acting like a repository of the view models. Since ViewModelLocator and the DialogService are in the same namespace we can create an instance of DialogService and pass it to the MainViewModel at the time of construction as

            _main = new MainViewModel(new DialogService());

After making these changes the solution should build properly. In case it doesn’t there must be some problem with the references.




  • Create Unit Test project


Add a Test project to the solution and name it as ViewModel.UnitTest. Make sure that it is of type Test and not Silverlight Unit Test.


image


Add a new class called MainViewModelTest.cs which we’ll use to unit test the MainViewModel. We’ll mock the DialogService and for that we can use any of the commonly available mocking frameworks. I chose to use RhinoMocks. Like we added the MVVMLight toolkit using the NuGet package manager, we add the RhinoMocks dll as well.


image


Lets write our first unit test. To keep things simple, I am going to test the MainViewModel’s constructor. If the MainViewModel instance was created successfully, I can ensure that the default properties are set correctly and also the delegate command is created.

        private MainViewModel _mainViewModel;         private IDialogService mockDialogService;         [TestInitialize]         public void Setup()         {             mockDialogService = MockRepository.GenerateStub<IDialogService>();             _mainViewModel = new MainViewModel(mockDialogService);         }         [TestMethod]         public void ConstructorTest()         {             Assert.IsNotNull(_mainViewModel);             Assert.IsNotNull(_mainViewModel.SearchCommand);             Assert.IsTrue(string.IsNullOrEmpty(_mainViewModel.SearchText));             Assert.IsFalse(_mainViewModel.HasText);         }



  • Update reference assemblies


You can build the solution now. I got a build error because of the version of the assembly which is referenced by default for the Test project. We need to make sure that the System.dll, System.Core.dll and System.Windows.dll are referenced from the Silverlight SDK folder and not from the .Net framework folder.


image


From the references delete the System.dll, System.Core.dll and System.Windows.dll (if present). Add these dll from the Silverlight folder which is located at “C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0” on my machine.


image


Once the dll’s are added change the properties of these dll to copy them as local.


image


Now if we build the solution, it should build without any build errors. We can run the constructor test and verify that is passes. Once we have the running test, the last thing is to enable the code coverage for the ViewModel project. To enable code coverage, edit the local test run settings


image


In the test setting dialog, select Data and Diagonostics options and enable the covergae as shown below


image


We are almost there. Once the coverage is enabled, we can decide which all dll’s should be considered for the calculation of the code coverage. This is done using the Configure option when the Coverage is enabled. Enable coverage only for ViewModels.dll


image


Thats it. We have enabled coverage for the viewmodels project. Running the test now will tell how what percentage of the code has been covered. Lets run the test and see the results.


image


We can see that overall 51% of the code has been covered as part of running the constructor test. From the result we can see that the Setter for HasText and SearchText has not been covered so far. Lets add a test to set the SearchText and see how does it impact the coverage.

        [TestMethod]         public void MainViewModel_WhenSearchTextIsSet_ReturnHasTextAsTrueTest()         {             _mainViewModel.SearchText = "Silverlight";             Assert.IsFalse(string.IsNullOrEmpty(_mainViewModel.SearchText));             Assert.IsTrue(_mainViewModel.HasText);         }

Lets run all the tests again and see the code coverage.


image


With the addition of our new test we can see that the coverage now is 72%. I’ll leave it to the readers to write tests for the remaining uncovered pieces of code as an exercise Smile


Conclusion


In this post we saw that with little bit of tweaks here and there it is possible to use the Visual Studio Code Coverage with Silverlight application to unit test the view models for Silverlight. I hope that the Silverlight unit testing framework will soon enable this feature as it is very important and helpful in writing quality code using unit tests. There is nothing wrong in using the Silverlight Unit Testing framework. It works seamlessly with Visual Studio. One problem I have seen is that the unit tests written using Silverlight Unit Testing framework cannot be run as part of continuous integration process. They need to be run manually.


Compared to that the approach I have demonstrated here can be used to automate the tests as part of continuous build. Personally I feel that’s the biggest advantage using this approach. Hope this helps.


As always I have uploaded the working solution to dropbox. Until next time Happy Programming Smile

spacer