Category Archives: Microsoft .NET

Painless File Backups to Azure Storage

Windows Azure

In my previous post I discussed steps and utilities for backing up Azure SQL Databases in order to guard against data loss due to user- or program-error. Since then I’ve started investigating options for backing up files – specifically those in Azure Virtual Machines – to the same Azure Storage service used previously.

Just like before I was delighted to find an existing app that makes this super easy. The AzCopy utility makes it possible to copy files to and from Azure Storage and local storage, or from Azure Storage to Azure Storage, with a nice set of arguments.

For instance, the following command will copy all of the files in a local folder, recursively, over to Azure Storage. It will overwrite existing files, and it will skip any files that already exist unless the source file is newer. Perfect.

AzCopy.exe C:\Here\Be\Important\Things http://yourstoragename.blob.core.windows.net/yourstoragecontainer /destKey:YourSuperLongAzureStorageKey /S /V /Y /XO

The Azure storage account name and access key can be accessed in the Storage section of the portal, by clicking the Manage Access Keys button at the bottom of the Windows Azure Portal.

Azure Storage Information

This command took under a minute to backup 3,000 files to Azure Storage from an Azure Virtual Machine. From there I can keep running the command and it will only copy new files over to Azure Storage, overwriting any existing file.

As in my previous post, my little utility AzureStorageCleanup is a nice companion to this process. I have updated the source on Github to include a -recursive argument, which will remove files within the virtual hierarchy found in blob storage (created by the recursive option in AzCopy).

AzureStorageCleanup.exe -storagename yourstoragename -storagekey YourSuperLongAzureStorageKey -container yourstoragecontainer -mindaysold 60 -recursive

By scheduling AzureStorageCleanup to run with the -recursive option, you can remove old files to keep storage use in-check.

Painless Azure SQL Database Backups

Windows Azure

While the SQL Database service from Windows Azure provides resiliency and redundancy, there is no built in backup feature to guard against data loss due to user- or program-error. The advised way to handle this is to take a three-step approach:

  1. Make a copy of the SQL Database
  2. Backup the database copy to Azure Storage
  3. Maintain & remove any outdated backups on blob storage

The process in Windows Azure that backs up a SQL Database to blob storage is not transactionally consistent, which is why the initial database copy is required.

Richard Astbury has provided an excellent tool, SQLDatabaseBackup, that takes care of the first two steps with little fuss:

SQLDatabaseBackup.exe -datacenter eastus -server hghtd75jf9 -database MyDatabase -user DbUser -pwd DbPassword -storagename mybackups -storagekey YourSuperLongAzureStorageKey -cleanup

The data center and server name can be obtained from the SQL Databases section of the Windows Azure Portal.

SQL Database Information

The Azure storage account name and access key can be accessed in the Storage section of the portal, by clicking the Manage Access Keys button at the bottom of the portal.

Azure Storage Information

Finally, by specifying the -cleanup argument, the utility will delete the SQL Database copy it creates after the backup is successfully created.

And while the pricing for Azure blob storage is very affordable, you may want to automate the process of deleting old backups. I’ve created a very simple utility that does just that. AzureStorageCleanup uses command line arguments that mirror the SQLDatabaseBackup project (as it is meant to compliment its use):

AzureStorageCleanup.exe -storagename mybackups -storagekey YourSuperLongAzureStoragekey -container sqlbackup -mindaysold 60

The above command will remove files equal-to-or-older-than sixty days from the container “sqlbackup” – the default container used by SQLDatabaseBackup. The details of each file deleted are printed to the console.

By scheduling these two utilities on an available machine you’ll have painless, affordable backups for any of your Windows Azure SQL Databases.

Integration Testing ASP.NET MVC Projects with SpecsFor.Mvc

SpecsFor.Mvc

I’ve recently spent some time looking into different frameworks for doing integration testing for ASP.NET MVC projects. One that caught my eye almost immediately was SpecsFor.Mvc. Unlike other solutions I found for writing integration tests, SpecsFor.Mvc lets you write tests in a fashion that is very similar to writing unit tests, using strongly-typed access to your application’s data without having to script or dig into the DOM.

