Tag Archives: Configuration

Manually Creating a Test Harness in .Net

Let me start by saying that this post isn’t intended to try to replace Selenium, or Cypress, or whatever UI testing tools you may choose to use. In fact, it’s something that I did for manual testing, although it’s not difficult to imagine introducing some minor automation.

The Problem

Imagine that you have a solution that requires some data – perhaps it requires a lot of data, because you’re testing some specific performance issue, or perhaps you just want to see what the screen looks like when you have a lot of data. Let’s also imagine that you’re repeatedly running your project for one reason or another, and adding data, or whatever.

My idea here was that I could create a C# application that scripts this process, but because it’s an internal application, I could give it access to the data layer directly.

The Solution

Basically, the solution to this (and to many things) was a console app. Let’s take a solution that implements a very basic service / repository pattern:

From this, we can see that we have a pretty standard layout, and essentially, what we’re trying to do is insert some data into the database. It’s a bonus if we can add some test coverage while we’re at it (manual test coverage is still test coverage – it just doesn’t show up on your stats). So, if you’re using a REST type pattern, you might want to use the controller endpoints to add the data; but for my purpose, I’m just going to add the data directly into the data access layer.

Let’s see what the console app looks like:

        static async Task Main(string[] args)
        {
            IConfiguration configuration = new ConfigurationBuilder()
                  .AddJsonFile("appsettings.json", true, true)
                  .Build();

            // Ensure the DB is populated
            var dataAccess = new TestDataAccess(configuration.GetConnectionString("ConnectionString"));
            if (dataAccess.GetDataCount() == 0)
            {
                var data = new List<MyData>();

	     // Generate 100 items of data
                for (int j = 0; j <= 100; j++)
                {
		var dataItem = CreateTestItem();
                      data.Add(dataItem);
                }
                dataAccess.AddDataRange(data);
            }

            // Launch the site            
            await RunCommand("dotnet", "build");
            await RunCommand("dotnet", "run", 5);

            System.Diagnostics.Process.Start(@"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", @"https://localhost:5001");
        }

Okay, so let’s break this down: there’s essentially three sections to this: configuration, adding the data, and running the app.

Configuration

We’ll start with the configuration:

       IConfiguration configuration = new ConfigurationBuilder()
                  .AddJsonFile("appsettings.json", true, true)
                  .Build();

        // Ensure the DB is populated
        var dataAccess = new TestDataAccess(configuration.GetConnectionString("ConnectionString"));

Because we’re using a console app, we’ll need to get the configuration; you could copy the appsettings.json, but my suggestion would be to add a link; that is, add an existing item, and select that item from the main project, then choose to “Add As Link” (this is not a new feature):

This means that you’ll be able to change the config file, and it will be reflected in the test harness.

Creating the data

There’s not too much point in me covering what’s behind TestDataAccess – suffice to say that it encapsulates the data access layer; which, as a minimum, requires the connection string.

It’s also worth pointing out that we check whether there is any data there before running it. Depending on your specific use-case, you may choose to remove this.

Building, running, and launching the app

Okay, so we’ve now added our data, we now want to build the main application – thanks to the command line capabilities of .Net Core, this is much simpler than it was when we used to have to try and wrangle with MSBuild!

    // Launch the site            
    await RunCommand("dotnet", "build");
    await RunCommand("dotnet", "run", 5);

    await RunCommand(@"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", @"https://localhost:5001");

RunCommand probably needs a little more attention, but before we look at that, let’s think about what we’re trying to do:

1. Build the application
2. When the application has built, run the application
3. Once the application is running, navigate to the site

RunCommand looks like this:

        private static async Task RunCommand(string command, string? args = null, int? waitSecs = -1)
        {
            Console.WriteLine($"Executing command: {command} (args: {args})");

            Process proc = new System.Diagnostics.Process();
            proc.StartInfo.WorkingDirectory = @"..\..\..\..\MyApp.App";
            proc.StartInfo.FileName = command;
            proc.StartInfo.Arguments = args ?? string.Empty;

            proc.Start();

            if ((waitSecs ?? -1) == -1)
            {
                proc.WaitForExit();
            }
            else
            {
                if (waitSecs! == 0) return;
                await Task.Delay(waitSecs!.Value * 1000);
            }
        }

“But this looks inordinately complicated for a simple wrapper for running a process!” I hear you say.

It is a bit, but the essence is this: when running the build command, we need to wait for it to complete, when running the run command, we can’t wait for it to complete, because it never will; but we do need to move to the next thing; and when we launch the site, we don’t really care whether it waits or not after that.

Summary

I appreciate that some of you may be regretting spending the time reading through this, as all I’ve essentially done is script some data creation and run an application; but I imagine there are some people out there, like me, that want to see (visually) what their app looks like with different data shapes.

Configuration and Dependency Injection

In this post, I wrote about how to mock out the configuration for an application. What I did not cover in that post was whether it was a good idea to pass around IConfiguration. The answer is that, at least in my opinion, it’s a very bad idea.

In this post, I’d like to discuss why I think it’s a bad idea, and my take on a better idea.

Single Responsibility

The first reason is that you are, essentially, breaking the principle of single responsibility. Let’s imagine that we have a class that accepts an IConfiguration as a parameter. When you need an element from the configuration, you have to issue a command like this:

var myValue = new _configuration.GetValue<string>("MyValue");

