Skip to content

Commit

Permalink
Add react-native tutorial, update react tutorial, add blog post.
Browse files Browse the repository at this point in the history
  • Loading branch information
cpojer committed Jul 27, 2016
1 parent 7ed5eb2 commit 0060d79
Show file tree
Hide file tree
Showing 8 changed files with 615 additions and 55 deletions.
42 changes: 40 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ describe('CheckboxWithLabel', () => {
});
```

Check out the [React tutorial](https://facebook.github.io/jest/docs/tutorial-react.html) for more.

**And you are good to go!** The next time you run Jest it will print something
like

Expand All @@ -122,6 +120,38 @@ The
[react-native](https://github.com/facebook/react-native/tree/master/Libraries/Animated/src/__tests__)
repositories have excellent examples of tests written by Facebook engineers.

### React, React-Native and Snapshot Testing

Check out the [React tutorial](https://facebook.github.io/jest/docs/tutorial-react.html) and the [React-Native tutorial](https://facebook.github.io/jest/docs/tutorial-react-native.html) to get started with React or React-Native codebases.

We recommend using React's test renderer to capture snapshots with Jest's snapshot feature. Write a test using `toMatchSnapshot`:

```js
import renderer from 'react/lib/ReactTestRenderer';
it('renders correctly', () => {
const tree = renderer.create(
<Link page="http://www.facebook.com">Facebook</Link>
).toJSON();
expect(tree).toMatchSnapshot();
});
```

and it will produce a snapshot like this:

```js
exports[`Link renders correctly 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function bound _onMouseEnter]}
onMouseLeave={[Function bound _onMouseLeave]}>
Facebook
</a>
`;
```

On subsequent test runs, Jest will compare the stored snapshot with the rendered output and highlight differences. If there are differences, Jest will ask you to fix your mistake and can be re-run with `jest -u` to update an outdated snapshot.

### Advanced Features

#### Only run test files related to changes with `jest -o`
Expand Down Expand Up @@ -337,6 +367,7 @@ Jest uses Jasmine 2 by default. An introduction to Jasmine 2 can be found
- [`modulePathIgnorePatterns` [array<string>]](https://facebook.github.io/jest/docs/api.html#modulepathignorepatterns-array-string)
- [`notify` [boolean]](https://facebook.github.io/jest/docs/api.html#notify-boolean)
- [`preprocessorIgnorePatterns` [array<string>]](https://facebook.github.io/jest/docs/api.html#preprocessorignorepatterns-array-string)
- [`preset` [string]](https://facebook.github.io/jest/docs/api.html#preset-string)
- [`rootDir` [string]](https://facebook.github.io/jest/docs/api.html#rootdir-string)
- [`scriptPreprocessor` [string]](https://facebook.github.io/jest/docs/api.html#scriptpreprocessor-string)
- [`setupFiles` [array]](https://facebook.github.io/jest/docs/api.html#setupfiles-array)
Expand Down Expand Up @@ -813,6 +844,8 @@ along with any other options: `['node_modules', 'bower_components']`

A map from regular expressions to module names that allow to stub out resources, like images or styles with a single module.

Modules that are mapped to an alias are unmocked by default, regardless of whether automocking is enabled or not.

Use `<rootDir>` string token to refer to [`rootDir`](https://facebook.github.io/jest/docs/api.html#rootdir-string) value if you want to use file paths.

Additionally, you can substitute captured regex groups using numbered backreferences.
Expand All @@ -831,6 +864,11 @@ Example:

Activates notifications for test results.

### `preset` [string]
(default: `undefined`)

A preset that is used as a base for Jest's configuration. A preset should point to an npm module that exports a `jest-preset.json` module on its top level.

### `rootDir` [string]
(default: The root of the directory containing the `package.json` *or* the [`pwd`](http://en.wikipedia.org/wiki/Pwd) if no `package.json` is found)

Expand Down
96 changes: 96 additions & 0 deletions blog/2016-07-27-jest-14.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: Jest 14.0: React Tree Snapshot Testing
author: Christoph Pojer
authorURL: http://twitter.com/cpojer
authorFBID: 100000023028168
---

One of Jest's philosophies is to provide an integrated “zero-configuration” experience. We want to make it as frictionless as possible to write good tests that are useful. We observed that when engineers are provided with ready-to-use tools, they end up writing more tests, which in turn results in stable and healthy code bases.

<!--truncate-->

One of the big open questions was how to write React tests efficiently. There are plenty of tools such as [ReactTestUtils](https://facebook.github.io/react/docs/test-utils.html) and [enzyme](http://airbnb.io/enzyme/). Both of these tools are great and are actively being used. However engineers frequently told us that they spend more time writing a test than the component itself. As a result many people stopped writing tests altogether which eventually led to instabilities. Engineers told us all they wanted was to make sure their components don't change unexpectedly.

Together with the React team we created a new test renderer for React and added snapshot testing to Jest. Consider this [example test](https://github.com/facebook/jest/blob/master/examples/snapshot/__tests__/Link.react-test.js) for a simple [Link component](https://github.com/facebook/jest/blob/master/examples/snapshot/Link.react.js):

```javascript
import renderer from 'react/lib/ReactTestRenderer';
test('Link renders correctly', () => {
const tree = renderer.create(
<Link page="http://www.facebook.com">Facebook</Link>
).toJSON();
expect(tree).toMatchSnapshot();
});
```

The first time this test is run, Jest creates a [snapshot file](https://github.com/facebook/jest/blob/master/examples/snapshot/__tests__/__snapshots__/Link.react-test.js.snap) that looks like this:

```javascript
exports[`Link changes the class when hovered 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function bound _onMouseEnter]}
onMouseLeave={[Function bound _onMouseLeave]}>
Facebook
</a>
`;
```

The snapshot artifact should be committed alongside code changes. We use [pretty-format](https://github.com/thejameskyle/pretty-format) to make snapshots human-readable during code review. On subsequent test runs Jest will simply compare the rendered output with the previous snapshot. If they match, the test will pass. If they don't match, either the implementation has changed and the snapshot needs to be updated with `jest -u`, or the test runner found a bug in your code that should be fixed.

If we change the address the Link component in our example is pointing to, Jest will print this output:

![snapshot-testing](/jest/img/blog/snapshot.png)

Now you know that you either need to accept the changes with `jest -u`, or fix the component if the changes were unintentional.
To try out this functionality, please clone the [snapshot example](https://github.com/facebook/jest/tree/master/examples/snapshot), modify the Link component and run Jest.

This feature was built by [Ben Alpert](https://twitter.com/soprano) and [Cristian Carlesso](https://twitter.com/kentaromiura).

## Experimental React Native support

By building a test renderer that targets no specific platform we are finally able to support a full, unmocked version of React Native. We are excited to launch experimental React Native support for Jest through the `jest-react-native` package.

You can start using Jest with react-native by running `npm install —save-dev jest-react-native` and by adding the preset to your Jest configuration:

```javascript
"jest": {
"preset": "jest-react-native"
}
```

* [Example project](https://github.com/facebook/jest/tree/master/examples/react-native)
* [Tutorial and setup guide](http://facebook.github.io/jest/docs/tutorial-react-native.html#content)
* [Example pull request for *snowflake*](https://github.com/bartonhammond/snowflake/pull/110), a popular react-native open source library.

*Note: the preset currently only implements the minimal set of configuration necessary to get started with React Native testing. We are hoping for community contributions to improve this project. Please try it and file [issues](https://github.com/facebook/jest/issues) or send pull requests!*

## Why snapshot testing?

For Facebook's native apps we use a system called “snapshot testing”: a snapshot test system that renders UI components, takes a screenshot and subsequently compares a recorded screenshot with changes made by an engineer. If the screenshots don't match, there are two possibilities: either the change is unexpected or the screenshot can be updated to the new version of the UI component.

While this was the solution we wanted for the web, we also found many problems with such end-to-end tests that snapshot integration tests solve:

* **No flakiness:** Because tests are run in a command line runner instead of a real browser or on a real phone, the test runner doesn't have to wait for builds, spawn browsers, load a page and drive the UI to get a component into the expected state which tends to be flaky and the test results become noisy.
* **Fast iteration speed:** Engineers want to get results in less than a second rather than waiting for minutes or even hours. If tests don't run quickly like in most end-to-end frameworks, engineers don't run them at all or don't bother writing them in the first place.
* **Debugging:** It's easy to step into the code of an integration test in JS instead of trying to recreate the screenshot test scenario and debugging what happened in the visual diff.

Because we believe snapshot testing can be useful beyond Jest we split the feature into a [jest-snapshot](https://github.com/facebook/jest/tree/master/packages/jest-snapshot) package. We are happy to work with the community to make it more generic so it can be integrated with other test runners and share concepts and infrastructure with each other.

Finally, here is a quote of a Facebook engineer describing how snapshot testing changed his unit testing experience:


> “One of the most challenging aspects of my project was keeping the input and output files for each test case in sync. Each little change in functionality could cause all the output files to change. With snapshot testing I do not need the output files, the snapshots are generated for free by Jest! I can simply inspect how Jest updates the snapshots rather than making the changes manually.” – [Kyle Davis](https://github.com/kyldvs) working on [fjs](https://github.com/kyldvs/fjs).
## What's next for Jest

Recently [Dmitrii Abramov](https://twitter.com/abramov_dmitrii) has joined the Jest team full time to improve our unit and integration test infrastructure for Facebook's ads products. For the next few months the Jest team is planning major improvements in these areas:

* **Replace Jasmine:** Jasmine is slowing us down and is not being very actively developed. We started replacing all the Jasmine matchers and are excited to add new features and drop this dependency.
* **Code Coverage:** When Jest was originally created, tools such as babel didn't exist. Our code coverage support has a bunch of edge cases and isn't always working properly. We are rewriting it to address all the current problems with coverage.
* **Developer Experience:** This ranges from improving the setup process, the debugging experience to CLI improvements and more documentation.
* **Mocking:** The mocking system, especially around manual mocks, is not working well and is confusing. We hope to make it more strict and easier to understand.
* **Performance:** Further performance improvements especially for really large codebases are being worked on.

As always, if you have questions or if you are excited to help out, please reach out to us!
6 changes: 6 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Jest uses Jasmine 2 by default. An introduction to Jasmine 2 can be found
- [`modulePathIgnorePatterns` [array<string>]](#modulepathignorepatterns-array-string)
- [`notify` [boolean]](#notify-boolean)
- [`preprocessorIgnorePatterns` [array<string>]](#preprocessorignorepatterns-array-string)
- [`preset` [string]](#preset-string)
- [`rootDir` [string]](#rootdir-string)
- [`scriptPreprocessor` [string]](#scriptpreprocessor-string)
- [`setupFiles` [array]](#setupfiles-array)
Expand Down Expand Up @@ -562,6 +563,11 @@ Example:

Activates notifications for test results.

### `preset` [string]
(default: `undefined`)

A preset that is used as a base for Jest's configuration. A preset should point to an npm module that exports a `jest-preset.json` module on its top level.

### `rootDir` [string]
(default: The root of the directory containing the `package.json` *or* the [`pwd`](http://en.wikipedia.org/wiki/Pwd) if no `package.json` is found)

Expand Down
34 changes: 32 additions & 2 deletions docs/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ describe('CheckboxWithLabel', () => {
});
```

Check out the [React tutorial](/jest/docs/tutorial-react.html) for more.

**And you are good to go!** The next time you run Jest it will print something
like

Expand All @@ -117,6 +115,38 @@ The
[react-native](https://github.com/facebook/react-native/tree/master/Libraries/Animated/src/__tests__)
repositories have excellent examples of tests written by Facebook engineers.

### React, React-Native and Snapshot Testing

Check out the [React tutorial](/jest/docs/tutorial-react.html) and the [React-Native tutorial](/jest/docs/tutorial-react-native.html) to get started with React or React-Native codebases.

We recommend using React's test renderer to capture snapshots with Jest's snapshot feature. Write a test using `toMatchSnapshot`:

```js
import renderer from 'react/lib/ReactTestRenderer';
it('renders correctly', () => {
const tree = renderer.create(
<Link page="http://www.facebook.com">Facebook</Link>
).toJSON();
expect(tree).toMatchSnapshot();
});
```

and it will produce a snapshot like this:

```js
exports[`Link renders correctly 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function bound _onMouseEnter]}
onMouseLeave={[Function bound _onMouseLeave]}>
Facebook
</a>
`;
```

On subsequent test runs, Jest will compare the stored snapshot with the rendered output and highlight differences. If there are differences, Jest will ask you to fix your mistake and can be re-run with `jest -u` to update an outdated snapshot.

### Advanced Features

#### Only run test files related to changes with `jest -o`
Expand Down
Loading

0 comments on commit 0060d79

Please sign in to comment.