[Guest Post] Visual Studio for Mac Helps You Write Tests
You’re writing tests for your code, right? No? Just say ‘yes’. It’ll make this blog post go a lot easier. So anyway, I’m happy to hear that you’re writing tests for all your code. Whether you’re following the “test first” / Test-Driven Development (TDD) approach or whether you’re just writing some unit tests or integration tests, Visual Studio for Mac has some nice features to make your life as a developer a lot easier.
In this article, I’ll walk you through the process of writing and running unit tests using Visual Studio for Mac.
Before I jump in on the features, let’s get a few terms out of the way. (For more information on the different types of tests and why you might choose one over the other, check out this article.)
What’s a “unit test”? A unit test is a piece of code that exercises and verifies the execution of a piece of code in your application. That application is referred to as the “system under test” or SUT. Let’s say I’m writing a .NET Core application using C#. When I’m writing code, if I have a C# class in my application, I’ll have at least one test class in my test project. For every public method in my application’s class, I’ll have at least one test method in my test class that tests the corresponding application method.
If you’re new to automated testing, you might want to check out this article on unit testing best practices.
Test-driven development (TDD) isn’t a type of test – it’s a way of writing features & tests. TDD is commonly referred to as “test first” and the idea is that you’re going to write your tests before you write your application code. Starting with your tests gets you a better overall design and cleaner code.
Writing your tests first can be a little cumbersome because you’re starting with almost nothing. Thankfully, Visual Studio for Mac has some features that help to make it easier. In this example, I’ll show how we can generate code as part of our test-first development workflow.
Tour of the Sample Code
Source code is available at https://github.com/benday-inc/visual-studio-mac-tdd-demo. This repo contains both “before” code so that you can code along and also an “after” folder that has the completed sample. If you’re interested in starting from scratch, you might want to check out this guide to getting started with the Testing tools in Visual Studio for Mac.
Let’s say that you’re going to write a calculator using test-driven development (TDD). The first step is to start writing your tests. To save time, I’ve created a .NET Core solution in Visual Studio for Mac that consists of an MSTest-based unit project, an class library for my application, and an ASP.NET Core MVC web application.
The class that contains the calculator logic is eventually going to go into the
Benday.CalculatorDemo.Api class library project but at the moment that class doesn’t exist. We’re going to start writing our test code in a class called
CalculatorFixture in the
Rename the Unit Test Class
Let’s start by editing UnitTest1.cs. Right now that class just has the default structure for an MSTest-based unit test in it and the class is named
Let’s change the class name to be
Right now the file name doesn’t match the class name – the file is named
UnitTest1.cs and the class name is
CalculatorFixture. There’s an easy way to fix that. Click on the “
CalculatorFixture” word of the class declaration and press Option-Enter to bring up the Quick Actions and Refactorings menu. One of the options is Rename type to CalculatorFixture. Visual Studio for Mac is smart enough to know that your class name doesn’t match the class name implied by your filename so if you choose this item from the menu, it’ll rename the class for you.
Now if you look at the Solution Explorer window, you’ll see that the filename now says
CalculatorFixture.cs. Sure, this isn’t life-changing but it’s one of those little things that makes coding a little more pleasant.
TDD Step #1: Write Your Tests
Now let’s write the empty structure of our calculator tests by adding test methods for
Divide(). When I know that I’m going to want to write a test case but I’m not quite ready to write it, I’ll put in a call to
Assert.Inconclusive(). If I left the test method code empty, it would look like a passing test but if I put the call in to
Assert.Inconclusive(), it’ll provide me a nice placeholder reminding me that I need to come back to implement the tests. It’s not going to fail but it won’t pass either.
Run the Tests
Now that we’ve got some code, let’s try to run the tests. The easiest way to run all the tests in a test class is to right-click on the class name and choose Run Test(s).
You should see the Tests panel appear and your tests should run.
Write the Test Code
Now let’s write some test code for the
If you press Command-B to build your solution, this is going to fail. The error should be something like “CalculatorFixture.cs(39,39): Error CS0246: The type or namespace name ‘Calculator’ could not be found”. This is because there’s no class named Calculator yet.
In the API project, there’s a class called
Class1.cs. Let’s rename this class to Calculator and change the filename to
After you’ve renamed that class to be Calculator, you’ll still be getting an error because of a missing using statement. In
CalculatorFixture.cs, on line 12, click on the word Calculator and then type Option-Enter to bring up the Quick Actions and Refactorings menu.
You should see an option to add a using statement. Choose that option.
Now that that’s fixed, try to rebuild the solution. You should now be getting an error that says “Error CS1061: ‘Calculator’ does not contain a definition for ‘Add’ and no accessible extension method ‘Add’ accepting a first argument of type ‘Calculator’ could be found”. This is because there’s no method named
Add() on the Calculator class.
TDD Step #2: Create an implementation / Add the Missing Method
Alright. So we’re trying to write that Add() method and our test class is failing to compile because that method doesn’t exist yet. Let’s use the Quick Actions and Refactorings menu to generate that method for us.
In CalculatorFixture.cs, on line 19, click on the word Add() and then type Option-Enter to bring up the Quick Actions menu. One of the options should be “Generate method ‘Calculator.Add’”. If you choose this option, Visual Studio for Mac will create a basic implementation for you including the arguments and return values.
After you run the Generate method action, when you open up
Calculator.cs, you’ll now see that there’s an implementation of the
Add() method that throws a
Now when you rebuild your solution, it builds successfully without errors. When you run all your tests, you should now see that the Add test is failing and that the other 3 tests are saying inconclusive.
Implement the Add() Method
Next let’s implement the add method in the Calculator class.
After you’ve added the implementation for the
Add() method, re-run the tests. The test for Add should pass.
From here you can now implement the rest of the tests using the same process. Visual Studio for Mac’s ability to generate code for you while you’re writing your test-first unit tests can really help you to avoid some common coding headaches.
If you’re looking for more advanced info on automated testing techniques such as how to break up testing dependencies and testing ASP.NET application security, check out my Architecting an ASP.NET Core MVC Application for Unit Testability course on Pluralsight.
About the Author
Benjamin Day is a consultant and trainer specializing in software best practices using Scrum with Microsoft’s DevOps tools. Ben’s main areas of emphasis include Azure DevOps, Scrum, software testing, and software architecture. He is a Microsoft MVP, a certified Scrum trainer via Scrum.org, and a speaker at conferences such as Pluralsight Live and VSLive. When not developing software, Ben’s been known to go running and sea kayaking in order to balance out his love of cheese, cured meats, and champagne. His online courses are available at https://courses.benday.com and at http://www.pluralsight.com. He can be contacted via http://www.benday.com.