Why you should make your tests fail
Tags: testing, javascript, webdev, beginners
Published: 2021-12-02 13:58:36

Let's face it, most of us developers don't necessarily love writing tests. We sometimes end up rushing through them, and once we see that green tick next to a passing test, we're generally pretty happy to move on. However, an enemy is lurking amongst us.

## False positive test

The enemy I'm talking about here is otherwise known as a false positive test. Let's take a look at what this beast looks like.

Here we have a `select` element with some countries as options:

```tsx
<select>
  <option value="">Select a country</option>
  <option value="US">United States</option>
  <option value="IE">Ireland</option>
  <option value="AT">Austria</option>
</select>
```

Here's my test:

```tsx
it('should allow user to change country', () => {
  render(<App />)
  userEvent.selectOptions(
    screen.getByRole('combobox'),
    screen.getByRole('option', { name: 'Ireland' } ),
  )
  expect(screen.getByRole('option', { name: 'Ireland' })).toBeInTheDocument();
})
```

The test passes, isn't that great? ✅  I'm afraid not. 😭  Let's see why after we intentionally make it fail.

## Making your test fail

Here's a real example of a false positive test situation I ran into recently:

```tsx
it('should allow user to change country', () => {
  render(<App />)
  userEvent.selectOptions(
    screen.getByRole('combobox'),
    screen.getByRole('option', { name: 'Ireland' } ),
  )
 
  // Changed expected country from "Ireland" to "Austria" - this should fail.
  expect(screen.getByRole('option', { name: 'Austria' })).toBeInTheDocument();
})
```

I was expecting the check for "Austria" to fail because it wasn't the selected country, and I was pretty surprised to see that it was still passing. Looks like we have just identified a false positive test.

Let us take a step back. The purpose of my test is to ensure that when changing a country, it is indeed the now selected option. However, after debugging for while I eventually realised that the test above only checks that the country "Ireland" exists, instead of checking if it's selected.

Here's how I eventually fixed it:

```tsx
it('should allow user to change country', () => {
  render(<App />)
  userEvent.selectOptions(
    screen.getByRole('combobox'),
    screen.getByRole('option', { name: 'Ireland' } ),
  )
 
  // Now checking if the option is selected
  expect(screen.getByRole('option', { name: 'Ireland' }).selected).toBe(true);
})
```

Now, I am correctly checking that the option is selected and all is good. I wouldn't have found this unless I intentionally made my test fail, so I'm glad my persistence has paid off and I avoided a potential bug. 

## Final thoughts

I've been burnt enough times in the past by false positive tests that I have vouched to always intentionally make my tests fail before moving on to the next one. Since doing this, I've gotten a lot more confident in my tests knowing that they'll only pass in the correct circumstances. 

That's about all I have to share with you today. Let me know in the comments if you found this article useful. 🙌 

## Want to follow along?

I mainly write about real tech topics I face in my everyday life as a Frontend Developer. If this appeals to you then feel free to follow me on Twitter: [https://twitter.com/cmacdonnacha](https://twitter.com/cmacdonnacha)

Bye for now 👋