Some nice things that SpecsFor.Mvc provides out-of-the-box:

  • Hosts your ASP.NET MVC project, building a specified configuration of your project and then hosting it automatically under an instance of IIS Express
  • Provides strongly-typed methods for navigating to controllers and actions, checking route results, and filling out and submitting forms
  • Provides access to validation data, including access to the validation summary as well as the validity of each property in your view’s model

SpecsFor.Mvc uses Selenium WebDriver internally in order to drive the browser. You can still access the Selenium IWebDriver interface any time you need to dig further into your page.

Let’s take a look at these things in practice by writing a few hypothetical tests written against the stock ASP.NET MVC Internet Application.

Starting the Project

To get started, create a new ASP.NET MVC 4 project in Visual Studio.

New ASP.NET MVC 4 Web Application

Select the Internet Application project template, check the option to create a unit test project and click OK.

Internet Application Project Template

Once both the ASP.NET MVC project and the unit test project have been created, right-click the References folder under your Tests project and click Manage Nuget Packages.

Manage Nuget packages

Under Online, search for and install the official SpecsFor.Mvc Nuget package.

SpecsFor.Mvc Nuget Package

Initializing the Hosting Environment

The next thing that we need to add to the Tests project is some code that will initialize the IIS Express hosting environment using the classes provided by SpecsFor.Mvc. To do this, create a new class called MvcAppConfig with the following contents (adjust the namespace as needed):

using Microsoft.VisualStudio.TestTools.UnitTesting;
using SpecsFor.Mvc;

namespace SpecsForMvcDemo2.IntegrationTests
{
    [TestClass]
    class MvcAppConfig
    {
        private static SpecsForIntegrationHost integrationHost;

        [AssemblyInitialize()]
        public static void MyAssemblyInitialize(TestContext testContext)
        {
            var config = new SpecsForMvcConfig();

            config.UseIISExpress()
                .With(Project.Named("SpecsForMvcDemo"))
                .ApplyWebConfigTransformForConfig("Debug");

            config.BuildRoutesUsing(r => RouteConfig.RegisterRoutes(r));

            config.UseBrowser(BrowserDriver.Chrome);

            integrationHost = new SpecsForIntegrationHost(config);
            integrationHost.Start();
        }

        [AssemblyCleanup()]
        public static void MyAssemblyCleanup()
        {
            integrationHost.Shutdown();
        }
    }
}

The class is marked as a TestClass even though there are no explicit methods to test. This is so that the MyAssemblyInitialize() and MyAssemblyCleanup() methods run. In order for the AssemblyInitialize and AssemblyCleanup attributes to work the class must be marked with the TestClass attribute. With this code in place, MyAssemblyInitialize() will run once before all of the test methods in the project and MyAssemblyCleanup() will run after they all complete.

The code found in MyAssemblyInitialize() is fairly straight-forward given the clarity of the SpecsFor.Mvc API. A new SpecsForMvcConfig instance is created and set to use IIS Express with a given project name and configuration name. Next, a call to BuildRoutesUsing is made in order to register the various controllers and actions with SpecsFor.Mvc. Finally, the browser is specified and the configuration is used to start a new instance of the SpecsForIntegrationHost.

The MyAssemblyCleanup() method, paired with the AssemblyCleanup attribute, is used to shut down the integration host after all the tests have completed.

Initializing the Browser

Now that we have code in place to host the ASP.NET MVC site before any tests are run, we need some code in place to create an instance of our MVC application in a browser. Right-click the Tests project and add a new Unit Test.

Add Unit Test

Add the following code to the top of your new UnitTest1 class, before the TestMethod1 declaration:

private static MvcWebApp app;

[ClassInitialize]
public static void MyClassInitialize(TestContext testContext)
{
    //arrange
    app = new MvcWebApp();
}

This will require adding a using statement for SpecsFor.Mvc.

Using SpecsFor.Mvc

This new method, MyClassInitialize() will run before all of the tests in the new UnitTest1 class. It will create a new instance of the MvcWebApp class which will launch the browser with your application loaded.

