Does it even exist if it isn’t in source control?

I was working on a little side project at work to make my employer’s data backup processes a bit more robust which involved writing a small console utility. I was asked if the code for the utility was already in source control (this code represented about 10 hours of effort on my part), and I almost replied “Does it even exist if it isn’t in source control?” Instead, of course, I simply sent the link to the repo where the code lives.

This made me start thinking about what really goes into a project, small or large. How many small little side projects have I started, and abandoned within a few hours simply because whatever I was working on wasn’t interesting enough to hold my interest? Would it be logical to start every side project by setting up source control?

At the end of the day I think there is a real judgement call that has to be made about what is appropriate to set up a repository for and what can just live (and likely die) on your local disks. When learning new technologies I generally work through a few different types of “Hello World” type applications that are very simple and then I’ll work through a tutorial or two that is a bit more advanced. Generally the bulk of the code for those things is heavily derived from whatever resource I’m using, so there is minimal to no benefit to putting it in source control. As soon as you move beyond the tutorials: enter source control, stage left.

Modern day software professionals have no excuse not to use source control. Github has free public repositories (and at $7/mo, most folks in software can afford the expense), Bitbucket has free public and private repositories, and those are only the two options that I have used extensively. If you don’t trust anyone else with your code, standing up your own git instance on a VPS is possible as well.

If you really don’t like git for some reason (I’d highly encourage you to learn it though), there are plenty of other options:
1. Bitbucket offers mercurial hosting
2. Fossil SCM (with hosting available here) – note I’ve never used Fossil, but I’ve heard many good things about it
3. If you want to kick it old school, there are plenty of SVN hosting options available as well

In the end, the adage “Does it even exist if it isn’t in source control” rings true. There are so many different options suitable for just about any skill level and personal preference and cost bracket that there are no excuses to no simply use source control.

VPS Migration to GCP

I’ve had all of the blogs that I manage on several VPSs hosted through RamNode for the past couple of years. While there is nothing wrong with RamNode, I figured it was about time to try out something new. I originally was going to move to AWS, since their MySQL RDS offering looked pretty compelling, but then I discovered Google pretty much had feature parity with the parts of AWS I was interested in (plus they have a much nicer value proposition than AWS does for hosting costs).

Out With the Old

In order to keep things reasonably fast, I ran 4 separate VMs: web1, web2, db1, and cache1. The initial idea was that web1 and web2 would be replicas of each other and cache1 (which ran Varnish) would be responsible for balancing load. I never got around to any of that, instead I have web1 (which had about 90% of the traffic) and web2 as completely independent machines. Both talked to cache1, which was running varnish and acted as the public entry point to the blogs. Db1 was just a database server, running some recentish version of MariaDB. Also, in order to help secure the database server, all of the VMs ran OpenVPN so that all internal communication was happening in a private network.

Unfortunately, this was probably a bit over-engineered for the amount of traffic that the blogs actually get in aggregate (under 200k uniques/month), plus it was a maintenance nightmare since I needed to watch over 4 separate servers (but it was a fun learning experience).

In With the New

Now that I have moved to Google Compute Engine, I just have 1 moderately beefy VM running which hosts all of the blogs. Instead of running a dedicated VM (which I would have to administrate), I’m using Google’s Cloud SQL MySQL offering (a dbn1-standard-1 instance). Eventually all of the images will be moved to Google Cloud Storage (this is one area where AWS is light years ahead of Google), in order for that work I need the Google sponsored wordpress plugin to actually work properly.

Future Plans

The reason that I wanted to migrate to either AWS or Google is in order to support future growth. While volume is moderately low right now, it is to be hoped that eventually one or more of the blogs being hosted will have considerable amounts of traffic. If that happens being able to reconfigure a few things in order to support GCP’s load balancing will be critical. The only thing preventing me from setting that up right now is that I will need an SSL certificate which can terminate all of the blogs I manage, which would be a bit expensive (especially since I currently just use LetsEncrypt for all my certificates).

Overall we’ll have to see if this ends up being more reliable and at least as fast as what I previously had configured. I have enough CPU and memory budget where I can probably implement a caching strategy again if the performance isn’t quite where it needs to be (or I’ll just end up setting up a second VM in order to handle all of the caching duties). I’m still running everything through CloudFlare, so that makes sizing everything much more forgiving.

XUnit Test Lifecycles

