Series: Automated Testing

Testing Part 4-Our first Acceptance Test

Published on Oct 29, 2016

Our first acceptance test!

Along the way we learn the basics of several synchronous and asynchronous helpers (visit, find, currentURL, andThen), the equality assertion, and how to set up the testing environment.


Links

Code

$ ember g acceptance-test monster-index
//tests/acceptance/monster-index-test.js
import { test } from 'qunit';
import moduleForAcceptance from 'crud-2016/tests/helpers/module-for-acceptance';

moduleForAcceptance('Acceptance | monster index');

test('visiting /monsters', function(assert) {
  server.createList('monster', 10);

  visit('/monsters');

  andThen(function() {
    assert.equal(currentURL(), '/monsters');
    assert.equal(find('.monster').length, 10);
  });
});

Transcript

In the last couple of episodes, we learned some useful things, one of which was how to setup ember-cli-mirage and then generate a bunch of data from that. And then the other thing was how to run our tests by typing ember test --server. Now that this infrastructure is set up, it’s time to generate our first test.

So we’ll do that by typing ember g acceptance test, and we’ll call this one monster index. So it creates a file at test/acceptance/monster-index-test. We’ll look at that file very soon, but first notice that our tests are now failing. Also notice that previously it was saying 59 out of 59 and now it’s saying 60 out of 62, so interesting it seems to have generated three instances of things that could pass or fail, and two of those are failing. So now let’s go to our test.

So up at the top it has a bit of boilerplate, so moduleForAcceptance is what sets up a lot of the things to create an acceptance test. And an acceptance test is basically you run your entire app, and then you can do various things in the app. It’s as if a user was clicking around on it. So let’s change this to a very simple working acceptance test. So it automatically generated it with the url monster-index. Let’s just change it to monsters, which is the url that we’re using. And then with that, we’ll be able to see that all of them are passing. But that’s not testing very much. That’s basically testing that there is a url at /monsters, and that when you visit it it doesn’t explode. We’re going to test a little bit more soon, but first let’s explain what’s happening here.

So a visit is a helper that takes you to visit a certain page in your app, and it’s an asynchronous helper. There are several of these such as visit and click. What sets these apart is that they’re aware of promises. So if you have say a promise in your model hook that is... let’s go ahead actually to our route for monsters. So this.store.findAll is a promise, and visit is aware of that promise and so it won’t move on to the next line until findAll has completed and that promise is returned. So these asynchronous helpers you could just keep on stacking them, keep on clicking things. And then there are synchronous helpers such as assert.equal, and for those you’ll want to wrap them in an andThen, so an andThen and then a function inside that and then you do your assertions and other synchronous things.

Here we’re asserting that the current url which is a synchronous helper that’s available to you is equal to /monsters, basically that we’re at the correct route. Now it’s time to make a more specific assertion. So we’ll assert that... we’re going to find number of monsters, whatever that ends up being, and assert they’re equal to 10. And how we can do this is we can use the find helper, and so it’ll find based on css selectors, so we’ll use the monster class, and there are some good arguments to be made for having a separate thing for finding via tests, so it’d be like monster-list-item-test, something that could be only found, it’s only used for this set of tests. But we’re going to go ahead and just use what we already have. So we’re going to find the monster and we’re going to get the length, and we’ll see what our tests have to say about that.

Well, it first says that we’re missing a semicolon, and then it says it fails because it expected 10. We know it expected 10. What did we actually get? Well, let’s go ahead and go to the more useful version of this. Okay, so here we can see the actual result compared with the expected. So we actually got zero, and that is because this test does not use the mirage scenario. So we’ve been inserting 10 on into the server in our default scenario, but that is for development.

So what we can do here is just like we created a list of monsters, there we can do the same thing in the monster-index-test. So we’re going to put in the same thing. We’re going to create a list of monsters, and we’re going to do it before we visit the page. That’s very important. And here we can see all the tests are now passing.

So that is our first acceptance test, visiting a page with monsters on it, and checking that the right amount of monsters were there. We’ll of course be doing more complex acceptance tests in the videos to come. If you’re curious about the various helpers, there’s a list of the built-in helpers in the ember guides. I’ll link to that in the show notes. So it has the asynchronous helpers, there are five built-in including visit which we used, and then several synchronous helpers. assert.equal is not in this list, but it comes in via our test helper here, which is imported from qunit, and then server.createList comes from ember-cli-mirage.

Alright, I’ll see you next week where we make another, more complex acceptance test.

Automated Testing

Subscribe to our mailing list