Daily Archives

One Article

Visual Studio Tips

Use Tasks for Easy Test Filtering in VS Code

Posted by matteskolin on

Automated tests should be discoverable and easy to run. In this post, I will show a way to make it easier to run tests in VSCode using Tasks. I will use the XUnit testing framework to run test against a .NET Core console application.

The full source code for this project can be found Here.

The Project that will be tested

I created a class with three methods. The AddInts and the SubtractInts methods are simple methods that contain logic that is unit testable.

The third method UpdateDatabaes() is a method that, because it updates a databaes and is therefore dependent on an system external to to the method, is a good candidate for an integration tests. Integration tests are tests that test the interaction among discrete components of a system, whereas unit tests are best used to test the behavior of a single method.

public class Foo
{
    public static int AddInts(int a, int b)
    {
        return a + b;
    }

    public static int SubtractInts(int a, int b)
    {
        return a - b;
    }

    public static bool UpdateDatabase()
    {
        //Example of an integration test that interacts with a database

        //Add Code here to update a database 

        return true;

    }
}

The Tests

I have created one class for integration tests and one class for unit tests. The Xunit TraitAttribute can be used on classes to assign a property to the test. This test metadata is used when we run the test to filter the tests by the Trait value, in this case either the Integration or Unit categories.

This way, we can seperate the execution of our unit and integration tests into seperate commands. This is important because we want to be able to run our unit tests frequently and quickly in order to detect new bugs early, and to not be spending too much time waiting around for the tests to run.

Integration tests, on the other hand, tend to be slower, especially since they may require the entire app to be loaded into memory, databases to be started and populated, networks to be setup, etc. Because of this, having the option to run integration tests seperately from the unit tests is helpful.

We will accomplish this by using the .NET CLI and the –filter flag. We will then make things even easier for us by using the VSCode tasks system, and optionally the Task Runner extension, to make running the filtered tests into a single click.

    [Trait("Category","Integration")]
    public class IntegrationTests 
    {
        [Fact]
        public void UpdateDatabaseTest()
        {
            //Arrange //Act
            var result = Foo.UpdateDatabase();

            Assert.True(result);
        }

    }

    [Trait("Category","Unit")]
    public class UnitTests 
    {
        [Fact]
        public void AddIntsTest()
        {
            var result = Foo.AddInts(3,1);
            Assert.Equal(4,result);
        }

        [Fact]
        public void SubtractIntsTest()
        {
            var result = Foo.SubtractInts(1,-3);
            Assert.Equal(4,result);
        }

        [Fact]
        public void SubtractInts2Test()
        {
            var result = Foo.SubtractInts(1,0);
            Assert.Equal(1,result);
        }
    }


Create the tasks.json

I have added two tasks labeled “Run Unit Tests”, and “Run Integration Tests” to my /.vscode/tasks.json file. For more information about VSCode tasks, checkout the microsoft docs here.

These tasks call the .NET CLI dotnet test command with the filter argument which itself takes a filter expression in which we can use the traits we defined earlier in our test code.

The –no-build flag is optional as you may want to build your project before executing the tests, but I like to only build the project when truly necessary, and don’t mind running a seperate build command before running my tests on updated code.

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Run Unit Tests",
            "command": "dotnet",
            "type": "process",
            "args": [
                "test",
                "--filter",
                "Category=Unit",
                "--no-build"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "Run Integration Tests",
            "command": "dotnet",
            "type": "process",
            "args": [
                "test",
                "--filter",
                "Category=Integration",
                "--no-build"
            ],
            "problemMatcher": "$msCompile"
        }
    ]
}

Running The Tests

There a couple options for how to run the tasks..

1) Use the comand palette

Press CONTROL + SHIFT + P to open the command palette. Select “Tasks: Run Task”. All of the tasks you have defined in tasks.json above should appear in this list. Select the desired tasks and press enter.







2) Use the Task Runner extension.

I reall like this task runner extension which displays a list of available tasks in the explorer window. Mine looks like this.. When I want to run my Unit Tests, I just click the button. I don’t need to type anything in the command line or fumble through the command palette