If you go ahead and run the tests for UnitTest1 now you’ll see that two console windows are opened, one for IIS Express hosting the ASP.NET application and one for the Selenium WebDriver that is driving your application. In addition, after the Selenium WebDriver console window is opened, the browser specified in the MvcAppConfig class will be launched.

Note that you may get a prompt from Windows Firewall that you’ll need to allow.

Firewall Alert

Because we haven’t actually written any tests yet, all these windows will close after they are opened, but this demonstrates that these few lines of code used to bootstrap the environment are working.

Authentication Tests

Now that all the setup work is done, let’s see what some actual integration tests look like using SpecsFor.Mvc. The first test will ensure that, if a user tries to navigate to the /account/manage route of the ASP.NET MVC application without logging in, they will be redirected to the login screen.

[TestMethod]
public void AccountManage_WithoutSession_RedirectsToLogin()
{
    //act
    AccountController.ManageMessageId? messageId = null;
    app.NavigateTo<AccountController>(c => c.Manage(messageId));

    //assert
    const string returnUrl = "%2fAccount%2fManage";
    app.Route.ShouldMapTo<AccountController>(c => c.Login(returnUrl));
}

This test will require adding two new items to the using statements: YourProjectName.Controllers and MvcContrib.TestHelper (MvcContrib.TestHelper is needed for the call to ShouldMapTo).

And that’s it for the first integration test. I love it. It’s clear, concise, and (aside from the return URL path) it’s strongly typed. The call to NavigateTo will navigate to the URL corresponding to the AccountController and the Manage action, specified in the lambda expression. The call to ShouldMapTo will ensure that the resulting route corresponds to the AccountController and Login action (with the proper ReturnUrl parameter).

Let’s add two more tests to illustrate a few more examples using SpecsFor.Mvc:

[TestMethod]
public void Login_InvalidInput_TriggersValidation()
{
    //act
    app.NavigateTo<AccountController>(c => c.Login(string.Empty));
    app.FindFormFor<LoginModel>()
        .Field(f => f.UserName).SetValueTo(string.Empty)
        .Field(f => f.Password).SetValueTo(string.Empty)
        .Submit();

    //assert
    app.FindFormFor<LoginModel>()
        .Field(f => f.UserName).ShouldBeInvalid();
    app.FindFormFor<LoginModel>()
        .Field(f => f.Password).ShouldBeInvalid();
}

[TestMethod]
public void Login_InvalidCredentials_TriggersValidation()
{
    //act
    app.NavigateTo<AccountController>(c => c.Login(string.Empty));
    app.FindFormFor<LoginModel>()
        .Field(f => f.UserName).SetValueTo(Guid.NewGuid().ToString())
        .Field(f => f.Password).SetValueTo(Guid.NewGuid().ToString())
        .Submit();

    //assert
    app.ValidationSummary.Text.AssertStringContains("incorrect");
}

These tests will require adding a using statement for YourProjectName.Models so that the LoginModel class can be accessed.

Again, looking at the code, I love the simplicity and clarity in the SpecsFor.Mvc tests. I can use NavigateTo to navigate to my controller and action, and then use FindFormFor to access my view’s model. Finally I can submit the form with easy access to the resulting validation data.

Unfortunately, if you try to run these new tests right now they will fail. The reason is that the SpecsFor.Mvc initialization code compiles and deploys a fresh copy of the ASP.NET MVC project to a TestSite folder within the Debug folder. The App_Data folder contents are not included in the ASP.NET MVC Visual Studio project. So, the database files are not deployed to the TestSite folder and the site itself will YSOD if you try to do anything requiring the database.

No DB YSOD

To fix this, right-click the App_Data folder in your main MVC project and click Add>Existing Item.

Add Existing Item

Then, add the two files found in your physical App_Data folder to the project (you’ll need to run the MVC site and access the database once manually).

After adding the MDF and LDF files to the project you should be able to run all of the authentication integration tests without error.

The Big But

Pee-Wee Big But

Now this all sounds great, but

At the time I’m writing this, SpecsFor.Mvc tests run great under third-party test runners such as TestDriven.Net and CodeRush. However, the tests don’t run under Visual Studio’s MSTest runner. Trying to run the tests using Visual Studio’s built in test runner will result in a “Build failed” error. The author of SpecsFor.Mvc has reproduced the issue and is hoping to have it fixed within a couple of days.

