This site works best in modern browsers. Looks like you're using an old one, you should upgrade if you can.

Testing That Your Public APIs Have Not Changed Unexpectedly with PublicApiGenerator and Approval Tests

We can write automated tests to cover various aspects of the code we write. We can write unit/integration tests that test that the code is producing the expected outcomes. We can use ConventionTests to ensure internal code quality, for example that classes following a specified naming convention and exists in the correct namespace. We may even add the ability to create a business readable tests using tools such as SpecFlow or BDDfy.

Another aspect that we might want to ensure doesn’t change unexpectedly is the public API that our code exposes to callers.

Using PublicApiGenerator to Generate a Report of our Public API

The first step of ensuring our public API hasn’t changed is to be able to capture the public API in a readable way. The PublicApiGenerator NuGet package (from Jake Ginnivan) gives us this ability.

Suppose we have the following class defined:

public class Calculator
{
    public Calculator()
    {
        CurrentValue = 0;
    }

    public int CurrentValue { get; private set; }

    public void Clear()
    {
        CurrentValue = 0;
    }

    public void Add(int number)
    {
        CurrentValue += number;
    }
}

Notice here that this code defines the public API that consumers of the Calculator class can use. It’s this public API that we want to test to ensure it doesn’t change unexpectedly.

We might start with some unit tests as shown in the following code:

public class CalculatorTests
{
    [Fact]
    public void ShouldHaveInitialValue()
    {
        var sut = new Calculator();

        Assert.Equal(0, sut.CurrentValue);
    }

    [Fact]
    public void ShouldAdd()
    {
        var sut = new Calculator();

        sut.Add(1);

        Assert.Equal(1, sut.CurrentValue);
    }
}

These tests help us ensure the code is doing the right thing but do not offer any protection against the public API changing. We can now add a new test that uses PublicApiGenerator to generate a string “report” detailing the public members of our API. The following test code shows this in use:

[Fact]
public void ShouldHaveCorrectPublicApi()
{
    var sut = new Calculator();

    // Get the assembly that we want to generate the public API report for
    Assembly calculatorAssembly = sut.GetType().Assembly;

    // Use PublicApiGenerator to generate the API report
    string apiString = PublicApiGenerator.PublicApiGenerator.GetPublicApi(calculatorAssembly);

    // TODO: assert API has not changed
}

If we debug this test and look at the content of the apiString variable we’d see the following text:

