Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Ember acceptance testing


May 09, 2021 Ember.js Reference documents


Table of contents


Acceptance testing

Create ember generate acceptance-test such as:

  1. ember g acceptance-test login

After executing the command, you get the following file content:

  1. //tests/acceptance/login-test.js
  2. import { test } from 'qunit';
  3. import moduleForAcceptance from 'people/tests/helpers/module-for-acceptance';
  4. moduleForAcceptance('Acceptance | login');
  5. test('visting /login' function(assert) {
  6. visit('/login');
  7. andThen(function() {
  8.  assert.equal(currentURL(), '/login');
  9. });
  10. });

moduleForAcceptance to start and terminate programs. The last few test contain an example.

Almost all tests have a routing request that interacts with the page (via helper) and checks that the DOM is changing as expected.

For example:

  1. test('should add new post' function(assert) {
  2. visit('/posts/new');
  3. fillIn('input.title' 'My new post');
  4. click('button.submit');
  5. andThen(() => assert.equal(find('ul.posts li:first').text(), 'My new post'));
  6. });

In general, go to route /posts/new fill in my new post in input.title in the input My new post button.submit and the desired result is: ul.posts li.first under the corresponding list My new post .

Test the assistant

A major problem in test web applications is that because the code is event-driven, they can be 异步 and cause the code 无序 order.

For example, there are two buttons that load data from different servers, and we click on them one after another, but perhaps the results are not returned in the order in which we clicked.

When you're writing tests, you need to pay special attention to the fact that you're not sure if you'll get a response back as soon as you make a request. T herefore, your assertion needs to be in a synchronized state to wait for the body to be tested. For example, in the example above, you should wait for both servers to return data before the test code executes its logic to detect the correctness of the data.

That's why, when making assertions, the Ember test assistant is wrapped in code that ensures synchronization status. This avoids doing such packages for all such code and improves the readability of the code by reducing the template code.

Ember contains multiple test aids to assist with acceptance testing. There are two types: asynchronous assistant asynchronous sync assistant synchronous

Asynchronous test assistant

The asynchronous test assistant is aware of the asynchronous behavior in the program, making it easier for you to write exact tests.

At the same time, these test assistants are executed in the order in which they are registered and are chained. E ach test assistant call is made after the previous call has ended before the next one is executed. Therefore, you can do this without having to be careful about testing the order in which the assistant performs.

  • click(selector)
    • Clicking on an element triggers the click event bound by click returning an asynchronously executed successful promise
  • fillIn(selector, value)
    • Fill the selected input element with the successfully executed promise value. Use As when, remember The value of value is the 所指定的值,并不是 the label displays.
  • keyEvent(selector, type, keyCode)
    • Simulate keyboard operations. For example, the selected element detects keypress keydown and presses keyup the keyCode
  • triggerEvent(selector,type,keyCode)
    • Trigger a given event on a specified element, such blur ddlclick etc..."
  • visit(url)
    • Access the route and return the result that the promise executed successfully.

Synchronize the test assistant

Synchronize the test assistant, which executes immediately when triggered and returns the results.

  • currentPath()
    • Returns the current path
  • currentRouteName()
    • Returns the currently activated route name
  • currentURL()
    • Returns the current URL
  • find(selector, context)
    • Look for the element specified below (optional) in the app root element. D efining its domain to the root element can effectively avoid conflicts with the test framework. When the context is not specified, it is done by default.

Wait for the assistant

andThen test assistant will wait for all asynchronous test assistants to complete before executing. For example:

  1. // tests/acceptance/new-post-appears-first-test.js
  2. tese('should add new post' function(assert) {
  3. visit('/posts/new');
  4. fillIn('input.title' 'My new post');
  5. click('button.submit');
  6. andThen(() => assert.equal(find('ul.posts li:first').text(), 'My new post'));
  7. });

First, we visit /posts/new fill in input with the title css class, and then click the button with submit

The asynchronous test assistant waiting for the signature is completed (specifically, andThen executes after the /posts/new access is complete, input form is populated, and the andThen Note andThen assistant has only one argument, which is a function, and the code for the function is code that is actually executed after the test assistant has executed.

In andThen assistant, we end up calling assert.equal to determine whether the value of the corresponding location is My new post

Custom test assistant

Use the ember generate test-helper to create a custom test assistant.

The following code is an ember g test-helper shouldHaveElementWithCount

  1. //tests/helpers/should-have-element-with-count.js
  2. export default Ember.Test.registerAsyncHelper(
  3. 'shouldHaveElementWithCount' function(app){}
  4. );

Ember.Test.registerAsyncHelper and Ember.Test.registerHelper'是当 are custom test assistants registered when the startApp 被调用时,会将自定义测试助手注册。两者的区别在于,前者 the former Ember.Test.registerHelper' will run after any previous asynchronous test assistant runs, and subsequent asynchronous test assistants will wait for him to complete before running.

Test assistant methods are typically called with the first argument of the current program, and other assert are provided when the test assistant is called. The test assistant needs to startApp but ember-cli you with it, and you don't need to worry about it.

Here's a non-asynchronous test assistant:

  1. //tests/helpers/should-have-element-with-count.js
  2. export default Ember.Test.registerHelper('shouldHaveElementWithCount'
  3. function(app assert selector n context){
  4. const el = findWithAssert(selector context);
  5. const count = el.length;
  6. assert.equal(n count 'found ${count} times');
  7. }
  8. );
  9. //shouldHaveElementWithCount(assert, 'ul li', 3);

Here's an asynchronous test assistant:

  1. export default Ember.Test.registerAsynHelper('dblclick'
  2. function(app assert selector context){
  3. let $el = findWithAssert(selector context);
  4. Ember.run(() => $el.dblclick());
  5. }
  6. );
  7. //dblclick(assert, '#persion-1')

Asynchronous test assistants also allow you to combine multiple test assistants into one. For example:

  1. //tests/helpers/add-contact.js
  2. export default Ember.Test.registerAsyncHelper('addContact',
  3. function(appname) {
  4. fillIn('#name', name);
  5. click('button.create');
  6. }
  7. );
  8. //addContact('Bob');
  9. //addContact('Dan');

Finally, don't forget to add your test tests/.jshintrc tests/helpers/start-app.js tests/.jshintrc you need to add it predef or you'll get a message that the jshint test failed.

  1. {
  2. "predef": [
  3. "document",
  4. "window",
  5. "locaiton",
  6. ...
  7. "shouldHaveElementWithCount",
  8. "dblclick",
  9. "addContact"
  10. ],
  11. ...
  12. }*

tests/helpers/start-app.js which will be registered with the app.

  1. import Ember from 'ember';
  2. import Application from '../../app';
  3. import Router from '../../router';
  4. import config from '../../config/environmnet';
  5. import './should-have-element-with-count';
  6. import './dblclick';
  7. import './add-contact';