Unit Tests & Scratchpads

21 Jan 2017

Often when developing something, I have the need to check how a function or library works. For example, I always have to check for this question:

Does Directory.ListFiles(".\\temp\\") return a list of filenames, a list of relative filepaths, or a list of rooted filepaths?

It returns relative filepaths by the way:

Directory.ListFiles(".\\temp\\");
[ ".\temp\NuCrunch.Tests.csproj", ".\temp\packages.config", ".\temp\Scratchpad.cs" ]

Now that there is a C# Interactive window in Visual Studio, you can use that to test the output. Sometimes however the C# Interactive window is not suitable:

  • You want to test needs a little more setup than a couple of lines
  • You wish to use the debugger to check on intermediate state
  • You are not in Visual Studio (I am 99% of the time in Rider)

When this happens, I turn to the unit test file which I add to all unit test projects: the Scratchpad.cs.

The complete listing of the file is this:

using Xunit;
using Xunit.Abstractions;

namespace NuCrunch.Tests
{
	public class Scratchpad
	{
		private readonly ITestOutputHelper _output;

		public Scratchpad(ITestOutputHelper output)
		{
			_output = output;
		}

		[Fact]
		public void When_testing_something()
		{

		}
	}
}

It gets committed to the git repository with no content in the When_testing_something method, and is never committed again afterwards. The _output field is added to allow writing to console/test window easily too.

Now whenever I wish to experiment with something, I can pop open the Scratchpad write some test content, then execute and debug it to my hearts content.

After I am done with the test code, one of two things happen: it gets deleted, or it gets moved into a proper unit test.

code, net, testing, xunit

---

Update all Docker images

16 Jan 2017

My work’s wifi is much faster than my 4G connection, so periodically I want to update all my docker images on my personal laptop while at work.

As I want to just set it going and then forget about it, I use the following one liner to do a docker pull against each image on my local machine:

docker images | grep -v REPOSITORY | awk '{print $1}'| xargs -L1 docker pull