UPDATE: This issue has since been resolved by Matt and is no longer a problem in version 2.4.0. No more buts!

Resources

Using Bootstrap with the DevExpress ASP.NET Data Grid

DX + Bootstrap
I’ve been having a lot of fun lately (and been quite productive) using Bootstrap as a way to lay my sites out before giving them a final visual style. The past three websites I’ve done have used Bootstrap and I love the CSS classes it provides and the speed with which I can develop a nice, consistent, responsive site with it.

In my most recent project I’ve been working on integrating some of the MVC Extensions from DevExpress with good success. However, one quirk had me scratching my head. My customer was generally very happy with the ASP.NET Data Grid but wanted a few additional features, one being the ability for the user to specify the page size for the grid. Easy enough – I thought – it’s just a setting after all.

However, this is what I saw after enabling the setting:

Page Size Item Before

After some poking around using the Developer Tools in Chrome, I was able to identify the CSS in Bootstrap that was interfering with the rendering of the ASP.NET Data Grid. Here is the CSS I used to fix the issue:

/* for playing happy with DX */
td.dxpDropDownButton img {
    max-width: none;
}

td.dxpComboBox input {
    margin-bottom: 0px;
    padding: 0px 0px;
}

With that bit of CSS in place the control now renders properly:

Page Size Item After

Note that there’s also a post available from DevExpress here on fixes for common CSS issues with Bootstrap. However, using that method requires overwriting your bootstrap.css file.

Running KnockoutJS Unit Tests with Chutzpah

In my previous blog post I discussed some of the specifics involved with unit testing JavaScript code that uses KnockoutJS and Web API. This blog posts builds on the example discussed in the previous post. If you missed that post you can read more about it here.

While unit testing our ViewModel was all working great, the real icing on the cake is getting JavaScript unit testing working without a browser, integrated into Visual Studio. And it would be even better if the test runs and results could be integrated into the Visual Studio Test Explorer. That’s where two separate Visual Studio extensions come in to play: the Chutzpah JavaScript Test Runner and the Chutzpah Test Adapter for Visual Studio. Both can be installed directly from the Extensions and Updates window in Visual Studio.

Chutzpah Extensions

The first extension allows you to right-click on your tests.js file and click a new “Run JS Tests” menu item to run your QUnit tests without launching a browser.

Run JS Tests

In order to for this to work, though, you must tell Chutzpah where to find the other JS files that your tests require (as it will not be launching your tests.html in a browser). To do this, add the following lines to the top of our tests.js file:

/// <reference path="../Scripts/jquery-1.9.1.js" />
/// 
/// <reference path="../Scripts/knockout-2.2.1.debug.js" />
/// 
/// <reference path="../Scripts/app/namespace.js" />
/// <reference path="webapiclient.stub.js" />
/// 
/// <reference path="../Scripts/app/model.js" />
/// <reference path="../Scripts/app/viewmodel.js" />

This is the same format used by the _references.js file that Visual Studio uses for JavaScript IntelliSense. With these lines in place, you can now right-click the tests.js file and click Run JS Tests, seeing the results right within Visual Studio:

Test Results in Visual Studio

Even cooler, with the Test Adapter installed, you can click CTRL+R, A to run all of the unit tests in your solution, and your QUnit tests will be run too, with their results displayed within the Visual Studio testing UI:

Test Results in Test Explorer

There is one catch I’ve found when using Chutzpah as a JavaScript test runner for KnockoutJS projects: if you right-click your tests.js file and click “Run JS Tests in browser”, Chutzpah will automatically generate an HTML file for the JS file and display that in a browser.

Run JS Tests in browser

However, the default template for the HTML used by Chutzpah puts the JavaScript references in the HTML head instead of at the bottom of the body. Without any changes, using the “Run JS Tests in browser” feature from Chutzpah, along with KnockoutJS, will result in an error running tests:

Test Results Wrong Order

To fix this you need to find and edit the HTML template used by Chutzpah. Search your C: drive for the text “Chutzpah” – under Windows Vista and up this should be located in a subfolder of C:\Users\UserName\AppData\Local\Microsoft\VisualStudio. For instance, the path on my system is:

C:\Users\Nathanial\AppData\Local\Microsoft\VisualStudio\11.0\Extensions\30spjmvi.u3x

Once you have found the folder, open the TestFiles\QUnit\qunit.html file:

<!DOCTYPE html>
<html>
<head>
    @@TestFrameworkDependencies@@
    @@ReferencedCSSFiles@@
    @@ReferencedJSFiles@@
    @@TestJSFile@@
</head>

<body>
    <h1 id="qunit-header">Unit Tests</h1>
    <h2 id="qunit-banner"></h2>
    <h2 id="qunit-userAgent"></h2>
    <ol id="qunit-tests"></ol>
    <div id="qunit-fixture"></div>
</body>
</html>

Move the lines referencing the JS files to the bottom of the body, leaving the CSS reference in the head tag:

<!DOCTYPE html>
<html>
<head>
    @@ReferencedCSSFiles@@
</head>

<body>
    <h1 id="qunit-header">Unit Tests</h1>
    <h2 id="qunit-banner"></h2>
    <h2 id="qunit-userAgent"></h2>
    <ol id="qunit-tests"></ol>
    <div id="qunit-fixture"></div>
    @@TestFrameworkDependencies@@
    @@ReferencedJSFiles@@
    @@TestJSFile@@
</body>
</html>

Save your changes and that’s it! You can now delete the tests.html file from the project if you’d like and use Chutzpah to run tests both within the Visual Studio IDE and within the browser.

Run JS Tests in browser - Fixed

Unit Testing KnockoutJS and Web API

After a couple of years of looking on from the side-lines at the advancements being made world of web development, I decided recently it was time to dive in head-first and bring my web knowledge up to speed. A lot of my initial work with C# and .NET was with ASP.NET WebForms, but in the past few years the majority of my work has been either mobile, desktop, or server-based.

So, for the past couple of months I’ve been investigating a variety of topics from top-to-bottom, including HTML5 and CSS3, Bootstrap, ASP.NET MVC, Entity Framework (including Repository, Unit of Work, and Service patterns), Dependency Injection, JavaScript (including the Module and Revealing Module patterns) and jQuery, KnockoutJS, and finally QUnit.

One topic I thought I’d blog about is how to unit test client-side JavaScript code, specifically ViewModels used by KnockoutJS that communicate with a Web API endpoint. To help illustrate these techniques I’ve created an ultra-simple ASP.NET MVC application that uses both Web API and KnockoutJS. Shockingly, it’s a to-do application. You can check out the source code for the application here. You can also download a snapshot of the project, before adding unit testing, here.

Here is the main view for the MVC application:

<input data-bind="value: addingItemText, valueUpdate: 'afterkeydown'" type="text" />
<button data-bind="enable: canAddItem, click: addNewItem">Add</button>

<ol data-bind="foreach: items">
    <li>
        <strong data-bind="visible: Completed">Completed </strong>
        <span data-bind="text: Text"></span>
        <button data-bind="click: $root.deleteSelectedItem">Delete</button>
        <button data-bind="click: $root.completeSelectedItem, visible: !Completed()">Complete</button>
        <button data-bind="click: $root.undoSelectedItem, visible: Completed()">Undo</button>
    </li>
</ol>

@section scripts {
    @Scripts.Render("~/bundles/app")
}

I define a text input and button for adding a new to-do item. The Add button should only be enabled when there is text entered. Following that there is a list of to-do items. If an item has been completed it shows appropriate text in bold. There’s a button to delete an item. Finally, if the item is uncompleted there is a button to complete it, and if the item is completed there is a button to undo it.

Here is a look at the ViewModel:

