Why snapshot testing in react is not as useful always

Introduction

Snapshot testing, as the name refers, is taking the snapshot of the component and then testing if it has changed from previous one. The previous snapshot of the component is source of truth. So any deviation from the previous snapshot will result in test failing. This type of testing allows you to test the component as a whole, and are useful when you do not want the UI to change unexpectedly. If the change of the snapshot is expected, then you update the snapshot of component which will be the reference for the next time when you do snapshot test of that component.

It requires discipline

The goal of testing is to make sure the component is not broken. When a normal unit test fails, you know exactly why and where did it failed. If you make some changes in the component, and the normal unit test passes, your component is not broken. But with snapshot testing, the test is going to fail even if the component is not broken (because you have changed the snapshot).

So it reduces the trust of the developers on the snapshot tests. And if the team does not follow discipline, then chances that a developer would update the snapshot of the failing test will be more instead of finding why did the test actually failed. The tests become irrelevant and developers would simply ignore these tests.

TDD is hard

Jest generates the snapshot of the component automatically. If you want to do test driven development using snapshot, then you need to write the snapshot test first. There are ways to write the snapshot test manually. But its hard, extremely hard. And snapshot tests are not meant to be written manually.

Its not unit test nor a regression test

Snapshot tests do not replace unit tests. They provide additional value and make testing easy. Snapshot tests can reduce the number of unit tests, but you cannot avoid it.

Snapshot tests are also not regression tests. Regression tests using selenium or cypress actually control the browser and run through the flow. Visual regression tools also work same way as snapshot tests, but in visual regression testing, the  comparision is between the screenshot of the page. But in snapshot tests, the page is serialized as string and is checked in with the code as well.

Snapshot tests lie on grey area between unit tests and regression testing. It is an additional testing tool that can make it easier to test events or css, but you cannot rely on it completely.

Snapshot tests are not documentation

Ususally, the tests are said to be documentation to the code. The developer can read through the unit tests and understand what the code is supposed to do. But can that be said same for the snapshot tests? No.

Consider a react component with a button and a name. The button toggles the name.

import React, { Component } from "react";

class App extends Component {
  state = {
    showName: false
  };
  toggleShowName = () => {
    const { showName } = this.state;
    this.setState({
      showName: !showName
    });
  };
  render() {
    const { showName } = this.state;
    return (
      <div className="App">
        <button onClick={this.toggleShowName}>Click me</button>
        {showName ? <div className="name">React</div> : null}
      </div>
    );
  }
}

export default App;

If we have to write unit test for the functionality of toggling, it would be  something like this.

it("should toggle name", () => {
  const wrapper = shallow(<App />);
  wrapper.find("button").simulate("click");
  expect(wrapper.find(".name")).toHaveLength(1);
});

In the above unit test, the developer can understand what the click of button is supposed to do (show the name in the component).

But compare that with snapshot test for the above component.

it("should toggle name", () => {
  const app = shallow(<SnapShotTests/>);
  const tree = renderer.create(<SnapShotTests />).toJSON();
  expect(tree).toMatchSnapshot();
  app.find('button').simulate('click');
  expect(tree).toMatchSnapshot();
});

Here we only assert that the tree should match the snapshot. The developer will not get to know what will happen when the button is clicked on reading the above snapshot test.

Conclusion

Snapshots tests are good feature to have for testing your apps. Although snapshot testing is easy, and it is extremely useful to test events and actions using it, there needs to be discipline among the developers to not abuse it.