MsDeploy to Azure Web App with Application Insights extension enabled when deleting additional destination files

When performing an MsDeploy to an Azure Web App and you have the App Insights extension enabled you may find something interesting happens if you use the option to delete additional files on the destination that don’t appear in the source. If you look at the deployment log you may see something like this:

2017-01-30T07:29:27.5515545Z Info: Deleting file ({sitename}\ApplicationInsights.config).
2017-01-30T07:29:27.5515545Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.2.2.0\Microsoft.ApplicationInsights.2.2.0.nupkg).
2017-01-30T07:29:27.5515545Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.2.2.0).
2017-01-30T07:29:27.5515545Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.0.6\Microsoft.ApplicationInsights.Agent.Intercept.2.0.6.nupkg).
2017-01-30T07:29:27.5515545Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.0.6).
2017-01-30T07:29:27.5515545Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.Azure.WebSites.2.2.0\Microsoft.ApplicationInsights.Azure.WebSites.2.2.0.nupkg).
2017-01-30T07:29:27.5515545Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.Azure.WebSites.2.2.0).
2017-01-30T07:29:27.5525645Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.DependencyCollector.2.2.0\Microsoft.ApplicationInsights.DependencyCollector.2.2.0.nupkg).
2017-01-30T07:29:27.5525645Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.DependencyCollector.2.2.0).
2017-01-30T07:29:27.5525645Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.2.0\Microsoft.ApplicationInsights.PerfCounterCollector.2.2.0.nupkg).
2017-01-30T07:29:27.5525645Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.2.0).
2017-01-30T07:29:27.5525645Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.Web.2.2.0\Microsoft.ApplicationInsights.Web.2.2.0.nupkg).
2017-01-30T07:29:27.5525645Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.Web.2.2.0).
2017-01-30T07:29:27.5525645Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.WindowsServer.2.2.0\Microsoft.ApplicationInsights.WindowsServer.2.2.0.nupkg).
2017-01-30T07:29:27.5525645Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.WindowsServer.2.2.0).
2017-01-30T07:29:27.5525645Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.2.0\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.2.0.nupkg).
2017-01-30T07:29:27.5525645Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.2.0).
2017-01-30T07:29:27.5525645Z Info: Deleting file ({sitename}\App_Data\packages\Microsoft.Web.Infrastructure.1.0.0.0\Microsoft.Web.Infrastructure.1.0.0.0.nupkg).
2017-01-30T07:29:27.5525645Z Info: Deleting directory ({sitename}\App_Data\packages\Microsoft.Web.Infrastructure.1.0.0.0).
2017-01-30T07:29:27.5535680Z Info: Deleting directory ({sitename}\App_Data\packages).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.AI.Agent.Intercept.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.AI.DependencyCollector.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.AI.HttpModule.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.AI.PerfCounterCollector.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.AI.ServerTelemetryChannel.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.AI.Web.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.AI.WindowsServer.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.ApplicationInsights.AzureWebSites.dll).
2017-01-30T07:29:27.5535680Z Info: Deleting file ({sitename}\bin\Microsoft.ApplicationInsights.dll).

The cool thing about this is it gives you an indication of what the extension actually does. The fact there is an App_Data/packages folder with what is clearly unpacked NuGet packages tells us that the extension is installing a NuGet package into your site for you. That makes a lot of sense given you don’t need to install the extension if you installed the NuGet package yourself (I generally don’t bother because I don’t need App Insights locally and see it as a deployment concern so I like App Service adding it for me :)).

Setting the MsDeploy option to delete extraneous files is very useful so it’s not something I want to simply turn off. However, a knowledge of MsDeploy gives us some indication as to a possible solution. In this case we can make use of the skip option to specify that MSDeploy should ignore the above affected files.

Putting it all together, if you specify the following rules in your msdeploy.exe call then you should have success:

-skip:objectname='filePath',absolutepath='ApplicationInsights.config' -skip:objectname='dirPath',absolutepath='App_Data\\packages\\*.*' -skip:objectname='filePath',absolutepath='bin\\Microsoft.AI.*.dll'  -skip:objectname='filePath',absolutepath='bin\\Microsoft.ApplicationInsights.*.dll'

After doing that your deployment log should look something like this:

2017-01-30T08:10:26.7172425Z Info: Object filePath ({sitename}\ApplicationInsights.config) skipped due to skip directive 'CommandLineSkipDirective 1'.
2017-01-30T08:10:26.7182428Z Info: Object dirPath ({sitename}\App_Data\packages) skipped due to skip directive 'CommandLineSkipDirective 2'.
2017-01-30T08:10:26.7192429Z Info: Object filePath ({sitename}\bin\Microsoft.AI.Agent.Intercept.dll) skipped due to skip directive 'CommandLineSkipDirective 3'.
2017-01-30T08:10:26.7192429Z Info: Object filePath ({sitename}\bin\Microsoft.AI.DependencyCollector.dll) skipped due to skip directive 'CommandLineSkipDirective 3'.
2017-01-30T08:10:26.7192429Z Info: Object filePath ({sitename}\bin\Microsoft.AI.HttpModule.dll) skipped due to skip directive 'CommandLineSkipDirective 3'.
2017-01-30T08:10:26.7192429Z Info: Object filePath ({sitename}\bin\Microsoft.AI.PerfCounterCollector.dll) skipped due to skip directive 'CommandLineSkipDirective 3'.
2017-01-30T08:10:26.7192429Z Info: Object filePath ({sitename}\bin\Microsoft.AI.ServerTelemetryChannel.dll) skipped due to skip directive 'CommandLineSkipDirective 3'.
2017-01-30T08:10:26.7202428Z Info: Object filePath ({sitename}\bin\Microsoft.AI.Web.dll) skipped due to skip directive 'CommandLineSkipDirective 3'.
2017-01-30T08:10:26.7202428Z Info: Object filePath ({sitename}\bin\Microsoft.AI.WindowsServer.dll) skipped due to skip directive 'CommandLineSkipDirective 3'.
2017-01-30T08:10:26.7202428Z Info: Object filePath ({sitename}\bin\Microsoft.ApplicationInsights.AzureWebSites.dll) skipped due to skip directive 'CommandLineSkipDirective 4'.
2017-01-30T08:10:26.7202428Z Info: Object filePath ({sitename}\bin\Microsoft.ApplicationInsights.dll) skipped due to skip directive 'CommandLineSkipDirective 4'.

What to do when accidentally deleting App Insights files

If you find yourself in the position that you have accidentally deleted the App Insights files you simply need to delete the App Insights extension and then re-add it and it should work again.

Adding the SDK to your application

If you eventually end up adding the App Insights SDK to your application then take note that you will probably want to delete the App Insights extension and remove the MsDeploy exclusions. This avoids the problem where an update by the Site Extension to a different version of App Insights SDK causes assembly load errors.

Announcing release of ChameleonForms 2.0.0 and new documentation site

I’m somewhat more subdued with my excitement for announcing this than I was for 1.0. In fact I just had a chuckle to myself in re-reading that post 🙂 (oh and if you were wondering – did Matt and I enjoy Borderlands 2? Yes we very much did, it’s a great game).

Nonetheless, there is some really cool stuff in ChameleonForms 2.0 and I’m particularly excited about the new PartialFor functionality, which I will describe below. My peak excitement about PartialFor was months ago when the code was actually written, but Matt and I have had a particularly busy second half of the year with our work roles expanding in scope and a healthy prioritisation of our personal lives so it took a while to get our act together and get the code merged and released.

There have been a range of point releases that added a bunch of functionality to ChameleonForms since the 1.0 release and before this 2.0 release. You can peruse the releases list to see the features.

New docs site

I’ve taken the lead (as well as a bunch of advice – thanks mate) from Jake Ginnivan and moved the documentation for ChameleonForms to Read the Docs. The new documentation site is now generated from files in the source repository’s docs folder. This is awesome because it means that the documentation can be tied to current state of the software – no more documentation that is ahead or behind and pull requests can now contain documentation changes corresponding to the code changes.

