Ken Muse

How to Test a .NET Package


This is a post in the series Governance in dotnet with NuGet Packages. The posts in this series include:

It’s one thing to create a package to support your own projects, but how do you make sure it works correctly? As developers, we’re often used to testing and maintaining source code for our products. The truth is, any source code – including templates or packages – should be maintained and tested. Over the last few articles, you’ve seen how to create a package to distribute a ZIP task. Now, let’s see how it can be tested.

To create a testing solution, we need to think about how the project should be expected to be used. In this case, we expect that any .NET project that adds our package will be able to automatically generate a ZIP file. That means that a basic test flow might look like this:

  • Build the package
  • Create a new .NET project
  • Add the package to the project
  • Publish the project
  • Test that the ZIP file was created

Thankfully, this can all be done on the command line.

Build the package

We’ll start by building the package being tested, writing it to a folder. In this case, I’ll assume that the package will be tested in Actions. We’ll build the package and write it to a folder in the runner’s temporary directory. We’ll use the package from the last post.

1dotnet pack --output ${{ runner.temp }}/package ZipPackage.csproj

That command will create the folder then place the package in it. Now that we have the package built, time to test it!

Creating a project for testing

To create a project for testing the package, we can use dotnet new to create a project from a template. It supports a variety of command line options, allowing you to pass in parameters for the template and avoid the interactive prompts. In this case, we want to create a new web API project with no authentication, using controllers, and using the program main style. The command looks like this:

1dotnet new webapi --auth None --use-controllers --use-program-main --language C# --name testproject

You’ll notice that I also defined a project name. You can take advantage of that to provide a unique project name. This would allow multiple tests to run in parallel without contention.

Add the package to the project

This step will take advantage of the fact that a folder with NuGet packages can be treated as a package source feed. To do that, we’ll need to run a few commands in the testproject folder. First, create a nuget.config in the project folder. This allows us to define and manage the package sources for this project rather than defining/managing the sources globally. This is important if you choose to run multiple tests in parallel.

1cd testproject
2dotnet new nugetconfig

Now, register the folder with the package as a feed. We’ll name the feed local. If you wanted to support parallel tests, you could dynamically generate a unique name for the folder.

1dotnet nuget add source --name local ${{ runner.temp }}/package

At this point, we’re ready to add the package to the project:

1dotnet add package Muse.ZipPackage

NuGet will check the available feeds, looking for this package. Once it finds the package in one of the feed sources it will install it.

Publish and test the project

For this test, we’ll verify that the project will create a ZIP file automatically when the project is published using this command:

1dotnet publish /p:PackageDir=${{ runner.temp }}/publish

This command will restore, build, and publish the testproject to the publish folder in the runner’s temporary directory. If everything worked correctly, you should see a ZIP file in the publish folder. We can validate that with bash:

1if [ !e "$RUNNER_TEMP/publish/publish.zip" ]; then
2  echo "ZIP file not found" 1>&2
3  exit 1
4fi

This writes a message to stderr and exits with a failure code (1) if the file is not found. If the file is found, then the test will pass and exit with a success code (0). If you prefer to test in PowerShell, the equivalent would be:

1if (!(Test-Path "$RUNNER_TEMP/publish/publish.zip")) {
2  Write-Error "ZIP file not found"
3  exit 1
4}

Alternatively, you could use throw to raise an error and fail the test.

Next steps

At this point, you have successfully confirmed that the the custom package will create the ZIP file as expected. You’re now a step closer to a reliable delivery. As next steps, you might consider adding a few more tests to validate the package:

  • ZIP contains the expected files
  • Calling dotnet clean removes the ZIP file
  • The Web API project doesn’t create the ZIP automatically if /p:PackageOnPublish=false is provided to dotnet publish
  • The Web API project creates the ZIP if both /p:PackageOnPublish=false and /t:Package are provided to dotnet publish

As you can see, it’s possible to test a custom .NET package and validate that it works as expected before you publish it. This makes the solution more reliable and reduces the risk of breaking changes. These tests could be written in bash, PowerShell, or even as command line calls from a .NET unit test project. The key is to make sure that the solution is maintainable. It’s code after all.

What will you test next? Happy DevOp’ing!