Saturday, July 26, 2014

Unit Testing Dynamics CRM Plugins

Now there are lots of approaches to unit testing Dynamics CRM plugins and some frameworks for creating Mocks

Recently an XRM Test Framework has been made available

But I like the simple approach(es) outlined in this blog.  It doesn't use any tools because you write the code yourself which can be an advantage or a drawback.  If you don't have time to evaluate a tool and think you can build unit tests quickly, then this is probably a good approach. 

The first approach described in this blog may involve refactoring your code but it is the best approach if you want to run unit tests during an automated build process.  It involves moving most of the code out of the Execute method of the Plug-in and putting it into a "logic" Class Library.  So the unit tests simply call the Class library and you avoid having to go through the executing the plug-in.  OK, it may not test that the attribute filter you included is working properly but at least it tests your code prior to deployment and so would catch any errors.  These approaches, are not mutually exclusive, you would combine them to ensure the quality of the code. 

 

Wednesday, July 23, 2014

VS 2012 and TFS 2013 Build Process Templates - How to add DefaultTemplate.11.1.xaml

Today was one of those days that forced me to blog. It was a deeply frustrating day but ended on a high and I thought to myself why hasn't anyone blogged that before?

I have a VS 2012 solution that was held in TFS 2012 and I've now moved it to TFS 2013.  I did not want to upgrade the development team to VS 2013 just at this moment. Besides, I thought VS 2012 and TFS 2013 were compatible, right?  I was trying to set up automated builds so I created a Build Controller on my build server using the TFS 2013 DVD image.

I opened my solution and selected create Build Definition and selected the Default Template (TfvcTemplate.12.xaml). I immediately saw lots of errors and a few minutes Googling revealed that you can't use this TFS 2013 template for VS 2012 projects.

Now the link just below the drop down list of build process templates should direct you to where the templates are stored in Source Code Explorer. Now my link showed #/1/BuildProcessTemplates/TfvcTemplate.12.xaml and that navigated to nowhere. I mean the link doesn't even start with $ so how was that ever going to work?

So I started trying to find the XAML files for the Build Process Template that the Build Controller was using. If they weren't in TFS then presumably they were on the hard drive. No. Then how do I add a Build Process template to the list? Hours of searching revealed nothing and this was the deeply frustrating part of the day.

Then I found this blog. The author very kindly provides the source code to create a Console application that will allow you to list the Build Process Templates you have and crucially to add a new one.  BTW, the two references that you need to add for this to work can be found in the GAC (C:\Windows\assembly\GAC_MSIL)

Now I already had the DefaultTemplate.11.1.xaml file that I needed for my VS 2012 solution because it was sitting there in the BuildProcessTemplates directory beneath the root of my project in TFS. 

I used the command line similar to this:

ManageBuildTemplates.exe http://jpricket-test:8080/tfs/TestCollection0 TestProject add  $/TestProject/BuildProcessTemplates/MyTemplate.xaml

to add my Build Process Template.  As soon as I selected a new Build Definition I could see my newly added template and I was cooking.  A few minutes later I had my first successful automated build.  From the depths of despair to deep joy in just a few minutes. 

Which of course made me think - why hasn't anybody blogged this before? And Microsoft what the hell were you thinking? Why isn't this essential tool included with TFS?  Thanks again Jason Prickett for providing the source.

Friday, July 11, 2014

Automated Builds and Incrementing Version Numbers

Incrementing the version number when you do a build in Visual Studio seems an obvious requirement.

I found this great post on using a T4 template.  I followed the instructions carefully by creating a common DLL library project, removing the Class1.cs and adding a AssemblyVersion.tt file using the code that was provided. 

As the author points out you just need to save the T4 template file and it will create a .cs file with the assembly information in it with the appropriate build number.  In my case it created a AssemblyVersion.cs file.

As advised, I removed the  AssemblyVersion and AssemblyFileVersion attributes from AssemblyInfo.cs files of all the projects  that I wanted to apply this version number to. 

I then added the AssemblyVersion.cs file to the projects as a link but I moved the file under the Properties folder so it appears directly under AssemblyInfo.cs. If you've not added a link before, select Add existing.. and select the file and you will see the Add button in the dialog has a little down arrow which will reveal the "Add as a link" option. 

Sure enough when I built the solution, my DLLs had the correct version  number. 

But I realised I had to manually save the T4 file each time to refresh the version.cs file.  Now I want to have automated builds so I was looking for a way to process the T4 template before each build.

I finally found the answer from this blog entry. There is a TextTransform.exe file that will take the T4 template and produce the cs file. 

TextTransform.exe is located here
\Program Files\Common Files\Microsoft Shared\TextTemplating\11.0

or

\Program Files (x86)\Common Files\Microsoft Shared\TextTemplating\11.0

In the Pre-Build event of the version project I added this
"C:\Program Files (x86)\Common Files\Microsoft Shared\TextTemplating\11.0\TextTransform.exe" ($ProjectDir)AssemblyVersion.tt -out ($ProjectDir)AssemblyVersion.cs

When I build the solution the version number is incremented.  Brilliant.

You can of course use lots of different variations for incrementing the build  or revision number. But remember the 4 parts are

major.minor.build.revision

I changed the original template to modify the AssemblyFileVersion only and not the AssemblyVersion.  I am still able to distinguish between the DLLs from different builds but the all important AssemblyVersion I control.  The first deployment will be version 1.0.0.0, I can then branch the code and change the T4 template to the next release 1.1.0.0.

To increment from the previous revision number using a T4 template there is a good blog post here. If you want to change both build and revision number use methods which use the declaration starting with <#+
using System.Reflection;
[assembly: AssemblyCompany("C Hoare & Co")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.<#= BuildNumber() #>.<#= RevisionNumber() #>")]
<#+
private int BuildNumber()
{
    int buildNumber = (int)(DateTime.UtcNow - new DateTime(2014,7,1)).TotalDays;
 return buildNumber;
 }
#>
<#+
private int RevisionNumber()
{
    int revisionNumber = 0 ; 
   // other code to increment revision number
    return revisionNumber;
}
#>

A couple of further points. 
1. Make sure there is no white space after the final #> or you will get an error.
2. If using TFS then add to the pre-build event, get latest version of AssemblyVersion,cs, check out before the TextTransform. In the Post Build event check the cs file back in.
3. To pause incrementing the build number, just unload the project from the solution.
4. SharePoint 2010 only recognises the major and minor number of the AssemblyVersion.  That's why controlling the AssemblyVersion is important, but you can increment the AssemblyFileVersion instead.

UPDATE
When I started using this method for automatic builds, I realised that using Pre and Post Build events to process the T4 template produced some errors.  I moved the commands into a PowerShell script and I execute this as a scheduled task an hour before my scheduled builds run.  I still have the version project but it becomes simple  container for the T4 template and the CS file, I don't need to add it to any solutions. I still like this approach. I have one place where I control Assembly and Assembly File Versions.