For those who are curious the process I followed to migrate from GitHub wiki to Read the Docs was:

  1. Clone the wiki
  2. Move all the files into the docs folder of the repository
  3. Add a mkdocs.yml file to the root of the repository with all of the files (this means I need to keep a list of the files in there, but I don’t mind since it gives me control of the menu, you can omit the mkdocs.yml file if you want and it alphabetically places all of the files in the menu)
  4. Sign up for Read the Docs and create a new project linked to the GitHub repository
  5. Enable the fenced code markdown extension
  6. Change all internal documentation links to reference the .md file (in my case I had to search for all links to wiki/* and remove the wiki/ and add in the .md)
  7. Change any occurrences of ```c# with ```csharp (GitHub supports using c# for the fenced code snippet, but mkdocs doesn’t)
  8. Check all of the pages since some of them might render weirdly – I had to add some extra spaces between paragraphs and code blocks / bullet lists for instance since the markdown parser is slightly different

There are a bunch of different formats that give more flexibility that Read the Docs supports (e.g. restructured text), but I’m very happy with the markdown support.

2.0 minor features and bug fixes

Check out the release notes for the 2.0 release to see a bunch of minor new features and bug fixes that have been contributed by a bunch of different people – thanks to everyone that contributed! It always give Matt and I a rush when we receive a pull request from someone :).

PartialFor feature

This is the big feature. A few breaking changes went into the 2.0 release in order to make this possible. This is the first of the extensibility features we have added to ChameleonForms.

Essentially, it allows us to contain a part of a form in a partial view, with full type-safety and intellisense. The form can be included directly against a form or inside a form section. This makes things like common parts of forms for create vs edit screens possible. This allows you to remove even more repetition in your forms, while keeping a clean separation between forms that are actually separate.

The best way to see the power of the feature in it’s glory is by glancing over the acceptance test for it. The output should be fairly self explanatory.

There is also a documentation page on the feature,

Is ChameleonForms still relevant?

We were very lucky to be included in Scott Hanselman’s NuGet package of the week earlier this year. The comments of Scott’s post are very interesting because it seems our library is somewhat controversial. A lot of people are saying that single page applications and the increasing prevalence of JavaScript make creating forms in ASP.NET MVC redundant.

Matt and I have spent a lot more time in JavaScript land than MVC of late and we concede that there is certainly a lot more scenarios now that don’t make sense to break out MVC. That means ChameleonForms isn’t as relevant as when we first started developing it.

In saying that, we still firmly believe that there are a range of scenarios that MVC is very much appropriate for. Where you don’t need the flexibility of an API and/or you need pure speed of development (in particular developing prototypes) and/or you’re building CRUD applications or heavily forms-based applications (especially where you need consistency of your forms) we believe MVC + ChameleonForms is very much a good choice and often is the best choice.

Recent talks

I recently gave a couple of conference talks:

  • 2015 Yow! West conference: Joint presentation with Matt Davies on Microtesting
    • Do you want to write less tests for the same amount of confidence?

      Do you want to print out the testing pyramid on a dot matrix printer, take it outside and set fire to it?

      How confident are you that you can survive the refactoring apocalypse without breaking your tests?

      As consultants, we get to see how testing is performed across many different organisations and we have a chance to experiment with different testing strategies across multiple projects. Through this experience, we have developed a pragmatic process for setting an initial testing strategy that is as simple as possible and iterating on that strategy over time to evolve it based on how it performs. We have also settled on a style of testing that has proved to be very effective at reducing testing effort while maintaining (or even improving) confidence from our tests.

      This talk will focus on some of our learnings and we will cover the different types of testing and how they interact, breaking apart the usual practice of testing all applications in the same way, the mysterious relationship between speed and confidence, how we were able to throw away the testing pyramid and a number of techniques that have worked well for us when testing our applications.

    • Slides published to GitHub
    • There will be a video, I’ll link to it from the GitHub when it’s published
  • 2015 ANZ Coders virtual conference: Presentation on Applying useful testing patterns using TestStack.Dossier
    • The Object Mother, Test Data Builder, Anonymous Variable/Value, equivalence class and constrained non-determinism patterns/concepts can help you make your tests more readable/meaningful, more terse and more maintainable when used in the right way.

      This talk will explain why and where the aforementioned patterns are useful and the advantages they can bring and show examples in code using a library I recently released called TestStack.Dossier.

    • Slides published to GitHub
    • Video

Azure Resource Manager intro presentation and workshop

I attended the Azure Saturday event here in Perth last weekend. Matt and I did a basic intro presentation on Azure Resource Manager and ran an associated workshop, which we have published to our GitHub organisation.

Azure Resource Manager is one of the most important things to understand about Azure if you plan on using it since it’s the platform that underpins the provisioning and management of all resources in Azure going forward.

Azure Saturday Perth 2015 presentation

Automating Azure Resource Manager

I’ve recently been (finally) getting to speed with Azure Resource Manager (ARM). It’s the management layer that drives the new Azure Portal and also features like Resource Groups and Role-Based Access Control.

You can interact with ARM in a number of ways:

To authenticate to the ARM API you need to use an Azure AD credential. This is all well and good if you are logged into the Portal, or running a script on your computer (where a web browser login prompt to Azure AD will pop up), but when automating your API calls that’s not available.

Luckily there is a post by David Ebbo that describes how to generate a Service Principal (equivalent of the concept of an Active Directory Service Account) attached to an Azure AD application.

The only problem with this post is that there are a few manual steps and it’s quite fiddly to do (by David’s own admission). I’ve developed a PowerShell module that you can use to idempotently create a Service Principal against either an entire Azure subscription or against a specific Resource Group that you can then use to automate your ARM code.

I’ve published the code to GitHub.

In order to use it you need to:

  1. Ensure you have the Windows Azure PowerShell commandlets installed
  2. Download the Set-ARMServicePrincipalCredential.psm1 file from my GitHub repository
  3. Download the Azure Key Vault PowerShell commandlets and put the AADGraph.ps1 file next to the file from GitHub
  4. Execute the Set-ARMServicePrincipalCredential command as per the examples on GitHub

This will pop up a web browser prompt to authenticate (this will happen twice since I’m using two disjointed libraries – hopefully this will get resolved if Azure AD commandlets end up becoming integrated with the Azure Commandlets) give you the following information:

  • Tenant ID
  • Client ID
  • Password

From there you have all the information you need to authenticate your automated script with ARM.

If using PowerShell then this will look like:

    $securePassword = ConvertTo-SecureString $Password -AsPlainText -Force
    $servicePrincipalCredentials = New-Object System.Management.Automation.PSCredential ($ClientId, $securePassword)
    Add-AzureAccount -ServicePrincipal -Tenant $TenantId -Credential $servicePrincipalCredentials | Out-Null

If using ARMClient then this will look like:

    armclient spn $TenantId $ClientId $Password | Out-Null

One last note: make sure you store the password securely when automating the script, e.g. TeamCity password, Bamboo password or Octopus sensitive variable.

Testing AngularJS directives using Approval Tests

I recently had an application I was developing using AngularJS that contained a fair number of directives that were somewhat complex in that the logic that backed them was contained in services that called HTTP APIs. The intent was to provide a single JavaScript file that designers at the company I was working at could include and then build product pages using just HTML (via the directives). I needed to provide some confidence when making changes to the directives and pin down the behaviour.

As explained below, I ended up doing this via approval tests and I’ve published how I did it on GitHub.

Why I wanted to use Approval Tests

In order to test these directives I didn’t want to have to perform tedious DOM inspection code to determine if the directives did what I wanted. Most AngularJS directive testing examples you will find on the Internet tell you to do this though, including the official documentation.

Side note: in my research I stumbled across the ng-directive-testing library, which I feel is an improvement over most example code out there and if you do want to inspect the DOM as part of your testing I recommend you check it out.

This style of testing works fine for small, simple directives, but I felt would be tedious to write and fragile for my use case. Instead, I had an idea that I wanted to apply the approval tests technique.

I use this technique when I have a blob of JSON, XML, HTML, text etc. that I want to verify is what I expect and pin it down without having to write tedious assertions against every aspect of it – hence this technique fitted in perfectly with what I wanted to achieve with testing the directives.

How I did it

Given that directives need the DOM it was necessary to run the tests in a web browser. In this case I decided to do it via Karma since I was already using Node JS to uglify the JavaScript.

ApprovalTests requires access to the filesystem in order to write the approval files and then access to open processes on the computer to pop open a diff viewer if there is a difference in the output. This is not possible from the web browser. Thus, even though there is a JavaScript port of ApprovalTests (for NodeJS) I wasn’t able to use it directly in my tests.

While contemplating my options, it occured to me I could spin up a NodeJS server to run the approvals code and simply call it from the browser – it’s not much different to how Karma gets test results. After that realisation I stumbled across approvals-server – someone had already implemented it! Brilliant!

From there it was simply a matter of stitching up the code to all work together – in my case using Grunt as the Task Runner.

Example code

To that end, I have published a repository with a contrived example that demonstrates how to test a directive using Approval Tests.

The main bits to look at are:

  • gruntfile.js – contains the grunt configuration I used including my Grunt tasks for the approval server, which probably should be split into a separate file or published to npm (feel free to send me a PR)
  • app/spec/displayproducts.directive.spec.js – contains the example test in all it’s glory
  • app/test-helpers/approvals/myapp-display-products-should-output-product-information.approved.txt – the approval file for the example test
  • app/test-helpers/approvals.js – the code to get name of currently executing Jasmine 2 test and the code to send an approval to the approval server
  • app/test-helpers/heredoc.js – a heredoc function to allow for easy specification of multi-line markup
  • app/test-helpers/directives.js – the test code that compiles the directive, cleans it up for a nice diff and passes it to be verified

Notable bits

Style guide

If you are curious about why I wrote my Angular code the way I have it’s because I’m following John Papa’s AngularJS style guide, which I think is very good and greatly improves maintainability of the resulting code.

Taming karma

I managed to get the following working for Karma:

  • Watch build that runs tests whenever a file changes – see the karma:watch and dev tasks
  • Default build including tests – see the karma:myApp and default tasks
  • A build that pops up a Chrome window to allow for debugging – see the karma:debug and debugtests takss

Simultaneous approval server runs

I managed to allow for the dev task to be running while running default by including the isPortTaken code to determine if the approvals server port is already taken.

Side note: if you are using this code across multiple projects consecutively then be careful because the approval server might be running from the other project. A way to avoid this would be to change the port per project (in both gruntfile.js and approvals.js.

Improved approval performance on Windows

I found that the performance of the approvals library was very slow on Windows, but with some assistance from the maintainers I worked out what the cause was and submitted a pull request. The version in npm has been updated, but there are currently no updates to approvals-server to use it. To overcome this I have used the npm-shrinkwrap.json file to override the version of the approvals library.

Get currently running test name in Jasmine 2

I wanted the approval test output file to be automatically derived from the currently-running test name (similar to what happens on .NET). It turns out that is a lot harder to arhieve in Jasmine 2, but with some Googling/StackOverflowing I managed to get it working as per the code in the approvals.js file.

Cleaning up the output markup for a good diff

AngularJS leaves a bunch of stuff in the resulting markup such as HTML comments, superfluous attributes and class names, etc. In order to remove all of this so the approved file is clean and in order to ensure the whitespace in the output is both easy to read and the same no matter what browser is being used I apply some modifications to the markup as seen in directives.js.

Easily specifying multi-line test markup

I pulled in a heredoc function I found on StackOverflow as seen in heredoc.js and used in the example test, e.g.:

DirectiveFixture.verify(heredoc(function () {/*    
    <myapp-display-products category="car" product="car">
        <div>{{car.name}}</div>
    </myapp-display-products>
*/}));

This is much nicer than having to concatenate one stirng per line or append a \ character at the end of each line, both of which aren’t handled nicely by the IDE I’m using.

 

Announcing TestStack.Dossier library

I’m pleased to announce the addition of a (somewhat) new library to the TestStack family called TestStack.Dossier. I say somewhat new because it’s a version 2 of an existing library that I published called NTestDataBuilder. If you hadn’t already heard about that library here is the one liner (which has only changed slightly with the rename):

TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns.

The release of TestStack.Dossier culminates a few months of (off and on) work by myself and fellow TestStacker Michael Whelan to bring a range of enhancements. The library itself is very similar to NTestDataBuilder, but there are some minor breaking changes. I decided to reduce confusion by keeping the version number consistent between libraries so TestStack.Dossier starts at version 2.0.

So why should I upgrade to v2 anyway?

There is more to TestStack.Dossier v2 than just a name change, a lot more. I’ve taken my learnings (and frustrations) from a couple of years of usage of the library into account to add in a bunch of improvements and new features that I’m really excited about!

Side note: my original post on combining the test data builder pattern with the object mother pattern and follow-up presentation still holds very true – this combination of patterns has been invaluable and has led to terser, more readable tests that are easier to maintain. I still highly recommend this approach (I use NTestDataBuilder TestStack.Dossier for the test data builder part).

