Designing and Developing Cross-Cutting Features
Every developer has had to integrate with another system, API or component. Tis article provides strategies to handle the change and for he separating system boundaries.
The content has been bookmarked!
There was an error bookmarking this content! Please retry.

Posted by Jamie Phillips on Oct 06, 2010
This is the third and final part of the late Jamie Phillip’s exploration into the world of coding kata’s and Behavior Driven Design. Part one introduced coding katas, part two combined them with behavior driven design.
I had started down the path of enlightenment through Katas and BDD and I was beginning to feel all warm and fuzzy, until I realized that if this was the way that I wanted to write my Unit Tests and do my development in the future, it was going to be pretty painful pulling around Eric Lee’s ContextSpecification each and every time. It would be a lot easier if I could just select a BDD Unit Test Project and have all I needed for the project already available after the project was created. After a bit of searching I found various references to the new features of the Project Template Export Wizard and that seemed the most logical solution for me.
In order to be able to work through this example you will need to download and install the Export Template Wizard from the Visual Studio Gallery (do a search on the Gallery site for Export Template Wizard). This is a free Visual Studio Extension from Microsoft that permits the export of an existing Code Project as a Project Template.
Before we dive in to creating our first template, it is important to take a look at some existing templates to get an idea of what we may need.
When you install Visual Studio the templates are located in:
For example, the following directory contains the Visual Studio project templates for English:
In addition, when you install a template (typically through double-clicking a .vsix file – Microsoft Visual Studio Extension file) it will get placed in the following folder:
Template Tip:Using Regedit and browsing to the following key, you will see all of the installed extensions for Visual Studio 2010:
HKCU\Software\Microsoft\VisualStudio\10.0\ExtensionManager\EnabledExtensions
The entries seen here are updated automatically by Visual Studio when it starts. So removing one of the Extensions (i.e. deleting the folder specific to the extension) will be reflected in the registry the next time that Visual Studio is started.
For any given template you will see that the content is stored in a ZIP file, which helps to “keep everything together” organizationally. When you inspect the content of one of these ZIP files, you will notice that, at a minimum, they contain a .vstemplate file; which can be thought of as the manifest of the template.
For our purposes, we are interested in the content of the BasicUnitTest Template found at:
C:\Program Files\Microsoft Visual Studio 10.0\Common7
Taking a look at an existing template from the VS 2010 installation, we notice that there are specific key words that are used within the code files (AssemblyInfo.cs, etc). In the following code sample, the highlighted text illustrates the various template parameter keywords:
using System;
using System.Text;
using System.Collections.Generic;
$if$ ($targetframeworkversion$ == 3.5)using System.Linq;$endif$
$if$ ($targetframeworkversion$ == 4.0)using System.Linq;$endif$
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace $rootnamespace$
{
[TestClass]
public class $safeitemname$
{
[TestMethod]
public void TestMethod1()
{
}
}
}
The keywords $rootnamespace$ and $safeitemname$ are reserved template parameters along with $safeprojectname$:
|
Parameter |
Description |
|
$rootnamespace$ |
The root namespace of the current project. This parameter is used to replace the namespace only in an item being added to a project. |
|
$safeprojectname$ |
The name provided by the user in the New Project dialog box, with all unsafe characters and spaces removed. |
|
$safeitemname$ |
The name provided by the user in the Add New Item dialog box, with all unsafe characters and spaces removed. |
Inspecting the associated .vstemplate file we can see that the reference to the code file is in the ProjectItem element and has the ReplaceParameters attribute set to true:
<TemplateContent> ... <ProjectItem ReplaceParameters="true">UnitTest.cs</ProjectItem> </TemplateContent>
This will instruct the Template Wizard to effectively search and replace all of the parameters in the file specified; which in the example above would be UnitTest.cs. Custom Parameters can also be used by simply adding a CustomParameters element to the .vstemplate file:
<TemplateContent> ... <CustomParameters> <CustomParameter Name="$TemplateParameter1$" Value="SomeValue"/> <CustomParameter Name="$TemplateParameter2$" Value="SomeOtherValue"/> </CustomParameters> </TemplateContent>
With this knowledge in mind we will start to put the pieces together to create our BDD Unit Test Template.


Template Tip:
It is important to note that you will need to have the same assemblies installed on each machine that the template is to be deployed to; therefore you should restrict the references to what is available as part of the .NET framework of your choice or what is in the GAC. This may mean that as part of your template you will have to create an installer that installs specific assemblies in the GAC – or make it a requirement that the intended user installs the necessary assemblies themselves.
using System;
using System.Text;
using System.Collections.Generic;
$if$ ($targetframeworkversion$ == 3.5)using System.Linq;$endif$$if$ ($targetframeworkversion$ == 4.0)
using System.Linq;$endif$
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace $safeprojectname$
{
...
}
using System;
using System.Text;
using System.Collections.Generic;
$if$ ($targetframeworkversion$ == 3.5)using System.Linq;$endif$$if$ ($targetframeworkversion$ == 4.0)
using System.Linq;
$endif$
using Microsoft.VisualStudio.TestTools;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace $safeprojectname$
{
public class $safeitemname$Context : ContextSpecification
{
/// <summary>
/// The "Given some initial context" method
/// </summary>
protected override void Context()
{
// setup your class under test
}
}
...
}
/// <summary>
/// Summary description for $safeitemname$
/// </summary>
[TestClass]
public class $safeitemname$ : $safeitemname$Context
{
/// <summary>
/// The "When an event occurs" method
/// </summary>
protected override void BecauseOf()
{
//
// TODO: Add behavior setup (Action) here
//
}
/// <summary>
/// The "then ensure some outcome" method.
/// </summary>
[TestMethod]
public void TestMethod1()
{
//
// TODO: Add test logic here
//
}
}
using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("$projectname$")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("$registeredorganization$")] [assembly: AssemblyProduct("$projectname$")] [assembly: AssemblyCopyright("Copyright © $registeredorganization$ $year$")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("$guid1$")] // Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]



Template Tip:
If the two fields “Icon Image” and “Preview Image” are not filled in, the Wizard will auto-generate images for you; which may not be to your liking (it looks like a snapshot of a code window – up close and small). It is advisable to create your own images and reference those in the two fields.
In the example we are working through I prepared my own images to the following dimensions (these are the same dimensions as the wizard generated images):

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace BDDUnitTest1
{
public class unittest1Context : ContextSpecification
{
...
}
/// <summary>
/// Summary description for unittest1
/// </summary>
[TestClass]
public class unittest1 : unittest1Context
{
...
}
}


<?xml version="1.0"?>
<VSTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"Type="Project" Version="3.0.0" xmlns="http://sc hemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>BDD Unit Test</Name>
<Description>A Test project based on Behavior Driven Development (BDD) principles</Description>
<Icon>__Template_small.png</Icon>
<PreviewImage>__Template_large.png</PreviewImage>
<ProjectType>CSharp</ProjectType>
<ProjectSubType />
<SortOrder>1000</SortOrder>
<DefaultName>BDDUnitTest</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
<EnableLocationBrowseButton>true</EnableLocationBrowseButton>
<LocationField>Enabled</LocationField>
</TemplateData>
<TemplateContent>
<Project File="BddUnitTest.csproj" TargetFileName="BddUnitTest.csproj" ReplaceParameters="true">
<ProjectItem
TargetFileName="contextspecification.cs"
ReplaceParameters="true">contextspecification.cs</ProjectItem>
<ProjectItem
TargetFileName="assemblyinfo.cs"
ReplaceParameters="true">properties\assemblyinfo.cs</ProjectItem>
<ProjectItem
TargetFileName="unittest1.cs"
ReplaceParameters="true">unittest1.cs</ProjectItem>
</Project>
<CustomParameters />
</TemplateContent> </VSTemplate>
<?xml version="1.0"?>
<VSTemplate xmlns:xsi="http://www.w3.org/2001/XMLSchema- instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Type="Project" Version="3.0.0" xmlns="http://sc hemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
...
</TemplateData>
<TemplateContent>
<Project File="BddUnitTest.csproj" TargetFileName="BddUnitTest.csproj" ReplaceParameters="true">
<ProjectItem
TargetFileName="ContextSpecification.cs"
ReplaceParameters="true">contextspecification.cs</ProjectItem>
<ProjectItem
TargetFileName="AssemblyInfo.cs"
ReplaceParameters="true">properties\assemblyinfo.cs</ProjectItem>
<ProjectItem
TargetFileName="UnitTest1.cs"
ReplaceParameters="true">unittest1.cs</ProjectItem>
</Project>
<CustomParameters />
</TemplateContent>
</VSTemplate>

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace BDDUnitTest1
{
public class UnitTest1Context : ContextSpecification
{
...
}
/// <summary>
/// Summary description for UnitTest1
/// </summary>
[TestClass]
public class UnitTest1 : UnitTest1Context
{
...
}
}
Although there was a certain amount of manual intervention at the end to perform clean-up, it helped expose how easy it is to update existing .vsix files and change a template. With the new template available for use, creating BDD Unit Tests will be easier as there is no worry about referencing the correct assemblies or including the appropriate code files; all you have to concentrate on is writing the actual tests themselves.
The journey from coding Kata to BDD and then Project Template has shown us an assortment of practical exercises that we can use to improve on various levels; through Katas we improve our coding techniques; through BDD we improve the way that we approach our designs and write our Unit Tests; through Project Templates we can improve the process of creating code projects.
T4 Templates offer an easy way to generate classes and other files in VS.NET. You do not need to compile or install anything after making changes to templates. See Scott Hanselman's blog
www.hanselman.com/blog/T4TextTemplateTransforma...
or Oleg Sych's extensive tutorials:
www.olegsych.com/2007/12/how-to-create-a-simple...
Thanks
Ravi
Every developer has had to integrate with another system, API or component. Tis article provides strategies to handle the change and for he separating system boundaries.
Alex Russell talks about the shortcomings of the web platform and how it is evolving in order to adress them. He also explains about how browsers are improving and shares his vision on things to come.
Jeff Lindsay discusses creating distributed and concurrent systems using ZeroMQ – a lightweight message queue-, and gevent – a coroutine-based networking library.
Brian Ketelsen introduces Skynet, a platform for polyglot, distributed and composable services that communicate with each other over RPC/JSON.
Carin Meier tells the story of Alice discovering Monads, meeting three types of monads – Identity, Maybe, State-, and learning how to implement them in Clojure.
The need for agile, queryable, reliable, scalable storage without the pain of SQL schema migration is real. This article uses MongoDB to introduce NoSQL concepts to Java, PHP, and Python developers.
Jérôme Giraud introduces Wink Toolkit, an open source mobile JavaScript framework for HTML5 web or hybrid apps, showing widgets and interactions.
Greg Wilson and Christophe Coenraets demo Adobe Edge, a motion and interaction tool, CSS Regions and Shaders, and PhoneGap.
1 comment
Watch Thread Reply