You are unit testing right? I hope so. If you are you may have run into some scenarios where things are not working quite right. One issue I’ve personally run into is things which attempt to maintain state between tests (eww, I know). Unfortunately, while it is good practice to make sure all of the tests you are writing are completely independent from each other, sometimes shared state will creep in due to other factors (like using an in-memory database because Microsoft kills kittens* and didn’t make Entity Framework easy to mock out).

XUnit Test Context

How many times does a constructor get called for a class in C#? If you answered one, you’d be completely wrong when it comes to XUnit (it kind of surprised me too when I first learned about it). Turns out that as part of the XUnit lifecycle the constructor is called before each test is run, likewise you can implement IDisposable and have Dispose() called after each test is run. While it runs kind of counter to expectations, no state set in any instance variables will be shared between any tests. If you need the ability to share state XUnit provides not one, but two separate options: 1) Class Fixtures and 2) Collection Fixtures. The choice of which to use is entirely dependent upon the scope of what needs to share state. As you’ll see below by default a class is by default a collection although you can also build collections composed of the tests of multiple classes.

Class Fixtures

In order to create a class fixture a small amount of setup needs to be done: a new class needs to be created which will maintain the shared state across all runs of all tests that are part of the class. The test in question needs to implement IClassFixture<YourFixtureName> and your fixture will be passed in as a constructor argument.

An example fixture might be something like:

public class MyFixture{
   private MySuperObject _myInstanceVar;
   public MyFixture(){
       _myInstanceVar = new MySuperObject();
   }

while consuming the fixture would look like this:

public class FixtureTests : IClassFixture<MyFixture>
{
    private MyFixture _fixture;
    public FixtureTests(MyFixture <span class="hiddenGrammarError" pre=""><span class="hiddenGrammarError" pre=""><span class="hiddenGrammarError" pre="">fixture)
    {
         _fixture</span></span></span> = fixture;
    }
}

From a test writers perspective the Fixture mechanism almost looks like a dependency injection engine (except with absolutely zero magic in it).

Collection Fixtures

Collection fixtures operate pretty similarly to class fixtures, although they do require a slightly larger amount of setup. In order to setup a collection fixture, much like a class fixture, you must first define the actual fixture. The wiring logic is a bit different:
First define a collection:

[CollectionDefinition("Awesome Collection")]
public class MyCollection : ICollectionFixture<MyFixture>
{
    // Intentionally left empty. 
}

The actual test class would look like the below:

[Collection("Awesome Collection")]
public class MemberOfMyCollectionTests
{
    private MyFixture _fixture;
    public FixtureTests(MyFixture fixture)
    {
         _fixture = fixture;
    }
}

Note on best practice: it is probably almost always best to pull the collection name out to a constants file to prevent simple typos from dramatically changing the behavior of your tests. But I’m in favor of just using constants everywhere unless there is a compelling reason not to…
Second note: the fixtures must all be in the same assembly. XUnit doesn’t let us get fancy with collection definitions spanning multiple assemblies (not that there would be any big benefit from that)

Fixture Lifetimes

For either of the possible fixture types the lifetime logic is basically the same: the fixture is created immediately prior to the first invocation of the first test in the collection (be it a class-collection or a collection-collection). The fixture is destroyed immediately after the last test in the collection.

XUnit Test Collections

The lifecycle and parallelization of tests is largely driven by the concept of Test Collections. The official documentation does a good job of giving a quick overview. To summarize: by default all tests in a given class are part of the same collection thus will run in a serial fashion. Classes in the same assembly will run their collections in parallel. This behavior is able to customized by specifying a couple of assembly level attributes:

  1. Forces all tests in all classes to be in a single collection – i.e. force serial execution of all tests in the assembly.
    [assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
  2. Determines the maximum parallelization of tests. Setting this to 1 only allows one test to execute at a time, although multiple tests may be executed in an interleaved fashion. By default this is equal to the number of virtual CPUs on the PC (which seems to be a good default unless you have some very specific use-cases).
    [assembly: CollectionBehavior(MaxParallelThreads = n)]
  3. Disables test paralleization assembly-wide. Note that this is different than MaxParallelThreads since it actually turns off the parallelization infrastructure in xunit (for the assembly this attribute decorates)
    [assembly: CollectionBehavior(DisableTestParallelization = true)]


*Just kidding. No kittens were harmed in the writing of this post.