Build and unit test Windows Azure projects from TFS Team Build
One of the great things about Windows Azure is that you can leverage a lot of your existing skills to write cloud-based applications. Want to run ASP.NET applications? No problem. Want to do WCF? Works fine. Windows Azure let's you write and run highly scalable and highly available applications. But what good is a highly scalable Web application if the Web site scales like crazy but the database is super slow? The answer is 'no good at all' and that's why we have the options of Windows Azure Storage and SQL Azure. For this article, we'll focus on Windows Azure Storage.
Windows Azure Storage a fast, scalable, and reliable storage solution for your Windows Azure applications. With the Windows Azure SDK, you get a version of Azure's cloud server and cloud storage that run on your desktop – DevFabric.exe and DevelopmentStorage.exe, respectively.
Now, just because you're running your applications in the cloud, there's no excuse for not unit testing your application. Arguably, since Windows Azure doesn't allow you to debug your application running on their cloud servers, you almost need unit tests in your development environment even more to make sure that you're catching your errors before you deploy out to the cloud.
Now let's say that your company is using Team Foundation Server and Team Build to do Continuous Integration (CI) builds. You definitely want to build your Windows Azure project and unit test it from your CI build, right? The hitch is that Azure's DevFabric.exe and DevelopmentStorage.exe only run in what is known as "interactive mode" which means that they require a graphical user interface to run. Well, the TFS Team Build service runs as a Windows Service and that means that there's no user interface.
That pretty much wraps it up for Windows Azure and Team Build then, huh? Nope. While the default installation of Team Build runs as a Windows Service, it is actually possible to run Team Build in interactive mode. (Hooray!)
Here's the basic overview of what needs to happen to build and unit test a Windows Azure application from Team Build:
- Configure an interactive-mode TFS Server.
- Log in to your build server.
- Start TFSBuildService.exe
- Create a Team Build that compiles your Windows Azure project and runs your unit tests.
- Customize the Team Build BeforeTest "Target" to start DevelopmentStorage.exe.
- Run the build.
Since setting up an interactive-mode Team Build server has already been well documented on Grant Holliday's blog (http://ozgrant.com/2008/02/28/running-an-interactive-team-build-2008-agent/) and on the Microsoft site (http://msdn.microsoft.com/en-us/library/bb399142.aspx), I'm going to focus on steps 4, 5, and 6. I'm also going to assume that you already have a solution that uses Windows Azure Storage from unit tests and that you already know the basics of creating a new TFS Team Build.
Starting from step 4, you need to create a TFS Build to compile your application. Once you've done this, you need to customize the build script. To do this, open Team Explorer, locate your build, right-click the build, and choose View Configuration Folder.
Figure 1. To start editing your build script, right-click the build and choose View Configuration Folder
You should now be in Source Control Explorer and you should see the two files that define for Team Build – TFSBuild.proj and TFSBuild.rsp. Double-click TFSBuild.proj to start editing the build script.
Figure 2. The build definition files. Double-click TFSBuild.proj to edit the build script.
Figure 3. The Team Build script.
In order to make our unit tests run against Windows Azure Storage, we need to make sure that Development Storage is running and that the tables it will be using have been initialized before the unit tests start executing. To do this, we'll hook in to the BeforeTest MSBuild target. A target in MSBuild is roughly the same as method in C#. It defines a series of tasks that should happen when the target is executed. Team Build gives us a handful of targets that we can hook in to various events in the build process. Not surprisingly, the BeforeTest target runs after the code has been compiled and just before the unit tests are executed.
Figure 4. An empty BeforeTest MSBuild target
Windows Azure Storage is essentially just a handful of REST service endpoints. In production, these REST endpoints are the front end of a massive number of servers that are ready to store your data. In development, Development Storage (DevelopmentStorage.exe) exposes the same REST service endpoints but uses SQL Express as its backend.
When you're running in development, you first have to execute a utility called DevTableGen to initialize SQL Express with the tables required to run your application. When you call DevTableGen, you'll send it the database name you want to use and a list of DLLs in your application. It will look for any property of type System.Linq.IQueryable that sits inside of any class that extends from System.Data.Services.Client.DataServiceContext and for each matching property that DevTableGen finds, it creates a table that can be used by Development Storage. Once the initialization is done, you then call DevelopmentStorage.exe and then your Development Storage REST endpoints are running.
Figure 5. Use an MSBuild ItemGroup to get the list of all the DLLs
To get the list of DLLs, we'll use an MSBuild ItemGroup inside of the BeforeTest target. ItemGroups as similar to array variables and are particularly good at storing arrays of file names. In figure 5, we declare an item group named TableAssemblies that "includes" any file ending in *.dll in the compilation output directory.
Figure 6. Properties required to run DevTableGen.exe and DevelopmentStorage.exe
Next we'll need to set up the configuration values that are required to run DevTableGen.exe and DevelopmentStorage.exe. We'll do this with an MSBuild PropertyGroup and MSBuild Properties. Properties MSBuild's equivalent of variables. In figure 6, we set up the connection info for the database we want to use and the path to the Azure SDK binaries.
Now that we have all our configuration values set up, we need to start the EXE's. For this, we'll use the MSBuild Exec task. Exec essentially issues a command line call from our MSBuild script and waits until the program exits before moving on to the next task.
Figure 7. The Exec task to run DevTableGen.exe
Figure 7 shows you the Exec call for DevTableGen. Please note that the value for the Command attribute has been formatted for readability and should actually be all on a single line.
Figure 8. The Exec task for starting DevelopmentStorage.exe
And finally, now that everything is initialized, we make the call to start DevelopmentStorage.exe as seen in Figure 8. Since the Exec task waits for the command it calls to exit and since we need DevelopmentStorage to keep running while we run our unit tests, we need to do a workaround so that the build doesn't hang on this Exec statement. To do this, we specify IgnoreExitCode='true' and Timeout='10000'. IgnoreExitCode tells the Exec task that we don't care what the return code was from whatever it just called and Timeout says to wait 10 seconds before moving on to the next line in the build script. This 10 second delay is helpful because it gives Development Storage a chance to initialize before the unit tests start running.
So, once you have made all these changes to your TFSBuild.proj build script, check it in to TFS source control, make sure that TFSBuildService.exe is running in interactive mode, and kick off a build. If you watch the screen on the build server, after a few seconds you'll see Development Storage start up as your unit tests start to execute (Figure 9).
Figure 9. Development Storage is starting.
You've successfully made Windows Azure storage start as part of your build and your Azure unit tests can run.