Reader small image

You're reading from  Mastering React Test-Driven Development - Second Edition

Product typeBook
Published inSep 2022
Reading LevelIntermediate
PublisherPackt
ISBN-139781803247120
Edition2nd Edition
Languages
Tools
Right arrow
Author (1)
Daniel Irvine
Daniel Irvine
author image
Daniel Irvine

Daniel Irvine is a UK-based software consultant. He helps businesses simplify their existing codebases and assists dev teams in improving the quality of their software using eXtreme programming (XP) practices. He has been coaching developers for many years and co-founded the Queer Code London meetup.
Read more about Daniel Irvine

Right arrow

Refactoring your work

Now that you’ve got a green test, it’s time to refactor your work. Refactoring is the process of adjusting your code’s structure without changing its functionality. It’s crucial for keeping a code base in a fit, maintainable state.

Sadly, the refactoring step is the step that always gets forgotten. The impulse is to rush straight into the next feature. We can’t stress how important it is to take time to simply stop and stare at your code and think about ways to improve it. Practicing your refactoring skills is a sure-fire way to level up as a developer.

The adage “more haste; less speed” applies to coding just as it does in life. If you make a habit of skipping the refactoring phase, your code quality will likely deteriorate over time, making it harder to work with and therefore slower to build new features.

The TDD cycle helps you build good personal discipline and habits, such as consistently refactoring. It might take more effort upfront, but you will reap the rewards of a code base that remains maintainable as it ages.

Don’t Repeat Yourself

Test code needs as much care and attention as production code. The number one principle you’ll be relying on when refactoring your tests is Don’t Repeat Yourself (DRY). Drying up tests is a phrase all TDDers repeat often.

The key point is that you want your tests to be as concise as possible. When you see repeated code that exists in multiple tests, it’s a great indication that you can pull that repeated code out. There are a few different ways to do that, and we’ll cover just a couple in this chapter.

You will see further techniques for drying up tests in Chapter 3, Refactoring the Test Suite.

Sharing setup code between tests

When tests contain identical setup instructions, we can promote those instructions into a shared beforeEach block. The code in this block is executed before each test.

Both of our tests use the same two variables: container and customer. The first one of these, container, is initialized identically in each test. That makes it a good candidate for a beforeEach block.

Perform the following steps to introduce your first beforeEach block:

  1. Since container needs to be accessed in the beforeEach block and each of the tests, we must declare it in the outer describe scope. And since we’ll be setting its value in the beforeEach block, that also means we’ll need to use let instead of const. Just above the first test, add the following line of code:
    let container;
  2. Below that declaration, add the following code:
    beforeEach(() => {
      container = document.createElement("div");
      document.body.replaceChildren(container);
    });
  3. Delete the corresponding two lines from each of your two tests. Note that since we defined container in the scope of the describe block, the value set in the beforeEach block will be available to your test when it executes.

Use of let instead of const

Be careful when you use let definitions within the describe scope. These variables are not cleared by default between each test execution, and that shared state will affect the outcome of each test. A good rule of thumb is that any variable you declare in the describe scope should be assigned to a new value in a corresponding beforeEach block, or in the first part of each test, just as we’ve done here.

For a more detailed look at the use of let in test suites, head to https://reacttdd.com/use-of-let.

In Chapter 3, Refactoring the Test Suite, we’ll look at a method for sharing this setup code between multiple test suites.

Extracting methods

The call to render is the same in both tests. It’s also quite lengthy given that it’s wrapped in a call to act. It makes sense to extract this entire operation and give it a more meaningful name.

Rather than pull it out as is, we can create a new function that takes the Appointment component as its parameter. The explanation for why this is useful will come after, but now let’s perform the following steps:

  1. Above the first test, write the following definition. Note that it still needs to be within the describe block because it uses the container variable:
    const render = component =>
      act(() => 
        ReactDOM.createRoot(container).render(component)
      );
  2. Now, replace the call to render in each test with the following line of code:
    render(<Appointment customer={customer} />);
  3. In the preceding step, we inlined the JSX, passing it directly into render. That means you can now delete the line starting with const component. For example, your first test should end up looking as follows:
    it("renders the customer first name", () => {
      const customer = { firstName: "Ashley" };
      render(<Appointment customer={customer} />);
      expect(document.body.textContent).toContain(
        "Ashley"
      );
    });
  4. Rerun your tests and verify that they are still passing.

Highlighting differences within your tests

The parts of a test that you want to highlight are the parts that differ between tests. Usually, some code remains the same (such as container and the steps needed to render a component) and some code differs (customer in this example). Do your best to hide away whatever is the same and highlight what differs. That way, it makes it obvious what a test is specifically testing.

This section has covered a couple of simple ways of refactoring your code. As the book progresses, we’ll look at many different ways that both production source code and test code can be refactored.

Previous PageNext Page
You have been reading a chapter from
Mastering React Test-Driven Development - Second Edition
Published in: Sep 2022Publisher: PacktISBN-13: 9781803247120
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 €14.99/month. Cancel anytime

Author (1)

author image
Daniel Irvine

Daniel Irvine is a UK-based software consultant. He helps businesses simplify their existing codebases and assists dev teams in improving the quality of their software using eXtreme programming (XP) practices. He has been coaching developers for many years and co-founded the Queer Code London meetup.
Read more about Daniel Irvine