$((function (ns, webApiClient) {
    "use strict";

    ns.todoViewModel = (function () {

        //utilities
        function cloneJSModel(sourceModel, destinationModel) {
            destinationModel.Id(sourceModel.Id)
                .Text(sourceModel.Text)
                .Completed(sourceModel.Completed);
        }

        function cloneKOModel(sourceModel, destinationModel) {
            var jsModel = ko.toJS(sourceModel);
            cloneJSModel(jsModel, destinationModel);
        }

        //UI binding
        var items = ko.observableArray();
        
        //web api calls
        function populate() {

            webApiClient.ajaxGet("TodoItem", "", function (json) {
                items.removeAll();

                $.each(json, function (index, value) { //ignore jslint
                    var item = new ns.todoItemModel();
                    cloneJSModel(value, item);
                    items.push(item);
                });
            });
        }

        function addItem(todoItem) {

            webApiClient.ajaxPost("TodoItem", ko.toJS(todoItem), function (result) {
                var newItem = new ns.todoItemModel();
                cloneJSModel(result, newItem);
                items.push(newItem);
            });
        }

        function deleteItem(id) {

            webApiClient.ajaxDelete("TodoItem", id, function (result) {
                items.remove(function (item) {
                    return item.Id() === result.Id;
                });
            });
        }

        function updateItem(todoItem) {

            webApiClient.ajaxPut("TodoItem", todoItem.Id(), ko.toJS(todoItem), function () {
                var existingItem = ko.utils.arrayFirst(items(), function (item) {
                    return item.Id() === todoItem.Id();
                });
                cloneKOModel(todoItem, existingItem);
            });
        }

        //UI actions
        var addingItemText = ko.observable('');

        var canAddItem = ko.computed(function () {
            return addingItemText() !== "";
        });

        var addNewItem = function () {
            var newItem = new ns.todoItemModel();
            newItem.Text(addingItemText());
            addItem(newItem);
            addingItemText("");
        };

        var deleteSelectedItem = function () {
            deleteItem(this.Id());
        };

        var completeSelectedItem = function () {
            this.Completed(true);
            updateItem(this);
        };

        var undoSelectedItem = function () {
            this.Completed(false);
            updateItem(this);
        };

        //return a new object with the above items
        //bound as defaults for its properties
        return {
            items: items,
            populate: populate,
            addingItemText: addingItemText,
            canAddItem: canAddItem,
            addNewItem: addNewItem,
            deleteSelectedItem: deleteSelectedItem,
            completeSelectedItem: completeSelectedItem,
            undoSelectedItem: undoSelectedItem
        };

    }());

    ns.todoViewModel.populate();

    ko.applyBindings(ns.todoViewModel);

    //pass in namespace prefix (from namespace.js)
}(todo, todo.webApiClient)));

Again this is all pretty standard. It follows the Revealing Module pattern for the ViewModel. One thing to note is that a webApiClient is passed in and used for the AJAX calls. John Papa shows something very similar in his Pluralsight training courses. This nicely abstracts out the Web API specifics plus, as you’ll see, it makes it easier to unit tests our ViewModel.

Here’s the Web API client source:

(function (ns) {
    "use strict";

    ns.webApiClient = (function () {

        var ajaxGet = function (method, input, callback, query) {

            var url = "/api/" + method;
            if (query) {
                url = url + "?" + query;
            }

            $.ajax({
                url: url,
                type: "GET",
                data: input,

                success: function (result) {
                    callback(result);
                }
            });
        };

        var ajaxPost = function (method, input, callback) {

            $.ajax({
                url: "/api/" + method + "/",
                type: "POST",
                data: input,

                success: function (result) {
                    callback(result);
                }
            });
        };

        var ajaxPut = function (method, id, input, callback) {

            $.ajax({
                url: "/api/" + method + "/" + id,
                type: "PUT",
                data: input,

                success: function (result) {
                    callback(result);
                }
            });
        };

        var ajaxDelete = function (method, id, callback) {

            $.ajax({
                url: "/api/" + method + "/" + id,
                type: "DELETE",

                success: function (result) {
                    callback(result);
                }
            });
        };

        return {
            ajaxGet: ajaxGet,
            ajaxPut: ajaxPut,
            ajaxPost: ajaxPost,
            ajaxDelete: ajaxDelete
        };
    }());

    //pass in namespace prefix (from namespace.js)
}(todo));

As you can see we’re simply wrapping access to the jQuery ajax function and calling our callback function. Again you can download the source code above or from Bitbucket and run the app to try all this out. It all works as expected: you can add, delete, complete, and undo items.

