Adding Test Classes
Add an MSTest test project beside your app, give it a reference to the app, and add a test class for each class you test.
Apprentice · Unit Testing · C# · Updated
After this lesson you can
- Add an MSTest test project to a solution, with a reference to the project it tests
- Write a test class with [TestClass] and [TestMethod], and run it
Key takeaways
dotnet new mstest -n TvRemote.Testsmakes a test project, anddotnet add TvRemote.Tests reference TvRemotelets its tests see the app's classes.[TestClass]marks a class that holds tests, and[TestMethod]marks apublic voidmethod that is one test.- A method without
[TestMethod], or one that isn'tpublic, isn't run as a test. - Test Explorer finds tests only after the solution builds, so build it when the list is empty.
Here's the Television class from Planning Unit Tests, in a console app named TvRemote:
namespace TvRemote;
public class Television
{
public const int LowestChannel = 3;
public const int HighestChannel = 15;
public bool IsOn { get; private set; }
public int CurrentChannel { get; private set; } = LowestChannel;
public void TurnOn()
{
IsOn = true;
}
public void TurnOff()
{
IsOn = false;
}
// Goes up one channel, from the highest back to the lowest, and returns the new channel.
// While the TV is off, nothing changes.
public int ChannelUp()
{
if (IsOn)
{
CurrentChannel = CurrentChannel == HighestChannel ? LowestChannel : CurrentChannel + 1;
}
return CurrentChannel;
}
// Changes to the channel, if the TV is on and the channel exists. Returns whether it changed.
public bool ChangeChannel(int channel)
{
if (!IsOn || channel < LowestChannel || channel > HighestChannel)
{
return false;
}
CurrentChannel = channel;
return true;
}
}
Add a test project
From the folder that holds TvRemote:
dotnet new mstest -n TvRemote.Tests
dotnet add TvRemote.Tests reference TvRemote
dotnet new sln -n TvRemote
dotnet sln add TvRemote TvRemote.Tests
| Command | Does |
|---|---|
dotnet new mstest |
Makes a test project with the MSTest package |
dotnet add ... reference |
Lets the tests see the app's classes |
dotnet new sln, dotnet sln add |
Puts both projects in one solution, so Visual Studio opens them together |
In Visual Studio: right-click the solution in Solution Explorer, Add > New Project..., choose MSTest Test Project, and name it TvRemote.Tests. Then right-click the test project's Dependencies, Add Project Reference..., and check TvRemote.
The test project's .csproj lists the MSTest package, the reference, and one handy line: a global using, so every test file can use MSTest's names without its own using line:
<ItemGroup>
<PackageReference Include="MSTest" Version="4.0.2" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TvRemote\TvRemote.csproj" />
</ItemGroup>
(The template also adds Test1.cs, an empty example: delete it.)
Add a test class
Add TelevisionTests.cs to the test project:
namespace TvRemote.Tests;
[TestClass]
public class TelevisionTests
{
[TestMethod]
public void ChannelUp_WhenOn_GoesUpOneChannel()
{
Television tv = new Television();
tv.TurnOn();
int newChannel = tv.ChannelUp();
Assert.AreEqual(4, newChannel);
}
}
Two attributes, in square brackets, tell the test runner what to run:
[TestClass]marks a class that holds tests.[TestMethod]marks a method that is one test. It'spublicand returnsvoid. (It takes no parameters, unless it gets them from[DataRow], which Writing Tests shows.)
Methods without [TestMethod] are ordinary helpers: the runner doesn't run them as tests.
Television needs no using: the test class's namespace, TvRemote.Tests, is inside TvRemote, so C# finds TvRemote.Television by itself.
Run it
Run Test > Run All Tests in Visual Studio, or in the terminal:
dotnet test
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 31 ms - TvRemote.Tests.dll (net10.0)
Test Explorer lists every test with a green check or a red cross. Double-click one to jump to its code, or right-click it to run just that test.
Common problems
| What you see | What to do |
|---|---|
The type or namespace name 'Television' could not be found |
The test project has no reference to the app. Add it: dotnet add TvRemote.Tests reference TvRemote. |
| Test Explorer is empty | Build the solution (Ctrl+Shift+B) so the runner can find the tests, and check the class has [TestClass]. |
| A test you wrote isn't run | It's missing [TestMethod], or it isn't public. |
Check yourself
2 questions to try on the lesson page.
So what
One command makes a test project, one more connects it to your app, and two attributes turn a class into tests. From here on, every class you write can have tests beside it.