Now if only I could get git bash to do TTY properly so I get the pretty download indicators too :(

docker, bash, git

---

MediatR and Magic

07 Jan 2017

Having recently watched Greg Young’s excellent talk on 8 Lines of Code I was thinking about how this kind of thinking applies to the mediator pattern, and specifically the MediatR implementation.

I have written about the advantages of CQRS with MediatR before, but having used it for a long time now, there are some parts which cause friction on a regular basis.

The problems

Discoverability

The biggest issue first. You have a controller with the following constructor:

public AddressController(IMediator mediator)
{
    _mediator = mediator;
}

What messages does it emit? What handlers are used by it? No idea without grepping for _mediator.

Where is the hander for X?

So you have a controller with a method which sends a GetAllAddressesQuery:

public class AddressController : ApiController
{
    public IEnumerable<Address> Get()
    {
        return _mediator.Send(new GetAllAddressesQuery(User));
    }
}

The fastest way to get to the handler definition is to hit Ctrl+T and type in GetAllAddressesQueryHandler. This becomes more problematic on larger codebases when you can end up with many handlers with similar names.

What calls {command|query}Handler?

Given the following handler, what uses it?

public class GetAllAddressesQueryHandler : IRequestHandler<GetAllAddressesQuery, IEnumerable<Address>>
{
    public IEnumerable<Address> Handle(GetAllAddressesQuery message)
    {
        //...
    }
}

With this problem you can use Find Usages on the GetAllAddressesQuery type parameter to find what calls it, so this isn’t so bad at all. The main problem is I am often doing Find Usages on the handler itself, not the message.

Solutions

Discoverability

The team I am on at work felt this problem a lot before I joined, and had decided to role their own mediation pipeline. It works much the same as MediatR, but rather than injecting an IMediator interface into the constructor, you inject interface(s) representing the handler(s) being used:

public AddressController(IGetAllAddressesQueryHandler getHandler, IAddAddressHandler addHandler)
{
    _getHandler = getHandler;
    _addHandler = addHandler;
}

The trade-offs made by this method are:

  • The controllers are now more tightly coupled to the handlers (Handlers are mostly used by 1 controller anyway)
  • We can’t easily do multicast messages (We almost never need to do this)
  • More types are required (the interface) for your handler (so what?)

On the whole, I think this is a pretty good trade-off to be made, we get all the discoverability we wanted, and our controllers and handlers are still testable.

What calls/Where is {command|query}Handler?

This is also solved by the switch to our internal library, but we also augment the change by grouping everything into functionality groups:

Frontend
  Adddress
    AddressController.cs
    GetAllAddressesQuery.cs
    GetAllAddressesQueryHandler.cs
    IGetAllAddressesQueryHandler.cs
  Contact
    ContactController.cs
    ...
  Startup.cs
  project.json

I happen to prefer this structure to a folder for each role (e.g. controllers, messages, handlers), so this is not a hard change to make for me.

Magic

As Greg noted in his video, the second you take in a 3rd party library, it’s code you own (or are responsible for). The changes we have made have really just traded some 3rd party magic for some internal magic. How the handler pipeline gets constructed can be a mystery still (unless you go digging through the library), but it’s a mystery we control.

The important part of this to note is that we felt a pain/friction with how we are working, and decided to change what trade-offs we were making.

What trade-offs are you making? Is it worth changing the deal?

code, net, cqs, cqrs, mediatr

---

Git Aliases

06 Jan 2017

Git is great, but creating some git aliases is a great way to make your usages even more efficient.

To add any of these you can either copy and paste into the [alias] section of your .gitconfig file or run git config --global alias.NAME 'COMMAND' replacing NAME with the alias to use, and COMMAND with what to run.

So without further ado, here are the ones I have created and use on a very regular basis.

Constant usage

  • git s - an alias for git status. Have to save those 5 keypresses!

    s = status
    
  • git cm "some commit message" - shorthand for commit with a message

    cm = commit -m
    
  • git dc - diff files staged for commit

    dc = diff --cached
    
  • git scrub - deletes everything not tracked by git (git clean -dxf) except the packages and node_modules directories

    scrub = clean -dxf --exclude=packages --exclude=node_modules
    

Context switching, rebasing on dirty HEAD

I rebase my changes onto the current branches often, but rebasing requires a clean repository to work on. The following two aliases are used something like this: git save && git pull --rebase && git undo

  • git save - adds and commits everything in the repository, with the commit message SAVEPOINT

    save = !git add -A && git commit -m 'SAVEPOINT'
    
  • git undo - undoes the last commit, leaving everything as it was before committing. Mostly used to undo a git save call

    undo = reset HEAD~1 --mixed
    

I also use these if I need to save my work to work on a bug fix on a different branch.

What have I done?

Often I want commits I have pending, either to the local master, or a remote tracking branch. These both give an output like this:

Git Pending

  • git pending - shows the commits on the current branch compared to the origin/master branch

    pending = log origin/master..HEAD --pretty=oneline --abbrev-commit --format='%Cgreen%cr:%Creset %C(auto)%h%Creset %s'
    
  • git pendingup - shows the commits on the current branch compared to its tracking branch

    pendingup = "!git log origin/\"$(git rev-parse --abbrev-ref HEAD)\"..HEAD --pretty=oneline --abbrev-commit --format='%Cgreen%cr:%Creset %C(auto)%h%Creset %s'"
    

More?

I have some others not documented here, but are in my config repo on Github.

code, git, environment, bash

---

Strong Type All The Configurations

06 Dec 2016

As anyone I work with can attest, I a have been prattling on about strong typing everything for quite a while. One of the places I feel people don’t utilise strong typing enough is in application configuration. This manifests in a number of problems in a codebase.

The Problems

The first problem is when nothing at all is done about it, and you end up with code spattered with this:

var someUrl = new Uri(ConfigurationManager.AppSettings["RemoteService"]);

This itself causes a few problems:

  • Repeated: You have magic strings throughout your codebase
  • Consistency: Was it RemoteService or RemoteServiceUri. Or was it in ConnectionStrings or AppSettings?
  • Visibility: Can you tell which classes require on which (if any) configuration values?
  • Typing: Was it actually a URL? or was it DNS entry?
  • Late errors: You will only find out once that particular piece of code runs
  • Tight Coupling: Tests won’t help either, as they’ll be reading your test’s app.config instead…

Solution: Version 1

The first solution involves abstracting the ConfigurationManager behind a general interface, which can be injected into classes requiring configuration values. The interface is usually along the following lines:

public interface ISettings
{
    string GetString(string key);
    Uri GetUri(string key);
    // GetInt, GetShort, etc.
}

And having an implementation which uses the ConfigurationManager directly:

public class Settings : ISettings
{
    public string GetString(string key) => ConfigurationManager.AppSettings[key];
    public Uri GetUri(string key) => new Uri(ConfigurationManager.AppSettings[key]);
}

This solves one of the problems of direct usage of the ConfigurationManager, namely Tight Coupling. By using an interface we can now use NSubstitute or similar mocking library to disconnect tests from app.config and web.config.

It doesn’t really solve the Typing issue however, as the casting is only done on fetching the configuration value, and so errors in casting still only happen when the code is executed. It also doesn’t really solve the Discoverability issue either - you can now tell if a class requires configuration values, but you cannot tell which values it requires from outside.

The other issues such as Repeatablility, Late Errors and Consistency are not addressed by this method at all.

Solution: Version 2

My preferred method of solving all of these problems is to replace direct usage of ConfigurationManager with an interface & class pair, but with the abstraction being application specific, rather than general. For example, at application might have this as the interface:

public interface IConfiguration
{
    string ApplicationName { get; }
    Uri RemoteHost { get; }
    int TimeoutSeconds { get; }
}

This would then be implemented by a concrete class:

public class Configuration : IConfiguration
{
    public string ApplicationName { get; }
    public Uri RemoteHost { get; }
    public int TimeoutSeconds { get; }

    public Configuration()
    {
        ApplicationName = ConfigurationManager.AppSetting[nameof(ApplicationName)];
        RemoteHost = new Uri(ConfigurationManager.AppSetting[nameof(RemoteHost)]);
        TimeoutSeconds = (int)ConfigurationManager.AppSetting[nameof(TimeoutSeconds)];
    }
}

This method solves all of the first listed problems:

Repeated and Consistency are solved, as the only repetition is the usage of configuration properties themselves. Visibility is solved as you can now either use “Find Usages” on a property, or you can split your configuration interface to have a specific set of properties for each class which is going to need configuration.

Typing and Late errors are solved as all properties are populated on the first creation of the class, and exceptions are thrown immediately if there are any type errors.

Tight Coupling is also solved, as you can fake the entire IConfiguration interface for testing with, or just the properties required for a given test.

The only down side is the amount of writing needed to make the constructor, and having to do the same code in every application you write.

Solution: Version 3

The third solution works exactly as the 2nd solution, but uses the Stronk Nuget library to populate the configuration object. Stronk takes all the heavy lifting out of configuration reading, and works for most cases with zero extra configuration required.

public interface IConfiguration
{
    string ApplicationName { get; }
    Uri RemoteHost { get; }
    int TimeoutSeconds { get; }
}

public class Configuration : IConfiguration
{
    public string ApplicationName { get; }
    public Uri RemoteHost { get; }
    public int TimeoutSeconds { get; }

    public Configuration()
    {
        this.FromAppConfig(); //this.FromWebConfig() works too
    }
}

Stronk supports a lot of customisation. For example, if you wanted to be able to handle populating properties of type MailAddress, you can add it like so:

public Configuration()
{
    var mailConverter = new LambdaValueConverter<MailAddress>(val => new MailAddress(val));
    var options = new StronkOptions();
    options.Add(mailConverter);

    this.FromAppConfig(options);
}

You can also replace (or supplement):

  • How it detects which properties to populate
  • How to populate a property
  • How to pick a value from the configuration source for a given property
  • How to convert a value for a property
  • Where configuration is read from

A few features to come soon:

  • Additional types supported “out of the box” (such as TimeSpan and DateTime)
  • Exception policy controlling:
    • What happens on not being able to find a value in the configuration source
    • What happens on not being able to find a converter
    • What happens on a converter throwing an exception

I hope you find it useful. Stronk’s Source is available on Github, and contributions are welcome :)

code, net, strongtyping, configuration, stronk

---