Anonymous value support

As explained in my anonymous variables post (TBW(ritten) – future proofing this post, or setting myself up for disappointment :P) in my automated testing series, the use of the anonymous variable pattern is a good pattern to use when you want to use values in your tests whose exact value isn’t significant. By including a specific value you are making it look like that value is important in some way – stealing cognitive load from the test reader while they figure out the value in fact doesn’t not matter.

This is relevant when defining a test data builder because of the initial values that you set the different parameters to by default. For instance, the example code for NTestDataBuilder on the readme had something like this:

class CustomerBuilder : TestDataBuilder<Customer, CustomerBuilder>
{
    public CustomerBuilder()
    {
        WithFirstName("Rob");
        WithLastName("Moore");
        WhoJoinedIn(2013);
    }

    public CustomerBuilder WithFirstName(string firstName)
    {
        Set(x => x.FirstName, firstName);
        return this;
    }

    ...
}

In that case the values "Rob", "Moore" and 2013 look significant on initial inspection. In reality it doesn’t matter what they are; any test where those values matter should specify them to make the intent clear.

One of the changes we have made for v2 is to automatically generate an anonymous value for each requested value (using Get) if none has been specified for it (using Set). This not only allows you to get rid of those insignificant values, but it allows you to trim down the constructor of your builder – making the builders terser and quicker to write.

