[NoBrainer] Using TeamCity Build Parameters with Environment Variables in C#

When integrating back end systems we very often would like our build server to run integration tests against our test evironments. The problem is that we do not want to hard code any connection uris (or even worse credentials) into our unit and integration tests.

As we are using TeamCity as our build server (again thanks to JetBrains for our free open source license) we there can easily define evironment variables per build job to define environment specific settings that our tests can read so they can target the appropriate systems.

And while reading an environment variable in C# is as easy as writing …

var value = System.Environment.GetEnvironmentVariable("ABIQUO_API_BASE_URI");

… it is still a nuisance to read and convert them into the correct data types – especially when we have a lot of these properties.

As we are already making heavy use of our ConvertibleBaseDtoConverter (hmm – how does this name roll off the tongue ?) which supports annotation based conversion, we adapted this to support environment variables as well – enter EnvironmentVariableConverter:

Now we can create configuration classes like this where we defines the corresponding environment variable as an annotation with EnvironmentVariable (and also supply default values via the DefaultValue attribute if no corresponding environment variable is defined):

public class AbiquoSettings : 
  biz.dfch.CS.Commons.Converters.EnvironmentVariableBaseDto
{
  [EnvironmentVariable("ABIQUO_API_BASE_URI")]
  [DefaultValue("https://abiquo.example.com/api/")]
  public string AbiquoApiBaseUri { get; set; }

  [EnvironmentVariable("ABIQUO_USERNAME")]
  [DefaultValue("admin")]
  public string Username { get; set; }

  [EnvironmentVariable("ABIQUO_PASSWORD")]
  [DefaultValue("xabiquo")]
  public string Password { get; set; }

  [EnvironmentVariable("ABIQUO_TENANT_ID")]
  [DefaultValue(1)]
  public int TenantId { get; set; }
}

After we have defined this class (which derives from biz.dfch.CS.Commons available at NuGet) we only have to instantiate it and call Import() and all existing environment variables of the process are mapped to their properties.

In addition a conversion to the property type is also performed (as long as the target supports the implicit conversion or Convert.ChangeType()).

[TestClass]
public class AbiquoIntegrationTest
{
  [TestMethod]
  public void TestSomething()
  {
    var settings = new AbiquoSettings();
    settings.Import();

    // settings.AbiquoApiBaseUri now equals 
    // $ENV:ABIQUO_API_BASE_URI or 'DefaultValue'

    // ... test code goes here ...
  }
}

Now all we have to do is to define one ore more environment variables in TeamCity for the build configuration of our project and the settings are picked upon the next execution:

TeamCitiy Build Configuraiion Environment Variables

TeamCitiy Build Configuraiion Environment Variables

For a complete example see IntegrationTestEnvironment.cs.

Happy testing!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: