Sometimes a request from a customer inspires me to set up a CodeGrade assignment and explore new ways of autograding. In this case I got a request to provide an example of how to do unit testing to autograde a C# assignment. Creating C# assignments in CodeGrade is rather easy, either using mono, or by actually using .NET Core, which is available for Linux and MacOS as well nowadays. The thing is, though, often you don't want students to hand in a complete project, as that makes it harder to focus on the important stuff: the actual files they create. It is much easier and less error prone, especially for basic assignments, if students just hand in the .cs files they have created instead of the whole Visual Studio project.
Now comes the interesting part: using those files, and automatically creating the project structure around them. The reason we want to do this, is so that we can use the .NET tools to test the code and write unit tests using xUnit, one of the most popular unit testing frameworks for C#. The .NET Core framework provides the "dotnet" command to run projects and tests. But, for the "dotnet" command to work it has to be a valid project. In this case, we do not want students to hand in full projects, so we will have to craft the project and insert the tests automatically. This might sound difficult, but it is actually not that hard and quite fast to all set up.
Before we start setting up the CodeGrade assignment straight away, it is usually a good idea to start locally on your own computer. There we can easily figure out how we can create the structure, test if it works, and then port it to CodeGrade when we have a clear and clean idea.
For this particular example, we will be following most of the structure from this excellent guide from Microsoft. In this example, students will create a small program that will check if a number is prime. Following the earlier guideline, students will only hand in the PrimeService.cs file, which is a simple function to determine if a number is a prime. To make sure students only hand in this file, we can use CodeGrade's hand-in instructions. The Microsoft guide walks you through setting up a whole solution, but for our purposes, that's not necessary. The simple structure we would like to create is as follows:
- PrimeService.cs: this is the file that students hand in.
- PrimeService.csproj: this is a fixture we generate and then upload to AutoTest.
- PrimeService_IsPrimeShould.cs: our xUnit tests live here.
- PrimeService.Tests.csproj: this is a fixture we upload.
This gives us the following tasks:
- Generate the .csproj files
- Write the unit tests
- Create a simple script that generates the folder structure.
- Port it to CodeGrade.
Generating the .csproj files
Let's start with the first step, and that's creating the .csproj files. We can just execute some simple dotnet commands to create these:
-!- CODE language-console -!-dotnet new classlib -o PrimeService
This command will create the PrimeService.csproj file (and some other stuff including the directory structure, but we can disregard that).
Write the unit tests
Now let's quickly take a look at the solution file that students will hand in:
-!- CODE language-cs -!-using System;
public class PrimeService
public bool IsPrime(int candidate)
if (candidate < 2)
for (var divisor = 2; divisor <= Math.Sqrt(candidate); divisor++)
if (candidate % divisor == 0)
Then we can start writing some unit tests for this. First, we'll have to create the tests project and link them to the solution:
-!- CODE language-console -!-dotnet new xunit -o PrimeService.Tests
dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj
Then within this directory, we can create the actual unit test. For this example let's just create one simple test:
-!- CODE language-cs -!-using Xunit;
public class PrimeService_IsPrimeShould
public void IsPrime_InputIs1_ReturnFalse()
var primeService = new PrimeService();
bool result = primeService.IsPrime(1);
Assert.False(result, "1 should not be prime");
We can already test this on our solution locally by simply running the "dotnet test" command.