I’ll be honest, I wasn’t sure what to expect when I heard I’d been assigned the last session of the conference. I’m told that people remember the first and last sessions best, but I guess that only works if you’re all still awake :)
My presentation today is about saving time, so I’ll try to live up to that by keeping things moving and honoring your time. That said, if you have questions as I go, feel free to ask.
So quick note about me, I’m a local developer, I work at Windsor Circle, a startup in downtown Durham.
Today I’m going to be talking to y’all about testing.
This will break down into 5 parts: What is Jest, what is it trying to solve, how can it save you time, a demo, and a chance for you to ask questions.
I will say now that this is an introductory talk. If you were hoping for advanced Jest tips, you’ll probably be disappointed. There’s still time to slip out and find another talk though :). This is going to be about what Jest is and why you would want to use it.
But first, I want to get you moving, so here is a quick poll:
OK looks like this will be relevant to some of y’all and an opportunity to learn new things for the rest.
Separate: Enjoy testing?
Think testing is a waste of time?
Haha alright I’ll try to show you how it can be easier.
So! What is Jest?
When it was first released, Jest didn’t get the same type of love and attention other Facebook open source projects have seen. That changed in 2015 when Christoph Pojer and Dmitrii Abramov joined the project.
They really put in a lot of work to improve it, leading to the release of version 11.0 in April 2016, which marked a big change, and the first step towards it being a modern project
JS is used for lots of async code. It’s used in the browser and on phones, and in server side web applications. Asynchronous code is notoriously difficult to test and just to comprehend in general
Being real, most UIs see a lot of spaghetti code build up over time. That makes testing even harder.
All of these challenges and more add up to one real challenge: People don’t write tests.
Its hard. Its annoying. So people avoid testing or write inadequate tests. I’m certainly guilty of this, especially when I’m trying to go fast.
The problem is, since test suites gain in value the more comprehensive they are, and can be hard to build up, many folks never see any value from tests and may just give up.
What do you do when something is important but people don’t do it because its hard or not fun? You either dictate to them, tell them they have to do it, and then fight them over it… or you try to make the experience better.
Mocha Jasmine and Karma are big ones that have been around a while now.
My understanding is that Tape and Ava are big in node-world
QUnit was a jQuery project and is now widely used by the Ember community
The test libraries here provide assertion functions or other test utilities and aren’t full test runners.
Basically there are a lot of options.
So what I always want to know when I evaluate a new tool, especially in an area where there are lots of competitors, is — where does it fit in? How does it stand out (good and bad) against the other options?
Saves you time - gonna be talking a lot about that
Visual - information is presented clearly
Reliable - AFAIC remember I’ve only had a single bug the whole time I’ve been using Jest (A single bug with the framework, it’s caught a lot of my own bugs)
Learning curve was a big part of the overhaul of Jest over the course of 2016. Jest has simple concepts and complicated concepts, and previously the defaults required understanding the complicated concepts before using Jest. That is no longer the case, and it now has a nice learning curve.
So those were the pros, its also good to understand the limitations.
Jest is not simple. It still has plenty of concepts, and is more of a “do everything” library , not a “do one thing well” library. Those components are split out into separate modules though, so you can use parts of it for specific tasks if you want.
Jest has gotten a lot more stable in the past year, as it has become “good enough” for Facebook, but it is still making steady progress, and it won’t stay the same.
Alright that was the intro to Jest, now lets talk about how Jest can save you time.
I’m going to discuss 4 ways that Jest can save you time. As part of
Setting up tests Writing Tests Running Tests Fixing Tests
We’ll take them one at a time
The first way Jest helps you save time is during initial setup.
Jest only requires installing one or two dependencies to get a test environment going, and doesn’t require any config by default. It also provides ways to automate switching from other test libraries.
Please note that this slide is probably not completely fair. You definitely can set up a test environment with Jasmine that has fewer dependencies than what I’m showing, Karma is more flexible in what it can do than just running server side tests. There are other test frameworks that can be simple (AVA)
But Jest is difficult to make complicated in terms of dependencies and comes with a lot of common things out of the box.
Out of the box you get: Babel support Assertions library AND test runner Watch mode (I’ll talk more about that in a bit) And Code coverage
When using other testing tools, a lot of these features are split out into separate libraries that require custom setup and configuration to use.
I have one source file, and one test file, and I’ve written no configuration. I did set the nom script `test` to run jest
Here we have the source and test file in our simple project. A simple sum function, and 2 tests, one that should pass, and one that should fail (because 1 + 2 + 7 doesn’t equal 9). Note that we’re using modern import/export syntax, which is not supported on Node natively at this point. So we need to use babel to compile it
I’ll show stuff like this live in the demo later, but running npm test with this simple test, Jest is able to identify my test files and run them. That lookup is based on a few default regular expressions. All of that is configurable if you’re opinionated about how to structure your project, but you can also just enjoy the easy defaults and skip having a config file when you’re getting started.
So I already pointed out that this super simple little test is using babel syntax (the import/export). But we were able to run the test just fine. That means the test is running against transformed code, and that one liner of adding babel-jest let us run this test with no problems. Note that it still gets the line numbers right and everything when identifying failed tests.
<point out line 9 -> line 9>
Ok, another quick poll Who is using/has used any of the following libraries?
The stuff we’ve talked about before makes it nice to start new projects but what about those of you who are already invested in something?
Jest makes it easy to convert from other test frameworks with codemods. A code mod is a script to perform a specific transformation on a set of code, Jest uses them to transform code from other frameworks into something usable by Jest
It isn’t perfect, but it will let you know what it can convert and can’t and is a great start for moving tests over to a new system
Jest also helps you write tests fast.
Jest’s test syntax actually started out as a fork of Jasmine. It has since been extended and re-written but most Jasmine code can be used in Jest without any changes, and everything should feel very familiar
Jest also provides a simpler style that is reminiscent of other newer frameworks like Tape and AVA
Jest also provides great, detailed APIs for testing different specific scenarios
And finally, Jest’s signature feature is snapshot testing. I’ll be talking about that in more detail in a minute
So here’s an example of 2 tests using different syntaxes.
Jest makes it easy to write tests by NOT innovating on syntax. It lets you write tests in 2 different styles, and they both are pulled straight from widely used libraries.
You can see the first test here is written in the Jasmine “describe/it/expect” style, while the second one uses the simplified test syntax
The describe style can be nice when you want to group a set of tests with the same “beforeEach”/afterEach setup or cleanup steps. But otherwise, `test` is generally simpler. Either way you can use whatever is familiar or comfortable for you.
Jest provides really expressive assertion APIs that let us handle tricky situations like async functions, testing function behavior, and testing the shape of an object easily
The first test here demonstrates how Jest tests asynchronous code (a promise). If you’re not familiar with promises, they run a bit of code that can be asynchronous, and then call a resolve or reject callback when they’re completed. Other code can provide handlers for the resolved or rejected values. Asynchronous logic is usually annoying in tests, but Jest provides `resolve` and `reject` methods on expect that makes it easy to test the async values generated by a promise. And since its easy to wrap other async methods like `setTimeout` in a promise, this works for testing any async code.
The second test is showing how Jest handles mock functions. There’s nothing exciting here, but Jest provides methods for determining very specifically how a given function was called or not called.
The final test is showing a few of the methods we have for checking the shape of an object. The first test is `toEqual`, which does a recursive deep match. That fails because the object isn’t exactly the same. The second is `toMatch`, which looks to see if the object has the same properties as what it is being tested against (but ignores other things). That passes. The third test just looks to see if an object has a specific property. All 3 can be useful depending on how much control you want to have over a test result.
These are just examples, Jest has over 25 different specific assertions you can use.
Detailed APIs like this help you write tests that aren’t too boilerplate-heavy, don’t need a bunch of setup code, and also don’t result in too much rigidity and break too easily.
So this is something I just saw this morning on Twitter. Look at this whole library of extra matchers to play with! Thats the benefit of Jest having an extensible core.
Snapshot tests are Jest’s signature feature. They’re a way of testing that the results of a particular operation have not changed, or seeing how they have changed, rather than comparing them to a universally expected outcome.
Jest’s snapshot tests have really nice react handling out of the box, but can be used against lots of things, including other UI libraries. Pretty much anything that can be described as a JSON object can be snapshot tested
Ok so there is a lot of code on this slide. Lets break it down:
This is code for a simple link component. (It’s actually from the Jest repo’s example list, but it’s pretty perfect as an example, so I’m stealing it)
We have 3 files here, a link source file, a link test file (note the `toMatchSnapshot` syntax), and a snapshot file. The snapshot file shows the result of running the 2 tests in the test file.
But what happens if we change something?
So if we just change the test to have a new default value for the link’s href…
We can run Jest and see 2 tests are failing, and we get a diff for what is different in those tests.
For something like this where its a direct change to the same component, that may not be too interesting. But this can be very helpful for showing side effects and letting us know all the places effected by a change. It also can show which states change when we make a change to logic.
If we’re satisfied that the changes we saw are ok, we can run jest -u to update. This updates the snapshots, and once they’re checked into git, they become the new basis of comparison when the test is run in the future.
So lets talk pros and cons:
Snapshot tests are good for things that are going to change a lot, and also good for generating a lot of tests quickly.
However they require good code review, and tend to be less helpful at communicating the original developers intent
I find them really useful for UI tests, where the real world alternative would be not having real tests since the code changes so often and in arbitrary ways, and for running code against a large amount of real world data so I can observe the effect of changes against that data.
For example I recently used it when I wrote a function that took a JSON format describing data for a graph, and converted it to a configuration for the charting library I was using. I had 20some graph configs actually being used in my application, so I took snapshots of the configs generated for each of them, so that I could see how they changed if I ever changed the transformation logic. It wouldn’t have been worth writing 20 detailed tests laying out the exact shape for the data, but it took me 2 minutes to copy and paste the data into a test file and set up a snapshot test
Jest saves you time by running tests quickly.
But the more interesting touches are more about UX. Smart testing and watch mode.
Smart tests are really what makes Jest run fast. Jest can give you instant feedback on your changes, because it only runs the tests it needs. Even if you have a gigantic 5000 test project, it gives feedback quickly because it only runs a few tests at a time, and you don’t have to run special scripts to accomplish that.
Instead Jest uses git and import tracking to determine what files have changed and which files depend on other files. It builds a dependency graph and then only runs tests when they change or a file they depend on changes.
Smart testing is made even better by watch mode. You can leave it on all the time and it will update with feedback as you make changes. This will show a bit better with the demo in a second.
The last way Jest saves you time is by helping you fix tests fast. I’m not going to get into this too much today, but this is also really about the UX touches, with good error reporting, making it easy to see if your fixes worked, and editor integration to Visual Studio Code.
Ok demo time!
I always like to talk about how things are changing, not just how they are now. So whats next for Jest?
Jest has settled down a bit after a lot of changes in the past 2 years, but there are still interesting things on the horizon.
They’re investigating using the jest test runner for tests in other programming languages like Python.
There also is interest in allowing parts of Jest to run in the browser, and adding first class support to more editors. I know they’re looking for contributors to tackle all of those things, so if you’re inspired to contribute to open source after this conference, feel free to checkout their GitHub page
Saving Time By Testing With Jest
Saving Time By
Testing With Jest
Who Am I?
• Senior Software Engineer @ Windsor Circle
• Live in Durham NC
• Jest user since early 2016
• Blogger @ benmccormick.org
What To Expect
• What is Jest?
• What problems does it try to solve?
• How can it save me time?
• Q & A
So What Is Jest?
• Developed by Facebook for internal testing needs
• Open Sourced in 2014
• Mostly stagnant for 2 years
• Revived in late 2015 / early 2016
• Many Environments
• Async Code
• User Interface code is hard to test
• People don’t write tests
Prior Art: Who has been facing these
• Test Runners: Mocha, Jasmine, Karma, Tape, AVA,
• Test libraries: Chai, Sinon, should.js, expect.js,
How Does Jest Fit In?
• Jest saves you time
• Jest is visual
• Jest is reliable
• Jest (now) has a good learning curve
How Does Jest Fit In?
• Jest does not test every environment
• Jest is not simple
• Jest is still growing and changing
How Does Jest Save You Time?
• Setting Up Tests: Simple configuration
• Writing Tests: Simple UI tests, familiar syntax
• Running Tests: Fast startup, fast test runs, smart
• Fixing Tests: Clear error and failure messages
• 1 Dependency for Test Runner, assertion library, code
• No extra configuration for Babel support (just 1
• Sane defaults (run anything in a __tests__ directory)
• Codemods to transition from other libraries
Setup Fast: One Dependency
Karma + Jasmine (Vue.js) Jest
*Not necessarily optimized
Write Tests Fast: Snapshot Tests
• Captures the current state of the code
• Future runs compare the state to the previous state of
• Has special handling for React components by default
• Can write serializers for other type of data
We updated the component to add a #test as the default
Write Tests Fast: Snapshot Tests
• Pro: Quick To Write and update
• Pro: Catch side effects
• Con: Don’t enforce correctness/communicate
• Con: Require a strong process backing them up
• Good for: UI tests, runs against large amounts of real
Run Tests Fast
• Tests Run in Node, no browser overhead
• Tests Run in Parallel
• Smart Testing - only run the tests that changed
• Watch Mode
Run Tests Fast: Smart Tests
• Jest is aware of modules
• Runs tests when any
dependency of the test (or the
test itself changes)
• Git based
• Don’t run unnecessary tests!
Run Tests Fast: Watch Mode
• Watch mode is a cli that
watches for file changes
• Can control which tests are
Fix Tests Fast
• Failed Tests Run First
• Accurate error reporting by line
• Editor Integration (VS Code)