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

Testing - The Next Frontier

Testing - The Next Frontier

Talk given at the Boston Ember meetup on 2016-03-10.

Robert Jackson

March 10, 2016
Tweet

More Decks by Robert Jackson

Other Decks in Programming

Transcript

  1. Testing: The Next
    Frontier?

    View full-size slide

  2. Who the heck is this guy?
    ● Ember Core Team
    ● Twitch
    ● General Open Source Addict
    twitter: rwjblue
    github: rwjblue

    View full-size slide

  3. What are we talking about?

    View full-size slide

  4. State of Testing Today
    ● Acceptance
    ● Integration
    ● Unit

    View full-size slide

  5. Acceptance
    moduleForAcceptance('Acceptance | login');
    test('visiting /login', function(assert) {
    visit('/login');
    andThen(function() {
    assert.equal(currentURL(), '/login');
    });
    });

    View full-size slide

  6. Integration
    moduleForComponent('pretty-color', {
    integration: true
    });
    test('button click', function(assert) {
    this.render(hbs`{{magic-title}}`);
    this.$('button').click();
    assert.equal(this.$().text(), 'This is Magic');
    });

    View full-size slide

  7. Unit
    moduleFor('route:application');
    test('perform the right query', function(assert) {
    let route = this.subject();
    let result = route._queryString();
    assert.equal(result, '?awesome=sauce');
    });

    View full-size slide

  8. Great, :shipit:

    View full-size slide

  9. ● Built for a globals world.
    ● “magic” `andThen`
    ● No ability to stub/mock services.
    Acceptance Test Issues

    View full-size slide

  10. ● Completely ignorant about async
    ● Manual triggering of user interaction
    ● Much less “tailored” API
    Unit/Integration Test Issues

    View full-size slide

  11. emberjs/rfcs#119

    View full-size slide

  12. ● Use `async` / `await`
    ● Consistent interface
    ● Extendability
    ● Backwards Compatibility
    Grand Testing Unification

    View full-size slide

  13. Acceptance
    moduleForAcceptance('Can see things');
    test('clicking redirects', async function(assert) {
    await visit('/things');
    let list = find('.thing-item');
    assert.equal(list.length, 5);
    await click('.thing-item[data-id=1]');
    assert.equal(this.currentRouteName, 'other-
    thing');
    });

    View full-size slide

  14. Integration
    moduleForIntegration('post-display');
    test('expand when clicked', async function(assert) {
    await render(hbs`{{post-display}}`);
    await click('.post-item');
    assert.equal(
    this.find('.post-created-at').textContent,
    '2016-01-05'
    );
    });

    View full-size slide

  15. ● Overriding a service
    ● Registering custom test helpers
    ● Registering custom waiters
    ● Accessing service instances
    General Testing Concerns

    View full-size slide

  16. ● Hooks for work before/after tests.
    ● Accessing general test information
    General Testing Concerns

    View full-size slide

  17. Overriding a Service
    import Mock from 'somewhere/else';
    moduleForAcceptance('something', {
    beforeEach() {
    this.owner.register('service:stripe', Mock);
    }
    });

    View full-size slide

  18. Registering Custom Helpers
    import selectCategory from '../helpers/select-category';
    import loginAsAdmin from '../helpers/login-as-admin';
    moduleForAcceptance('Can see things', {
    beforeEach() {
    this.registerHelpers({
    loginAsAdmin, selectCategory
    });
    }
    });

    View full-size slide

  19. Custom Helpers
    // tests/helpers/login-as-admin';
    import { testHelper } from 'ember-qunit';
    export default testHelper(async function() {
    await this.click('.login-now');
    await this.fillIn('.username', 'rwjblue');
    await this.fillIn('.password', 'moar beerz plz');
    await this.click('.submit');
    });

    View full-size slide

  20. Custom Helpers
    import selectCategory from '../helpers/select-category';
    import loginAsAdmin from '../helpers/login-as-admin';
    moduleForAcceptance('Can see things', {
    beforeEach() {
    this.registerHelpers({
    loginAsAdmin, selectCategory
    });
    }
    });

    View full-size slide

  21. Custom Waiters
    import { testWaiter } from 'ember-test-helpers';
    import { hasPendingTransactions } from 'app-
    name/services/transactions';
    export default testWaiter(function() {
    return hasPendingTransactions();
    });

    View full-size slide

  22. Custom Waiters
    import transactionWaiter from '../waiters/pending-transactions';
    test('stuff happens', async function(assert) {
    // Normally done in setup, but slides....
    this.registerWaiter(transactionWaiter);
    await click('.foo');
    // all pending transactions are completed here...
    });

    View full-size slide

  23. Accessing Services
    test('foo', function(assert) {
    this.store = this.owner.lookup('service:store');
    this.store.push(....);
    });

    View full-size slide

  24. General Hooks
    // */tests/configuration.js
    import { TestConfig } from 'ember-test-helpers';
    export default class extends TestConfig {
    beforeSuite() {}
    beforeEach(testType, testContext) {}
    afterEach(testType, testContext) {}
    }

    View full-size slide

  25. General Hooks
    // liquid-fire's addon-test-support/configuration.js
    import { TestConfig } from 'ember-test-helpers';
    import runningTransitionWaiter from './waiters/running-transition';
    import randoHelper from './helpers/rando';
    export default class extends TestConfig {
    beforeEach() {
    this.registerWaiter(runningTransitionWaiter);
    this.registerHelper('randoHelper', randoHelper);
    }
    }

    View full-size slide

  26. General Hooks
    // mirage's addon-test-support/configuration.js
    import { TestConfig } from 'ember-test-helpers';
    import setup from 'ember-cli-mirage/setup-server';
    export default class extends TestConfiguration {
    beforeEach() {
    this.server = setup(this.owner);
    }
    }

    View full-size slide

  27. Test Information
    import { testHelper } from 'ember-qunit';
    export default testHelper(function() {
    if (this.testInfo.type === 'acceptance') {
    // acceptance test stuff here
    } else {
    // integration/unit test stuff here
    }
    });

    View full-size slide