In this example I’ll be using QUnit to unit test the JavaScript. JavaScript unit tests, unlike standard unit tests, generally exist in the same project as your site. You’ll see that sites like KnockoutJS and Sugarjs have a webpages where you can run their tests. The tests need access to your JavaScript source files, and there is no easy way to make these available to other projects like you can .NET assemblies.

So we’ll start by creating a new Tests folder in the project.

Add New Folder

Inside that folder create both a test.html and a tests.js file. The next step is to put the QUnit specific markup in the tests.html file:

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta charset="utf-8">
        <!-- QUnit stylesheet from the jQuery CDN -->
        <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.11.0.css">
    </head>
    <body>
        <!-- elements that QUnit will inject test results into -->
        <div id="qunit"></div>
        <div id="qunit-fixture"></div>

        <!-- required JS libraries, such as jQuery and KnockoutJS -->
        <script src="/Scripts/jquery-1.9.1.js"></script>
        <script src="/Scripts/knockout-2.2.1.debug.js"></script>

        <!-- QUnit itself from the jQuery CDN -->
        <script src="http://code.jquery.com/qunit/qunit-1.11.0.js"></script>

        <!-- include tests themselves -->
        <script src="tests.js"></script>
    </body>
</html>

Note that I’ve also included references to the jQuery and Knockout js files. Next, add the following code to the tests.js file in order to ensure things are working:

test("hello test", function () {
    ok(1 == "1", "Passed!");
});

Now, if you right-click on the tests.html file and click View in Browser, you should see passing results for the single test.

Hello Test Run

Now lets implement actual unit tests for our ViewModel. One of the cardinal rules of unit tests is that they should not interact with the “outside world”, specifically things like databases, file systems, and web services. Tests that do this, even using a unit testing framework, are known as integration tests. So, one thing we need resolve is how to test our ViewModel without making the Web API calls.

We’ll do this by creating a stub for our Web API client object. With typical C# applications you can do stubbing, mocking, and faking in a variety of ways. I personally like using FakeItEasy. However, the dynamic nature of JavaScript means that, at least for something simple like stubbing our Web API client, there’s really no additional framework needed.

Let’s start the stubbing by creating a new JavaScript file called webapiclient.stub.js in the Tests folder. Now add the following code to define the stub:

(function (ns) {
    //better exceptions, less tomfoolery allowed
    "use strict";

    ns.webApiClient = (function () {

        var testResult = [];

        var ajaxGet = function (method, input, callback, query) { //ignore jslint
            callback(this.testResult);
        };

        var ajaxPost = function (method, input, callback) { //ignore jslint
            callback(this.testResult);
        };

        var ajaxPut = function (method, id, input, callback) { //ignore jslint
            callback(this.testResult);
        };

        var ajaxDelete = function (method, id, callback) { //ignore jslint
            callback(this.testResult);
        };

        //return a new object with the above items
        //bound as defaults for its properties
        return {
            ajaxGet: ajaxGet,
            ajaxPut: ajaxPut,
            ajaxPost: ajaxPost,
            ajaxDelete: ajaxDelete,
            testResult: testResult
        };
    }());

    //pass in namespace prefix (from namespace.js)
}(todo));

This code is pretty straight forward. It uses the same signatures as the real Web API client object. However, instead of making real AJAX calls, it calls the callback immediately, passing back the value stored in testResult.

One important thing to note is that the function calls to the callbacks pass this.testResult rather than just testResult. This is because the return block is returning a new object with the specified properties and default values for those properties. Those properties are not getters or setters for the privately scoped variables above, although it may look that way if you are used to OOP languages like C# or Delphi.

Next lets look at how to make use of this stub to write tests against the ViewModel. We’ll add the following script references to the tests.html file:

<!-- include the application's namespace.js -->
<script src="/Scripts/app/namespace.js"></script>

<!-- include our sub Web API client -->
<script src="webapiclient.stub.js"></script>

<!-- include the items to test -->
<script src="/Scripts/app/model.js"></script>
<script src="/Scripts/app/viewmodel.js"></script>

