Reader small image

You're reading from  Refactoring with C#

Product typeBook
Published inNov 2023
Reading LevelIntermediate
PublisherPackt
ISBN-139781835089989
Edition1st Edition
Languages
Right arrow
Author (1)
Matt Eland
Matt Eland
author image
Matt Eland

Matt Eland is a Microsoft MVP in Artificial Intelligence (AI) who has been working with .NET since 2001. Matt has served as a senior engineer, software engineering manager, and .NET programming instructor. He is currently an AI specialist and senior consultant at Leading EDJE near Columbus, Ohio, where he helps companies with their software engineering and data science needs using C# and related technologies. Matt speaks and writes in his community and co-organizes the Central Ohio .NET Developers Group while pursuing a master's degree in data analytics.
Read more about Matt Eland

Right arrow

Unit Testing

In the first part of this book, we covered the process of refactoring and some of the more common refactoring techniques. Now, it’s time for us to take a step back and remind ourselves of what refactoring is: refactoring is the process of changing the form or shape of the code without changing how it behaves.

In other words, we can make our code as clean and easy to maintain as we can, but if those changes introduce bugs, that’s not refactoring since refactoring is about changing the form of code without changing its behavior. To improve our code without introducing bugs, we need a safety net: unit testing.

In this chapter, we’ll explore unit tests and cover the following main topics:

  • Understanding testing and unit tests
  • Testing code with xUnit
  • Refactoring unit tests
  • Exploring other testing frameworks
  • Adopting a testing mindset

Technical requirements

The starting code for this chapter is available from GitHub at https://github.com/PacktPublishing/Refactoring-with-CSharp in the Chapter06/Ch6BeginningCode folder.

Understanding testing and unit tests

Whenever I was managing or mentoring another developer and they wanted to make a change to a system I’d ask them a question: “How can you be sure your change won’t break things?”

This simple question can be deceptively hard to answer, but every answer I’ve ever heard boils down to a single concept: testing.

I define testing as the process of verifying software functionality and detecting unwanted changes to program behavior.

This testing could be done by a human, such as a developer or a quality assurance analyst, or it could be done via software, depending on the type of test involved.

Types of tests and the testing pyramid

Testing is a broad field that encompasses many different types of activities, including the following:

  • Manual testing, which involves a person performing some activity manually and verifying the outcome.
  • Exploratory testing, a subset of manual testing that focuses...

Testing code with xUnit

xUnit.net, commonly referred to as xUnit, is currently the most popular unit testing library in .NET, followed by NUnit and MSTest. All three libraries provide Attributes that you can use to identify your test code, as we’ll see shortly. Using these attributes lets a test runner, such as Visual Studio’s Test Explorer, recognize your methods as unit tests and run them.

This chapter’s code starts with most of the classes from the chapters up to this point, organized into various namespaces inside of the Chapter6 project within the Chapter6BeginningCode solution.

Solutions and projects

In .NET, a project represents a distinct assembly of .NET code that accomplishes some purpose. Different projects have different types, from desktop applications to web servers to class libraries and test projects. Solutions, on the other hand, group all of these projects together into a collection of interrelated projects.

In the remainder of this...

Refactoring unit tests

Unit tests are code, and like other types of code, they can degrade in quality over time when not given proper respect and proactive refactoring.

Hence, when you see code smells such as duplicated code that appears in most of your tests, it’s a sign that your tests need to be refactored.

In this section, we’ll explore several ways of refactoring your test code.

Parameterizing tests with Theory and InlineData

When we think about the similarities between our two tests, they only vary based on the values being passed into the method we’re testing and the value we expect the result to be.

Thinking about our test method, this is a clear case where it’d be wonderful to have parameters that could go into one test method that could represent multiple unit tests, each testing something slightly different, but with similar code.

As you may recall from earlier, unit tests that use Fact cannot have any parameters to them. However...

Exploring other testing frameworks

Beyond xUnit, the next most popular testing frameworks are NUnit and MSTest.

These two frameworks operate in very similar ways to xUnit but with slight differences in the syntax you use to declare a unit test.

I’ve had the opportunity to program professionally and recreationally in all three major testing frameworks and I can tell you that these differences are largely cosmetic. That said, you will find that certain frameworks have specific features that might not be present in the others.

Testing with NUnit

Of the three testing frameworks, NUnit’s syntax is my favorite because it uses the Test name for both unit tests that require no parameters (equivalent to an xUnit Fact) and those that do (equivalent to an xUnit Theory).

Here’s a parameterized test that verifies the Load method on PassengerFlightInfo:

public class PassengerFlightTests {
    [TestCase(6)]
    public...

Adopting a testing mindset

Let’s take a step back and talk about why a book on refactoring features an entire series of chapters around testing. The reason is that code that needs to be refactored is often a bit more volatile and tends to break more easily when changed. Since the art of refactoring is about changing the form of the software without changing its behavior, introducing bugs when refactoring is undesirable and unacceptable.

This is where tests come in. Tests give you the confidence you and your team need to be able to improve your code. Your legacy code may or may not have tests around it already, so the responsibility and necessity of ensuring good tests are present falls to you before you perform any testing work.

This requires you to adopt a testing mindset. This phrase refers to thinking about tests at the beginning of the development process as a vital component of software development and refactoring, not as an afterthought.

While we’ll explore...

Summary

Unit testing is a powerful way to verify that refactoring code does not introduce bugs, document your classes, and prevent bugs from occurring in the future.

Unit tests are code that tests other code. In .NET, project unit tests are usually performed with xUnit, NUnit, or MSTest. Each testing framework provides assertions that verify that code behaves correctly or fails a test if the actual value doesn’t match the expected value.

When we write unit tests, we typically structure our tests in the arrange/act/assert pattern, which sets up the thing being tested in the arrange step, does a single action in the act step, and verifies the correctness of the action’s result in the assert step.

In the next chapter, we’ll explore testing more with test-driven development.

Questions

Answer the following questions to test your knowledge of this chapter:

  1. Which unit testing framework syntax do you like the most?
  2. What are the most complex parts of your application? Are they tested?
  3. How would you test a method that calculates the credit score of an applicant?
  4. How do you test a void method?
  5. What things can you do to help test code stay clean and readable?
lock icon
The rest of the chapter is locked
You have been reading a chapter from
Refactoring with C#
Published in: Nov 2023Publisher: PacktISBN-13: 9781835089989
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Matt Eland

Matt Eland is a Microsoft MVP in Artificial Intelligence (AI) who has been working with .NET since 2001. Matt has served as a senior engineer, software engineering manager, and .NET programming instructor. He is currently an AI specialist and senior consultant at Leading EDJE near Columbus, Ohio, where he helps companies with their software engineering and data science needs using C# and related technologies. Matt speaks and writes in his community and co-organizes the Central Ohio .NET Developers Group while pursuing a master's degree in data analytics.
Read more about Matt Eland