Successfully reported this slideshow.
Your SlideShare is downloading. ×

Saving Time By Testing With Jest

More Related Content

Related Books

Free with a 30 day trial from Scribd

See all

Saving Time By Testing With Jest

  1. 1. Saving Time By Testing With Jest Ben McCormick Windsor Circle Twitter: @ben336 Blog: http://benmccormick.org
  2. 2. Who Am I? • Senior Software Engineer @ Windsor Circle • Live in Durham NC • Jest user since early 2016 • Blogger @ benmccormick.org
  3. 3. What To Expect • What is Jest? • What problems does it try to solve? • How can it save me time? • Demo • Q & A
  4. 4. 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
  5. 5. JavaScript Testing Challenges • Many Environments • Async Code • User Interface code is hard to test
  6. 6. JavaScript Testing Challenges • People don’t write tests
  7. 7. Prior Art: Who has been facing these problems? • Test Runners: Mocha, Jasmine, Karma, Tape, AVA, QUnit • Test libraries: Chai, Sinon, should.js, expect.js, Istanbul
  8. 8. How Does Jest Fit In? • Jest saves you time • Jest is visual • Jest is reliable • Jest (now) has a good learning curve
  9. 9. How Does Jest Fit In? • Jest does not test every environment • Jest is not simple • Jest is still growing and changing
  10. 10. 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 watch mode • Fixing Tests: Clear error and failure messages
  11. 11. Setup Fast • 1 Dependency for Test Runner, assertion library, code coverage • No extra configuration for Babel support (just 1 dependency) • Sane defaults (run anything in a __tests__ directory) • Codemods to transition from other libraries
  12. 12. Setup Fast: One Dependency Karma + Jasmine (Vue.js) Jest *Not necessarily optimized
  13. 13. Setup Fast: Minimal Project
  14. 14. Setup Fast: Minimal Project
  15. 15. Setup Fast: Sane Defaults
  16. 16. Setup Fast: Easy Babel Support
  17. 17. Quick Poll: • Mocha • Jasmine • Chai • AVA • expect.js • Should.js • Tape • Proxyquire
  18. 18. Setup Fast: Codemods https://www.npmjs.com/package/jest-codemods
  19. 19. Write Tests Fast • Familiar syntax: Jasmine or `test()` style • Great mocking + assertion APIS • Snapshot Tests!
  20. 20. Write Tests Fast: Syntax
  21. 21. Write Tests Fast: APIs
  22. 22. Write Tests Fast: Extensible APIs
  23. 23. Write Tests Fast: Snapshot Tests • expect(<json>).toMatchSnapshot() • Captures the current state of the code • Future runs compare the state to the previous state of the code • Has special handling for React components by default • Can write serializers for other type of data
  24. 24. We updated the component to add a #test as the default
  25. 25. `jest -u` updates snapshots to the new state
  26. 26. Write Tests Fast: Snapshot Tests • Pro: Quick To Write and update • Pro: Catch side effects • Con: Don’t enforce correctness/communicate developer intent • Con: Require a strong process backing them up • Good for: UI tests, runs against large amounts of real world data
  27. 27. Run Tests Fast • Tests Run in Node, no browser overhead • Tests Run in Parallel • Smart Testing - only run the tests that changed • Watch Mode
  28. 28. Run Tests Fast: Smart Tests • Jest is aware of modules dependency Graph • Runs tests when any dependency of the test (or the test itself changes) • Git based • Don’t run unnecessary tests!
  29. 29. Run Tests Fast: Watch Mode • Watch mode is a cli that watches for file changes • Can control which tests are watched
  30. 30. Fix Tests Fast • Failed Tests Run First • Accurate error reporting by line • Editor Integration (VS Code)
  31. 31. DEMO
  32. 32. The Future? • Multi Language Support • More environment Support? • More Editor Integrations ? Repo: https://github.com/facebook/jest
  33. 33. Want more detail?
  34. 34. Questions?
  35. 35. Ben McCormick Windsor Circle Twitter: @ben336 Blog: http://benmccormick.org

Editor's Notes

  • Hi everyone!

    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.

    I’ve been using Jest since early 2016, and I write about Jest and other JavaScripty topics on my blog at benmccormick.org.

    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:

    I want you to raise your hand if you’ve:
    Ever written a test for JavaScript code
    Written a test in the last month
    Wrote a test today (During the conference!)
    Write tests for all of your new code

    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?

    Jest is an Open Source JavaScript testing framework developed by Facebook.

    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

    I will note that Jest works well with Facebook’s other projects like React, but is not “for” them, and can be used in many JavaScript environments.

    Now before we go further, lets take a step back and talk about the state of JavaScript testing
  • JavaScript has some distinct challenges. I wouldn’t say these are unique challenges, but rather challenges that are more common in the situations where JavaScript is used.

    JavaScript runs in a lot of places: Node, different browsers, React Native, Electron. That means compatibility is a big deal. And some of those environments are more amenable to testing than others.

    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

    Lots of JavaScript is used for building UIs and UIs are hard to test
    Requirements change a lot for UIs, and its difficult to define a UI to the level of detail needed to run adequate tests much less maintain that over time.

    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.
  • Jest is not the first attempt to solve these problems. There are a lot of JavaScript testing libraries out there.

    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?

    Jest

    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 does not test every environment. I mentioned earlier that multiple environments was a JavaScript testing challenge. Jest does not attempt to address that as it exists today. It runs all of its tests against a virtualized DOM (jsDOM) in Node, and doesn’t run against a browser at all.

    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.
  • This is an example of fairly normal setups for local testing of JavaScript using Jest vs an older test framework.

    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.
  • So this is an example of a minimal project. All I’ve done is pull in Jest, babel-jest, and a babel preset package (if you don’t use babel, Babel is a tool that transforms JavaScript using newer or experimental syntax into code based on an older more compatible subset of the language. The preset just tells babel how I want the code to be transformed)

    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.

    Some of this is just how Jest runs tests. For many traditional JavaScript testing methods, tests run in a browser, which leads to slowness and flakiness when setting up and communicating with an external application. Jest runs tests in Node against a virtual DOM, and therefore has very little overhead on startup. Jest can also run tests in parallel, while sandboxing the tests so that they don’t conflict with each other

    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

×