The first reference is to our Web API client stub and the second two are to our application’s Model and ViewModel respectively. Now lets add our first real test to the tests.js file:

module("todo.viewmodel.populate");

test("todo.viewmodel.populate (0 length)", function () {
    "use strict";

    //arrange
    todo.webApiClient.testResult = [];

    //act
    todo.todoViewModel.populate();

    //assert
    equal(todo.todoViewModel.items().length, 0, "Passed!");
});

The first line defines a module. This is not required at all and is merely a way to group tests visually into sections when results are displayed. Next we setup the todo.webApiClient (our stub) to return an empty array for any calls to it. Then, we call the populate() function on our ViewModel. Finally, we assert that the items() in our ViewModel is zero-length. You can save the tests.js and tests.html file and refresh your browser to view the results:

First Real Test Run

Here are some more example tests for the to-do ViewModel:


test("todo.viewmodel.populate (1 length)", function () {
    "use strict";

    //arrange
    todo.webApiClient.testResult = [
        {
            Id: 1,
            Text: "To-do",
            Completed: false
        }
    ];

    //act
    todo.todoViewModel.populate();

    //assert
    equal(todo.todoViewModel.items().length, 1, "Passed!");
});

module("todo.viewmodel.canAddNewItem");

test("todo.viewmodel.canAddNewItem (without text)", function () {
    "use strict";

    //arrange

    //act
    todo.todoViewModel.addingItemText('');

    //assert
    equal(todo.todoViewModel.canAddItem(), false, "Passed!");
});

test("todo.viewmodel.canAddNewItem (with text)", function () {
    "use strict";

    //arrange

    //act
    todo.todoViewModel.addingItemText('To-do');

    //assert
    equal(todo.todoViewModel.canAddItem(), true, "Passed!");
});

module("todo.viewmodel.addNewItem");

test("todo.viewmodel.addNewItem", function () {
    "use strict";

    //arrange
    todo.webApiClient.testResult = [];
    todo.todoViewModel.populate();

    var expectedItem = {
        Id: 1,
        Text: "To-do",
        Completed: false
    }

    todo.webApiClient.testResult = expectedItem;

    //act
    todo.todoViewModel.addingItemText(expectedItem.Text);
    todo.todoViewModel.addNewItem();

    //assert
    var firstItem = todo.todoViewModel.items()[0];
    equal(firstItem.Id(), expectedItem.Id, "Passed!");
});

Along with results for the full suite of tests:

All Tests Run

Hopefully this proves helpful to other developers taking a look at writing more client-side JavaScript and looking for ways to test it. Look forward to more posts in the coming months on other topics and techniques I’ve discovered relating to these evolving web technologies.

Remote Debugging WinForms Desktop Apps on Windows RT

Once you have your Windows RT device jailbroken and running your WinForms applications it would be very handy to be able to remotely debug those apps running on Windows RT, similar to what can be done when developing Windows Store apps.

The first step is to share the project folder. Right-click the project in the Solution Explorer in Visual Studio and click “Open Folder in File Explorer”. Then use the context menu in Explorer to share the folder with a common Windows user. The basic sharing wizard worked fine in my testing.

Sharing Wizard

Next we need to setup debugging for the project. Unlike a Windows Store application the remote debugger options aren’t available from the Start debugging button in VS2012. Each project type in Visual Studio seems to surface its remote debugging options in a slightly different way.

Right-click the project in Solution Explorer and click Properties. On the Debug tab, select “Start external program” and enter the path to your exe using the UNC (network) path. Then, check “Use remote machine” and enter either the computer name or IP of your Windows RT device.

Debug Settings

Switch to the Windows RT device and start the Remote Debugger from the Start screen. If you do not have the Remote Debugger for Windows RT installed you can download the Remote Tools for Visual Studio 2012 on your Windows RT device here, under Additional software. Make sure you select the ARM download.

With the Remote Debugger running on your Windows RT device, you should now be able to click Play in VS2012. The application will launch on your Windows RT device, and you can set breakpoints and debug as you normally would.

Windows RT Debugging

Throw in the Remote Desktop app in Windows RT along with the split screen feature and you’ll be debugging from your couch in no time!

RDP Debugging