[assembly: System.Runtime.InteropServices.ComVisibleAttribute(false)]
[assembly: System.Runtime.InteropServices.GuidAttribute("c2dc3732-a4a5-4baa-b4df-90f40aad1c6a")]
[assembly: System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5.1", FrameworkDisplayName=".NET Framework 4.5.1")]

namespace Demo
{
    
    public class Calculator
    {
        public Calculator() { }
        public int CurrentValue { get; }
        public void Add(int number) { }
        public void Clear() { }
    }
}

Using Approval Tests to Assert the API Is Correct

Now in our test we have a string that represents the public API. We can combine PublicApiGenerator with the Approval Tests library to check that this API text doesn’t change.

First off we go and install the Approval Tests NuGet Package. We can then modify the test as shown below:

public class CalculatorApiTests
{
    [Fact]
    public void ShouldHaveCorrectPublicApi()
    {
        var sut = new Calculator();

        // Get the assembly that we want to generate the public API report for
        Assembly calculatorAssembly = sut.GetType().Assembly;

        // Use PublicApiGenerator to generate the API report
        string apiString = PublicApiGenerator.PublicApiGenerator.GetPublicApi(calculatorAssembly);

        // Use Approval Tests to verify the API hasn't changed
        Approvals.Verify(apiString);
    }
}

The first time we run this it will fail with a message such as “Failed Approval: Approval File "c:\…\Demo.Tests\CalculatorApiTests.ShouldHaveCorrectPublicApi.approved.txt" Not Found”. It will also generate a file called CalculatorApiTests.ShouldHaveCorrectPublicApi.received.txt. We can rename this to CalculatorApiTests.ShouldHaveCorrectPublicApi.approved.txt, run the test again and it will pass.

If we now modify the public API by changing a method signature (e.g. to public void Clear(int someParam)) and run the test again it will fail with a message such as “Received file c:\...\Demo.Tests\CalculatorApiTests.ShouldHaveCorrectPublicApi.received.txt does not match approved file c:\...\Demo.Tests\CalculatorApiTests.ShouldHaveCorrectPublicApi.approved.txt”.

Modifying the test and adding an Approval Tests reporter attribute ([UseReporter(typeof(DiffReporter))]) and running the test will now gives us a visual diff identifying the changes to the public API as shown in the following screenshot.

Approval Tests Diff Screenshot

To learn more about the features of Approval Tests, check out my Approval Tests for .NET Pluralsight course.

3 Tools for Choosing and Working with Color in Apps, Websites, and Print

When developing apps, websites, or even presentations for your team or management it can be difficult to come up with a working color scheme.

Below are three useful tools that can be of help.

Adobe Color CC (formerly Adobe Kuler)

Adobe Color CC Screenshot showing color wheel

Adobe Color CC is a classic color scheme designer based around the concept of the color wheel. You can choose a starting color and then one of the standard color schemes from color theory (complimentary, triadic, etc). This then gives you you the related colors based on the chosen color scheme.

For each color you can get the RGB, HEX, CMYK, LAB, and HSB values to use in whatever application your working on.

You can also explore a range of pre-built palettes created and shared by other users.

Paletton

paletton screenshot

Paletton is another tool based around the concept of the color wheel that offers a choice of color schemes. You can also use its “vision simulator” to simulate what the colors might look like to users with some kind of vision impairment.

The following image shows the same color sheme with no vision simulator (left) and protanopia – a form of color blindness (right).

paletton screenshot simulating color blindness

 

Multicolr

multicolr screenshot

Multicolr is an interesting tool that can help find images that match one or more colors. If you need to find images matching a set of colors this can be useful. To use Multicolr you start by selecting from one to five colors, in the preceding screenshot I have a chose a purple and white. The images come from flickr and you can select and image from the search results and view the original.

Winning in 2016

As the year 2015 starts its last slide into 2016, it’s the time of year that I start to think about what my 3 Wins are going to be for next year.

If you’re not familiar with the 3 Wins concept, it’s similar to goal setting but rather than focus on “what will I tick off my todo list” it’s more along the lines of “what will make me feel great, like I’ve accomplished something, like I’ve made progress…”. One way to help come up with three wins is to imagine how your future self will feel when you look back on the year and have accomplished all your 3 Wins.

It’s important to make your 3 Wins achievable, otherwise not achieving any of them could be disheartening and demotivating.

One technique to guide you, while being sounding very “managementy”, is the concept of SMART criteria.

SMART is an acronym that stands for:

  • Specific
  • Measurable
  • Attainable
  • Realistic
  • Time-related (or Time-bound)

Using SMART may help if you are struggling to create your own 3 Wins.

You might have 3 Wins for your work/career and you may also have 3 Wins for personal/health/family/etc. related things. Also you can use 3 Wins daily, weekly, monthly, quarterly, or at any scale you wish; you could even have decade or lifetime 3 Wins.

Testing Akka.NET Actor Systems

My new Pluralsight course Akka.NET Testing Fundamentals is now available.

Testing actor system brings a number of additional considerations over and above the concepts of traditional object oriented unit/integration testing.

While some additional testing support is required, for example as provided by Akka.NET’s TestKit, concepts such as “unit” and “integration” do translate to the testing of actors. For example a “unit” test becomes a test of the behaviour of a single actor in isolation and an “integration” test may involve multiple actors being testing together.

Just as with traditional OO testing where object dependencies can be mocked, so to with actor tests. For example, TestKit provides a number of pre-built mock actors that can be used if the actor(s) being tested need to be isolated. The simplest of these pre-built mock actors is the BlackHoleActor that will simply and silently accept any message sent to it and “swallow” the message. The EchoActor is another pre-built mock actor that will echo any message sent to it back into the test actor system instance as well as optionally back to the sending actor. The TestProbe pre-built mock actor is a more generalised mock actor and can be used in a number of useful ways.

To get access to the benefits of the actor testing infrastructure, the test class inherits from the TestKit base class. By doing this we get access to an automatically created actor system instance into which we can instantiate the actor(s) that need testing.

When testing an actor, it can be treated as a black or white box. A black box test would involve sending a message to the actor and examining (and asserting on) response message(s). Utilising TestKit we can also write white box actor tests where we can get access to the “internal” actor state directly and make asserts on this internal state.

If you’re new to the Actor Model or Akka.NET, check out the docs or my introductory Pluralsight course: Building Concurrent Applications with the Actor Model in Akka.NET.

Painless .NET Windows Service Creation with Topshelf

Windows Services allow us to run code in the background, without needing (for example) a console application running continually. Windows Services can run as various system users or specific local/domain users.

To see what Windows Services are installed on your (Win 8+) PC, hit Win+x then hit G. In the Computer Management window that opens, click the Services option under Services and Applications as shown in the following screenshot.

Computer Management window showing installed Windows Services

As the preceding screenshot shows, a Service has a (Display) Name, a Description, a Status (e.g. Running or not), a Startup Type (Manual, Automatic, Disabled, etc), and a Log On As that specifies in which user context the Service executes.

We can create Windows Services to run arbitrary .NET code such as:

  • Self-hosted web server using Owin
  • File system watcher and batch processing (e.g. image file conversion, video encoding)
  • Host remote Akka.NET actor system (such as in my Pluralsight course)
  • Process messages from a message queue as they arrive (e.g. MSMQ)
  • Mail, FTP, etc. servers
  • Integration/gateway, e.g. receive data from external systems

Using Topshelf

Topshelf is an open source project that greatly simplifies the creation of Windows Services.

The overview of creating a Service using Topshelf is:

  1. Create a Console application project in Visual Studio
  2. Add the Topshelf NuGet package
  3. Create a class to represent your service logic
  4. Configure your Service using the Topshelf API
  5. Build your Console application
  6. Execute your Console application passing Topshelf parameters to install/uninstall your Service

 

So assuming we have a new Console project called “Time” and the following NuGet packages are installed:

<packages>
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.Owin" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net451" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net451" />
  <package id="Owin" version="1.0" targetFramework="net451" />
  <package id="Topshelf" version="3.2.0" targetFramework="net451" />
</packages>

We can create a self-hosted OWIN service that tells us the time.

First off we create an API Controller to return the time and then create an OWIN startup configuration class:

public class TimeController : ApiController
{
    [HttpGet]
    public string Now()
    {
        return DateTime.Now.ToLongTimeString();
    }
}

public class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        var config = new HttpConfiguration();

        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{time}");
        config.Formatters.Remove(config.Formatters.XmlFormatter);
        config.Formatters.Add(config.Formatters.JsonFormatter);

        appBuilder.UseWebApi(config);
    }
}

