Test-Driven Test Development
Writing a Red Test
Integration Tests
Back in the root of our project folder, let’s create a project using an existing .NET testing framework.
At the time of writing, there are a many choices to choose from: xUnit
, NUnit
, MSTest
, and more.
To make this tutorial easier for most developers out there, let’s use the most popular one: xUnit
Let’s make a new xUnit
test project now by running this command from the root project folder:
dotnet new xunit -n MiniSpec.Specs
This will create a new project folder MiniSpec.Specs/
. Let’s go there and write an integration test!
We’ll create a test which:
- Runs
minispec.exe
with theMyTests.dll
DLL assembly provided as an argument - Asserts that the output contains text which indicates that
TestShouldPass()
passed - Asserts that the output contains text which indicates that
TestShouldFail()
failed
What is
minispec.exe
? It doesn’t exist yet, but that’s the program we’ll make to run tests!
Rename UnitTest1.cs
to IntegrationTest.cs
and replace its content with the following:
IntegrationTest.cs
using Xunit;
public class IntegrationTest {
[Fact]
public void ExpectedSpecsPassAndFail() {
// Arrange
var minispecExe = System.IO.File.Exists("minispec.exe") ?
"minispec.exe" : "minispec"; // No .exe extension on Linux
using var minispec = new System.Diagnostics.Process {
StartInfo = {
RedirectStandardOutput = true, // Get the StandardOutput
RedirectStandardError = true, // Get the StandardError
FileName = minispecExe,
Arguments = "MyTests.dll"
}
};
// Act
minispec.Start();
minispec.WaitForExit();
var StandardOutput = minispec.StandardOutput.ReadToEnd();
var StandardError = minispec.StandardError.ReadToEnd();
var output = $"{StandardOutput}{StandardError}";
minispec.Kill();
// Assert
Assert.Contains("PASS TestShouldPass", output);
Assert.Contains("FAIL TestShouldFail", output);
Assert.Contains("Kaboom!", output);
}
}
Review
So, what’s happening here?
- We assume that there will be a
minispec.exe
executable (or simplyminispec
on Linux). - We invoke the
minispec.exe
process passing the DLL with our defined tests as an argument. - We read StandardOutput and StandardError from the process result, i.e. all of the program’s console output.
- StandardOutput and StandardError are combined because we don’t currently care which the results output to.
- We look for expected messages in the output, e.g.
PASS [testname]
orFAIL [testname]
We’re totally making up some of these things as we go along, e.g. the
PASS
/FAIL
messages.
This is how TDD works. We just need to make it fail, then pass, then we can change it later!