Given we aren’t talking about variables but rather values I have thus named the pattern anonymous values rather than anonymous variables.

There are a number of default conventions that are followed to determine what value to use via the new Anonymous Value Fixture class. This works through the application of anonymous value suppliers – which are processed in order to determine if a value can be provided and if so a value is retrieved. At the time of writing the default suppliers are the following (applied in this order):

  • DefaultEmailValueSupplier – Supplies an email address for all string properties with a property name containing email
  • DefaultFirstNameValueSupplier – Supplies a first name for all string properties with a property name containing firstname (case insensitive)
  • DefaultLastNameValueSupplier – Supplies a last name for all string properties with a property name containing lastname or surname (case insensitive)
  • DefaultStringValueSupplier – Supplies the property name followed by a random GUID for all string properties
  • DefaultValueTypeValueSupplier – Supplies an AutoFixture generated value for any value types (e.g. int, double, etc.)
  • DefaultValueSupplier – Supplies default(T)

This gets you started for the most basic of cases, but from there you have a lot of flexibility to apply your own suppliers on both a global basis (viaAnonymousValueFixture.GlobalValueSuppliers) and a local basis for each fixture instance (via fixture.LocalValueSuppliers) – you just need to implement IAnonymousValueSupplier. See the tests for examples.

Equivalence classes support

As explained in my equivalence classes and constrained non-determinism post (TBW) in my automated testing series the principle of constrained non-determinism frees you from having to worry about the fact that anonymous values can be random as long as they fall within the equivalence class of the value that is required for your test.

I think the same concept can and should be applied to test data builders. More than that, I think it enhances the ability for the test data builders to act as documentation. Having a constructor that reads like this for instance tells you something interesting about the Year property:

class CustomerBuilder : TestDataBuilder<Customer, CustomerBuilder>
{
    public CustomerBuilder()
    {
        WhoJoinedIn(Any.YearAfter2001());
    }

    ...
}

You may well use value objects that protect and describe the integrity of the data (which is great), but you can still create an equivalence class for the creation of the value object so I still think it’s relevant beyond primitives.

We have some built-in equivalence classes that you can use to get started quickly for common scenarios. At the time of writing the following are available (as extension methods of the AnonymousValueFixture class that is defined in a property called Any on the test data builder base class):

  • Any.String()
  • Any.StringMatching(string regexPattern)
  • Any.StringStartingWith(string prefix)
  • Any.StringEndingWith(string suffix)
  • Any.StringOfLength(int length)
  • Any.PositiveInteger()
  • Any.NegativeInteger()
  • Any.IntegerExcept(int[] exceptFor)
  • Any.Of<TEnum>()
  • Any.Except<TEnum>(TEnum[] except)
  • Any.EmailAddress()
  • Any.UniqueEmailAddress()
  • Any.Language()
  • Any.FemaleFirstName()
  • Any.MaleFirstName()
  • Any.FirstName()
  • Any.LastName()
  • Any.Suffix()
  • Any.Title()
  • Any.Continent()
  • Any.Country()
  • Any.CountryCode()
  • Any.Latitude()
  • Any.Longitude()