So, what’s wrong with this? It’s not exactly complex code, and it’s intent is clear. However, your method is now doing two things: it’s doing what it was intended to do, and it’s reading from the configuration. If MyValue changes (say you want to call it “MyNewValue”) then you have to change your method – but your method should not care where, or how this value is retrieved! Let’s say my full class is this:

public class CalculateTemperature 
{
    private IConfiguration _configuration;
    public CalculateTemperature(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public bool IsFreezing(double temperature)
    {
        string scale = _configuration.GetValue<string>("TempScale");
        switch (scale)
        {
            case "Fahrenheit":
                return temperature == 32;

            case "Centigrade":
                return temperature == 0;

            case "Kelvin":
                return temperature == 273;

        }
    }
}

Okay, so I have a class, and a method – the class is responsible for temperature calculations, and the method for telling me if a given temperature is the freezing point of water. However, the IsFreezing method also gets a setting from the configuration file. What this means is that the method above already has a potential bug: what if the setting is not present, or it’s set to some other temperature scale, “Celcius” for example; so you now end up with a method that looks like this:

    public bool IsFreezing(double temperature)
    {
        string scale = _configuration.GetValue<string>("TempScale");
        switch (scale)
        {
            case "Fahrenheit":
                return temperature == 32;

            case "Centigrade":
            case "Celcius":
                return temperature == 0;

            case "Kelvin":
                return temperature == 273;

            case default:
                throw new Exception($"Temperature scale is unsupported");
        }
    }

Buy why should this method have to deal with what’s in the configuration file? A better implementation of this method would be something like this:

    public bool IsFreezing(double temperature, Scale scale)
    {
        switch (scale)
        {
            case Scale.Fahrenheit:
                return temperature == 32;

            case Scale.Centigrade:
                return temperature == 0;

            case Scale.Kelvin:
                return temperature == 273;
        }
    }

Now I can create a config full of ANSI art for all this method cares; and as a result, I can get rid of IConfiguration out of the class.

Testing

The second reason, as I think I implied, is that it is not straight-forward to mock out the IConfiguration class. That fact that I created a blog post on the subject means that it needs one (at least for me), which means it’s far too much hassle; which means that classes and methods that contain this are less likely to be tested.

The Real World

The example I’ve given above isn’t a very realistic example, and I’m sure that no-one reading this would create a method that read from the config for a setting that so clearly relates to the method; however, the following is a very common thing, and I’m sure that you have written something akin to this, somewhere (I know I have):

public class TemperatureRepository
{
    private IConfiguration _configuration;
    public CalculateTemperature(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public bool WasFreezingLastWeek(DateTime dateTime)
    {
        string connectionString = _configuration.GetValue<string>("ConnectionString");

        . . . 
    }
}

The exact same argument applies to this, as did for the method above, but this doesn’t feel so wrong. The reason is that you know what the Startup.cs call looks like when your class looks like this:

public class TemperatureRepository
{
    private string _connectionString;
    public CalculateTemperature(string connectionString)
    {
        _connectionString = connectionString;
    }

    public bool WasFreezingLastWeek(DateTime dateTime)
    {
        . . . 
    }
}

You either need to create the class before you inject it, or do something like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<ITemperatureRepository>(srv => 
    {        
          new  TemperatureRepository(Configuration.GetValue<string>("ConnectionString"));
    });
}

In fact, I don’t think this looks too bad but, recently, I’ve been using a slightly different approach, which allows you to avoid this: that is to register a class that contains your config. If you have three or four values, then maybe have one config class for your entire application; if there’s more then have as many as make sense:

public void ConfigureServices(IServiceCollection services)
{
    var configClass = new ConfigClass()
    {
        ConnectionString = Configuration.GetValue<string>("ConnectionString");
    };

    services.AddScoped<ConfigClass>(configClass);
    services.AddScoped<ITemperatureRepository>();
}

Summary

I’m not sure this warranted such a long blog post, but it’s a Saturday afternoon and the pubs are closed!

Caveat

None of the code in this post has been tested – it’s all been written in OneNote – I didn’t think the specific code syntax was particularly relevant, given it’s more of an opinion post.

Using Kudu to Edit a Deployed app.settings file

When you deploy an Azure App Service, there are occasions when you may need to change the running values. Exactly how you may do this depends heavily on how the service was deployed, and how you are managing your variables. You can typically overwrite variables inside the app service; however, the running appsettings.json and web.config will be deployed with the app, and you can edit these directly (whether you should or not is a different question).

It’s your foot

These instructions let you change the deployed files on your App Service. Doing so may result in the behaviour of the site changing.

On with the show

Launch Kudu

When you select this, you’ll be given the option to select “Go”, or … not. Select “Go”.

This will take you to the Kudu console.

From here, select “CMD”; this will take you to a hybrid screen with a command console and a file navigator:

Navigate to d:\home\site\wwwroot:

Too Many Files

Initially, you may get the following error:

There are n items in this directory, but maxViewItems is set to 99. You can increase maxViewItems by setting it to a larger value in localStorage.

To get around this, select F12 and in the console window type:

window.localStorage['maxViewItems'] = 1000

After you’ve changed this, refresh the page (F5).

App Settings

To change the variables, you’ll need to locate the appsettings.json in the list (it’s alpha-numerically sorted, so it should be near the top). (Unfortunately, you can’t edit this from the command line).

When you find the file, click the edit button:

And then change the file:

When done, select Save and then restart the app service.

References

https://www.poppastring.com/blog/kudu-error-with-maxviewitems-in-localstorage