Next we create a class that represents our Topshelf Windows Service:

class TimeService
{
    private IDisposable _webServer;

    public void Start()
    {
        // code that runs when the Windows Service starts up
        _webServer = WebApp.Start<Startup>("http://localhost:8084");
    }

    public void Stop()
    {
        // code that runs when the Windows Service stops
        _webServer.Dispose();
    }
}

Now in the Console applications main method we can use Topshelf’s HostFactory to configure what our Windows Service will do (via the TimeService class) and how it will be configured in Windows:

class Program
{
    static void Main(string[] args)
    {
        HostFactory.Run(
            configuration =>
            {
                configuration.Service<TimeService>(
                    service =>
                    {
                        service.ConstructUsing(x => new TimeService());
                        service.WhenStarted(x => x.Start());
                        service.WhenStopped(x => x.Stop());
                    });

                configuration.RunAsLocalSystem();

                configuration.SetServiceName("ASimpleService");
                configuration.SetDisplayName("A Simple Service");
                configuration.SetDescription("Don't Code Tired Demo");
            });
    }
}

Once the solution is built, navigate to the bin/debug directory in a admin command prompt and type:

time.exe install

This will install the Service into Windows as the following screenshots show.

command prompt showing Topshelf service installation

 

Service installed in Windows

 

In the command prompt window type:

time.exe start

This will start our new service.

Now in a browser, navigate to http://localhost:8084/api/time/now and you’ll see the current time come back as JSON

screenshot showing browser getting time

about jason

My Bio Photo

Jason Roberts is a Journeyman Software Developer, Microsoft MVP, writer, Pluralsight author, open source contributor and Windows Phone & Windows Store app author.

He holds a Bachelor of Science in computing and is an amateur music producer and landscape photographer.

MVP Logo

Pluralsight Author Badge

Sign up for the Don't Code Tired Newsletter

Disclaimer
The opinions expressed herein represent my personal opinions and do not represent my employer's views in any way.

© Copyright 2016, Jason Roberts