$30 off During Our Annual Pro Sale. View Details »

System Testing an API with NodeJS and Mocha

System Testing an API with NodeJS and Mocha

Do you test as much as you think you should? Or, even if you write tests, are you still confused about the different types of tests, how to structure and name your tests, or even what to test in the first place?

In this talk, Daniel Bostwick will walk through how he structures a NodeJS project for testing, integrates the Mocha and Chai testing frameworks, discuss the guidelines he uses for figuring out what to test, and show an examples of how to functionally test a backend API. You'll come away with a better understanding of BDD, learn how to functionally test any api, and be inspired to better test your own APIs.

Daniel Bostwick

September 24, 2015
Tweet

Other Decks in Programming

Transcript

  1. System Testing an API

    with NodeJS and Mocha
    1

    View Slide

  2. 2
    Daniel Bostwick
    cantina.co

    danielbostwick.com


    github.com/bostwick

    linkedin.com/in/dbostwick
    Senior Technical Consultant

    View Slide

  3. 3
    Testing Philosophy

    View Slide

  4. 4
    Testing Misconceptions
    What testing is not

    View Slide

  5. 5
    You Need To Test

    View Slide

  6. 6
    You Need To Test
    Testing is not a requirement
    for a successful* project.
    *depending on your definition of success.

    View Slide

  7. 7
    You need 100%
    test coverage

    View Slide

  8. 8
    You need 100%
    test coverage
    100% Coverage is a great
    ideal, but any coverage will
    help improve a project.

    View Slide

  9. 9
    Testing proves your
    program is correct
    or free of bugs

    View Slide

  10. 10
    Testing proves your
    program is correct
    or free of bugs
    Unless you’re using formal
    verification systems, testing
    can prove nothing.

    View Slide

  11. 11
    Writing tests means
    you can “grow” your
    architecture over time,
    instead of up front

    View Slide

  12. 12
    Writing tests means you
    can “grow” your
    architecture over time,
    and not make decisions
    up front
    If you don’t know how to
    implement something to
    start, following TDD will not
    help you figure it out.
    http://ravimohan.blogspot.com/2007/04/learning-from-sudoku-solvers.html

    View Slide

  13. 13
    So, Why Write Tests?

    View Slide

  14. If you aren’t testing, your users are.
    14
    Because it’s inevitable.

    View Slide

  15. - Ronald Reagan
    15
    Trust, but verify.

    View Slide

  16. 16
    Testing demonstrates the behavior
    of software.

    View Slide

  17. 17
    A test ensures that a system behavior
    remains constant even as the underlying
    implementation may change.

    View Slide

  18. “If builders built buildings the way programmers wrote programs, then
    the first woodpecker that came along would destroy civilization.” 

    - Gerald Weinberg
    18
    Testing inspires confidence

    View Slide

  19. 19
    What should be tested?

    View Slide

  20. 20
    It’s not about
    Code Structure
    “use strict”


    module.exports = {

    sayHello: function(name) {

    return “Hello, “ + name;

    }

    };



    if (require.main === module) {

    console.log(sayHello(“World”));

    }

    View Slide

  21. 21
    It’s about
    Behavior.
    When I run hello.js,
    I want to print “Hello, World.”
    so I can have an example for this
    presentation .

    View Slide

  22. 22
    Behavior The way in which a system acts
    in response to a particular
    situation or input.

    View Slide

  23. 23
    Job Story When ______________ ,
    I want to _______________ ,
    so I can _______________ .

    View Slide

  24. 24
    Behavior is
    independent of
    implementation.
    # This passes, too!

    “use strict”

    console.log(“Hello, World”);

    View Slide

  25. 25
    Test Categories
    Unit Tests
    Integration
    Tests
    System Tests

    View Slide

  26. 26
    How to Test?

    View Slide

  27. jsUnit, jUnit, OCUnit, Test::Unit, PyUnit
    27
    xUnit You already have it.

    View Slide

  28. 28
    Naming Tests
    How it’s
    taught.
    “use strict”


    module.exports = {

    sayHello: function(name) {

    return “Hello, “ + name;

    }

    };
    “use strict”


    var myLib = require(“hello-lib”);


    function testSayHello() {

    assert(myLib.sayHello(“World”) ===

    “Hello, World”);

    }

    View Slide

  29. 29
    Job Story When ______________ ,
    I want to _______________ ,
    so I can _______________ .

    View Slide

  30. 30
    Behavior-Based
    Test Names
    function

    testSayHello_givenName_returnsHelloName
    function
    testSayHello_givenUndefined_returnsNonsense
    function
    testSayHello_givenObject_returnsHelloObjectObject
    http://dannorth.net/introducing-bdd/

    View Slide

  31. 31
    Spec-Based
    Testing
    define(“sayHello”, function() {

    define(“given a name”, function() {

    it(“returns ‘Hello, {Name}’”, …);
    });

    define(“given a number”, function() {

    it(“returns ‘Hello, {Number}’”, …);
    });
    });

    View Slide

  32. 32
    Your test names should be executable
    documentation.

    View Slide

  33. 33
    Writing System Tests for an API

    View Slide

  34. 34
    Use Cases for API System Tests
    Building your own API
    • Write your API documentation as
    executable tests.
    • Know when the API demonstrates the
    required behavior for implementation.
    • Provides a “definition of done.”
    Integration with a 3rd-Party API
    • Verify the 3rd-Party API works as the
    vendor says it should.
    • Expose and document any
    inconsistencies between Vendor’s docs
    and the actual behavior.

    View Slide

  35. 35
    Tools
    1. NodeJS
    2. Mocha & Chai

    http://mochajs.org/, http://chaijs.com/
    3. request

    https://github.com/request/request

    4. Bluebird Promises

    https://github.com/petkaantonov/bluebird

    View Slide

  36. 36
    Project
    Structure
    project-name/
    [bin]/
    [config]/
    src/ or lib/
    project-name/
    test/

    project-name/
    helpers.js

    Readme.md
    package.json

    View Slide

  37. 37
    Installation $ npm install —save-dev
    mocha chai bluebird request

    View Slide

  38. 38
    Running the
    Tests
    $ # From the project dir
    $ ./node_modules/.bin/mocha test/**/*
    # Put this in your package.json:

    “scripts”: {
    “test”: “./node_modules/.bin/mocha
    test/**/*”
    }
    $ npm test

    View Slide

  39. 39
    Testing the Climb Higher API

    View Slide

  40. 40
    Climb Higher API
    GET, PUT /user
    POST /users
    GET, POST /sessions
    GET, PUT, DELETE /sessions/:sessionId
    POST
    /sessions/:sessionId/ticks
    DELETE /sessions/:sessionId/ticks/:tickId

    View Slide

  41. 41
    System Test Setup & Teardown
    https://github.com/climbhigher/climbhigher-api/blob/master/test/climb-
    higher/routes.js#L14

    View Slide

  42. 42
    Simple Endpoint Test
    https://github.com/climbhigher/climbhigher-api/blob/master/test/climb-
    higher/routes/get-user.js

    View Slide

  43. 43
    Complicated Endpoint Test
    https://github.com/climbhigher/climbhigher-api/blob/master/test/climb-
    higher/routes/post-session-ticks.js

    View Slide

  44. 44
    Extract Common Helpers
    https://github.com/climbhigher/climbhigher-api/blob/master/test/
    helpers.js

    View Slide

  45. 45
    What about unit tests?

    View Slide

  46. 46
    Review
    • Testing is not a magic silver bullet.
    • Testing gives you confidence about behavior.
    • Use Job Stories to define behavior.
    • Name your tests based on a system’s behavior.
    • It’s easy to test both your own code and other’s with System tests.
    • Mocha and BDD give you readable, executable documentation.

    View Slide

  47. 47
    Thank You
    Questions Welcome

    View Slide