Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Test-driven Client-side JS

Pete Hodgson
February 04, 2015

Test-driven Client-side JS

Presented at ForwardJS, Feb 2015
VIDEO: https://forwardjs.com/lectures/33

Writing high quality, maintainable client-side code is becoming increasingly important as we continue to move more logic into the browser. This talk will show how unit-testing and test-driven development helps you build better quality code, faster.

We'll see examples of building a React app test-first, then look at techniques and tools to solve the trickier parts of unit-testing in JavaScript. You'll see how TDD guides us towards cleaner and more maintainable code, with clear separation between your application logic and the browser's 'ideosnycractic' APIs.

Pete Hodgson

February 04, 2015
Tweet

More Decks by Pete Hodgson

Other Decks in Programming

Transcript

  1. TEST-DRIVEN
    CLIENT-SIDE APPS
    Pete Hodgson
    @ph1 | [email protected]

    View Slide

  2. UNIT

    TESTING

    View Slide

  3. TEST
    DRIVEN
    DEVELOPMENT

    View Slide

  4. me me me
    Pete Hodgson
    Consultant at ThoughtWorks
    @ph1
    blog.thepete.net

    View Slide

  5. WRITE A

    FAILING TEST
    GET THE TEST
    TO PASS
    REFACTOR

    View Slide

  6. WRITE A

    FAILING TEST
    GET THE TEST
    TO PASS
    REFACTOR

    View Slide

  7. FEEDBACK

    View Slide

  8. NXTBRT.COM

    View Slide

  9. the

    backend
    the

    browser

    single-page
    javascript
    app
    REACT
    {JSON}

    View Slide

  10. {
    dest_name: “Richmond”,
    etd: 8,

    }
    Departure Domain Object
    {
    destination: “Richmond”,
    departing: “8 mins”
    }
    View Object
    presenter
    function

    View Slide

  11. var presentDeparture = function(departure){
    return {
    destination: departure.dest_name
    };
    };

    View Slide

  12. var departurePresenter = require('../../js/departure_presenter');
    !
    describe( 'Departure presenter', function(){
    it('presents the destination', function(){
    // Given
    var departure = {
    dest_name: "Ontario",
    etd: 10
    };
    // When
    var viewModel = departurePresenter(departure);
    // Then
    expect(viewModel).to.have.property('destination','Ontario');
    });
    });

    View Slide

  13. var departurePresenter = require('../../js/departure_presenter');
    !
    describe( 'Departure presenter', function(){
    it('presents the destination', function(){
    // Given
    var departure = {
    dest_name: "Ontario",
    etd: 10
    };
    // When
    var viewModel = departurePresenter(departure);
    // Then
    expect(viewModel).to.have.property('destination','Ontario');
    });
    });

    View Slide

  14. {
    dest_name: “Richmond”,
    etd: 8,

    }
    Departure Domain Object
    {
    destination: “Richmond”,
    departing: “8 mins”
    }
    View Object

    View Slide

  15. {
    dest_name: “Richmond”,
    etd: 8,

    }
    Departure Domain Object
    {
    destination: “Richmond”,
    departing: “8 mins”
    }
    View Object

    View Slide

  16. FEEDBACK

    View Slide

  17. RAPID
    FOCUSED
    ACCURATE
    FEEDBACK

    View Slide

  18. 25

    View Slide

  19. 26

    View Slide

  20. 27

    View Slide

  21. 27
    TEST SCOPE

    View Slide

  22. TEST SCOPE
    DOM
    HTTP
    28

    View Slide

  23. 29

    View Slide

  24. 30
    ISOLATION

    View Slide

  25. 30
    ISOLATION
    test
    code

    View Slide

  26. presenter
    function
    test
    code

    ISOLATION

    View Slide

  27. departures
    gateway
    controller
    AJAX
    function
    “station-id”
    GET

    http://blah/station-id
    LIST OF
    DEPARTURE OBJECTS
    BIG BLOB

    OF JSON

    View Slide

  28. 34

    View Slide

  29. HTTP
    35
    ajax
    function

    View Slide

  30. 36
    fake
    ajax
    function

    View Slide

  31. 36
    fake
    ajax
    function

    View Slide

  32. departures
    gateway
    test
    code
    mock

    ajax fn

    View Slide

  33. departures
    gateway
    test
    code
    “station-id”
    “http://blah/station-id”
    mock

    ajax fn

    View Slide

  34. departures
    gateway
    test
    code
    CORRECTLY-PARSED
    DOMAIN OBJECT
    SOME JSON
    mock

    ajax fn

    View Slide

  35. it( 'parses the AJAX response as JSON', function(){
    // Given
    var fakeJson = '{ "some":"json" }';
    var fakeAjaxResponse = Q(fakeJson);
    var fakeAjaxFn = function(){
    return fakeAjaxResponse;
    };
    !
    var departuresGateway = createDeparturesGateway(fakeAjaxFn);
    !
    // When
    var departuresPromise = departuresGateway.fetchDeparturesFor('blah');
    !
    // Then
    return expect(departuresPromise)
    .to.eventually
    .deep.equal({some:"json"});
    });

    View Slide

  36. RAPID
    FOCUSED
    ACCURATE
    FEEDBACK

    View Slide

  37. 42
    ISOLATION

    View Slide

  38. mocha test runner
    chai assertion library
    gulp task runner, file watcher
    testem browser manager
    sinon stubbing/mocking
    chai-as-promised

    View Slide

  39. 45
    github.com/moredip/test-driven-react
    @ph1 | [email protected]
    http://slides.thepete.net

    View Slide