There is nothing stopping you using the anonymous value fixture outside of the test data builders – you can create a property called Any that is an instance of the AnonymousValueFixture class in any test class.

Also, you can easily create your own extension methods for the values and data that makes sense for your application. See the source code for examples to copy. A couple of notes: you have the ability to stash information in the fixture by using the dynamic Bag property and you also have an AutoFixture instance available to use via Fixture.

Side note: I feel that Dossier does some things that are not easy to do in AutoFixture, hence why I don’t “just use AutoFixture” – I see Dossier as complimentary to AutoFixture because they are trying to achieve different (albeit related) things.

A final note: I got the idea for the Any.Whatever() syntax from the TDD Toolkit by Grzegorz Gałęzowski. I really like it and I highly recommend his TDD e-book.

Return Set rather than this

This is a small, but important optimisation that allows test data builders to be that little bit terser and easier to read/write. The Set method now returns the builder instance so you can change your basic builder modification methods like in this example:

// Before
public CustomerBuilder WithLastName(string lastName)
{
    Set(x => x.LastName, lastName);
    return this;
}

// After
public CustomerBuilder WithLastName(string lastName)
{
    return Set(x => x.LastName, lastName);
}

Amazingly terse list of object generation

This is by far the part that I am most proud of. I’ve long been frustrated (relatively speaking, I thought what I had in the first version was very cool and useful) with the need for writing the lambda expressions when building a list of objects, e.g.:

var customers = CustomerBuilder.CreateListOfSize(3)
    .TheFirst(1).With(b => b.WithFirstName("Robert").WithLastName("Moore))
    .TheLast(1).With(b => b.WithEmail("matt@domain.tld"))
    .BuildList();

I always found tha the need to have the With made it a bit more verbose than I wanted (since it was basically noise) and I found that needing to write the lambda expression slowed me down. I dreamed of having a syntax that looked like this:

var customers = CustomerBuilder.CreateListOfSize(3)
    .TheFirst(1).WithFirstName("Robert").WithLastName("Moore")
    .TheLast(1).WithEmail("matt@domain.tld")
    .BuildList();

Well, one day I had a brainwave on how that may be possible and I went and implemented it. I won’t go into the details apart from saying that I used Castle Dynamic Proxy to do the magic (and let’s be honest it’s magic) and you can check out the code if interested. I’m hoping this won’t come back to bite me, because I’ll freely admit that this adds complexity to the code for creating lists; you can have an instance of a builder that isn’t an instance of a real builder, but rather a proxy object that will apply the call to part of a list of builders (see what I mean about complex)? My hope is that the simplicity and niceness of using the API outweighs the confusion / complexity and that you don’t really have to understand what’s going on under the hood if it “just works”TM.

If you don’t want to risk it that’s fine, there is still a With method that takes a lambda expression so you can freely avoid the magic.

The nice thing about this is I was able to remove NBuilder as a dependency and you no longer need to create an extension method for each builder to have a BuildList method that doesn’t require you to specify the generic types.

Why did you move to TestStack and why is it now called Dossier?

I moved the library to TestStack because it’s a logical fit – the goal that we have at TestStack is to make it easier to perform automated testing in the .NET ecosystem – that’s through and through what this library is all about.

As to why I changed the name to Dossier – most of the libraries that we have in TestStack have cool/quirky names that are relevant to what they do (e.g.Seleno, Bddfy). NTestDataBuilder is really boring so with a bit of a push from my colleagues I set about to find a better name. I found Dossier by Googling for synonyms of data and out of all the words dossier stood out as the most interesting. I then asked Google what the definition was to see if it made sense and low and behold, the definition is strangely appropriate (person, event, subject being examples of the sorts of objects I tend to build with the library):

a collection of documents about a particular person, event, or subject

Mundane stuff

The GitHub repository has been moved to https://github.com/TestStack/TestStack.Dossier/ and the previous URL will automatically redirect to that address. I have released an empty v2.0 NTestDataBuilder release to NuGet that simply includes TestStack.Dossier as a dependency so you can do anUpdate-Package on it if you want (but will then need to address the breaking changes).

If you have an existing project that you don’t want to have to change for the breaking changes then feel free to continue using NTestDataBuilder v1 – for the featureset that was in it I consider that library to be complete and there weren’t any known bugs in it. I will not be adding any changes to that library going forward though.

As usual you can grab this library from NuGet.