- snapshot testing.
- component testing.
- fakes, stubs, and mock functions aka spies.
- sub-type of component testing.
- very useful to spot regressions.
- automatically generated by Jest.
- a snapshot is a JSON based record of a component's output.
- snapshots are saved to a
__snapshots__
folder as a sibling of the tested component. - during testing, the components are automatically compared to their last recorded snapshot.
- fails with any change to the component.
- the snapshots are commited to source control.
- first, install
react-test-renderer
if you haven't. - second
import renderer from 'react-test-renderer';
. - then
import { TheComponent } from './TheComponent';
. - create a tree.
- run the assertion to match snapshot.
import renderer from 'react-test-renderer';
import { TheComponent } from './TheComponent';
const tree = renderer.create(<TheComponent />);
expect(tree.toJSON()).toMatchSnapshot();
- the first time, the snapshot is created.
- when the snapshot fails, the developer can decide to update the snapshot if the change was intended.
- to update snapshot:
jest TheComponent -u
or--update
, but, ain't nobody got time for that (if you used create-react-app the command isyarn test -u
).
-
fast and semi-automatic.
-
catches regressions that could be missed by humans.
-
works with any library that generates HTML components (Angular, Vue, React).
-
better than no tests at all to protect applications from regressions.
-
easy to override, save new snapshot.
-
protects only against regression.
-
easy to break, smallest change will fail test suite.
-
adds more files to the repository.
-
waste of time to have them while actively making changes to components.
- appearance and functionality of a component.
- highly sensitive to small changes.
- great against regression.
- verifies changes to component output resulting from changes to state.
- does NOT verify interaction between components.
- does it render?
- does it render correctly?
- are sub-components rendered, and how many of them.
- are props handled correctly.
- is state handled correctly.
- does it handle events correctly?
- should be independent.
- test only what needs to be tested.
- one test per behavior/functionality, multiple assertions are ok.
- one code unit at a time.
- render component in asolation without any sub components. This is called
shallow rendering
. - we'll use a library called
enzyme
forshallow rendering
. - insde the
README.md
file generated bycreate-react-app
there are instructions on how to addenzyme
to the project. Follow the instructions under
- type:
yarn add enzyme enzyme-adapter-react-16 react-test-renderer
. - add a global setup file:
src/setupTests.js
.
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
Using enzyme. Docs
- add library.
- add this code to
App.test.js
.
import { shallow } from 'enzyme';
it('shallow renders without crashing', () => {
shallow(<App />); // notice this only renders App and will not render any child components
});
-
a duplicate of a unit of code that has no implementation.
-
has the same API (method names, return value type and shape must be returned) of the original unit, but has no side effects.
-
prevent side effects.
-
reduce dependencies.
-
isolate tests to simplify testing.
-
add mocks to a
__mocks__
folder, next to the mocked module. -
to mock npm modules, just name your mock the same as the module and it will be loaded automatically.
- folder must be at the root of the application, next to
node_modules
folder. - add a file inside the folder with the name of the module you want to mock.
- folder must be at the root of the application, next to
-
to mock local files:
- add the
__mocks__
folder at the same level of the file to mock. - where the mock is needed (inside the test file) call
jest.mock('path to code file to be mocked');
.
- add the
Spies are functions that provide information about how they are used.
-
counts function calls.
-
records arguments passed to it when it is called.
-
we can return fake values in order to test specific scenarios.
-
to create
spies
:const jamesBond = jest.fn()
;. This creates anoop
function. -
passing a funcion as the first argument, wraps that function into a
spy
that then keeps track of useful information.