Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Moodle Mobile 2 (Ionic 1) End To End Testing: Difference between revisions

From MoodleDocs
No edit summary
Line 44: Line 44:
* Run Protractor  
* Run Protractor  
** ./node_modules/protractor/bin/protractor e2e/build/protractor.conf.js
** ./node_modules/protractor/bin/protractor e2e/build/protractor.conf.js
== Writing tests ==
Test files must:
* Be located in an e2e/ folder in the right component/addon
* End with .spec.js
* Use Jasmine as syntax
For example, if you want write tests for mod_book:
* www/addons/mod_book/e2e/suite1.spec.js
* www/addons/mod_book/e2e/suite2.spec.js
Protractor mostly does everything for us to ensure that Angular is not running however I noticed that in order for this to work we need to extensively use promises. Clicking on an element, or interacting with the app should return a promise which the tester will wait for before executing the next operation. For example:
<code javascript>
it('Does something', function(done) {
    return MM.loginAsStudent().then(function() {
        return MM.clickOnInSideMenu('Messages');
    }).then(function() {
        return MM.clickOn('Contacts');
    }).then(function() {
        expect(MM.getView().getText()).toMatch('Something');
        done();
    });
});
</code>
MM comes with some helper functions to make it easier to test various things. Helper methods can be added when they are useful however they should not be specific to addons. Should helper methods be required for addons we can improve the building process to include them. In general, the steps taken by helper methods should be at least tested once without the helper method. For instance if you implement a helper to login, one of the tests should manually follow the steps to login to confirm that it works as expected.
See the file e2e/lib.js for a list of helpers. The most helpful helpers might be the ones allowing you to follow a link in a certain region. Protractor often finds the first DOM element matching our selector, even if it's not visible on screen. Often leading to failures the test tries to click of that element. Here is an example of a click in the visible view:
<code javascript>
MM.clickOn($('.my-button'), MM.getView()).then(function() {
    // It worked!
})
</code>
=== Global variables ===
All tests have access to global variables. These are useful to conditionally decide what tests to run, or how tests should behave. We generally want to write tests which are compatible with any site, but at times we will need to alter them, or to write other ones for specific scenarios. For example a site running Moodle 2.7 with or without local mobile will generally behave differently and the tests should be written to handle this.
<code javascript>
Example:
MM.clickOn($('.my-button'), MM.getView()).then(function() {
    if (SITEHASLM) {
        // Assert something.
    } else {
        // Assert something else.
    }
})
</code>
These global variables are defined at the time when the protractor file is generated, hence the need for a different configuration file per site to be tested.
List of global variables:
* ISANDROID
* ISBROWSER
* ISIOS
* ISTABLET
* DEVICEURL
* DEVICEVERSION
* SITEURL
* SITEVERSION
* SITEHASLM (has local mobile)
* USERS.<role>.LOGIN
* USERS.<role>.PASSWORD

Revision as of 08:50, 28 June 2016

Protractor is an end-to-end test framework for AngularJS applications. Protractor runs tests against your application running in a real browser, interacting with it as a user would.

Setting-up testing environment

This currently only covers testing on Android 4.4 onwards and Chrome. iOS testing is a work in progress.

Head to the root directory of your MM instance.

  • Install the packages required for testing
npm install (do not use the -g option)
  • Install the Chrome webdriver
./node_modules/protractor/bin/webdriver-manager update
  • Make sure your checkout is up to date, all the cordova plugins are installed and the android platform is set-up. The following should be enough.
gulp
ionic state restore
ionic build android

Once this is done, you will need to generate a protactor configuration file for the platform you intend to test the app on.

Generating Protractor config file

Protractor config file contains all the information for running the tests, as well as to provide the tests with information about the site being tested.

  • For Android
    • gulp e2e-build --target android --device abcdefg --version 4.4
  • For Chrome (browser)
    • gulp e2e-build --target browser

By default the configuration file is saved at e2e/build/protractor.conf.js, should you wish to save the configuration file to re-use it later, you can use the argument --output <filename>.

Other arguments are available, you can find more about them using:

   gulp e2e-build -h
   gulp e2e-build --target android -h
   gulp e2e-build --target browser -h

Running the suite

  • Run the ionic first
    • ionic serve -b -a
  • Start the web driver
    • For Android: ./node_modules/appium/bin/appium.js
    • For Chrome : ./node_modules/protractor/bin/webdriver-manager start
  • Wait for the driver to be fully started
  • Run Protractor
    • ./node_modules/protractor/bin/protractor e2e/build/protractor.conf.js

Writing tests

Test files must:

  • Be located in an e2e/ folder in the right component/addon
  • End with .spec.js
  • Use Jasmine as syntax

For example, if you want write tests for mod_book:

  • www/addons/mod_book/e2e/suite1.spec.js
  • www/addons/mod_book/e2e/suite2.spec.js

Protractor mostly does everything for us to ensure that Angular is not running however I noticed that in order for this to work we need to extensively use promises. Clicking on an element, or interacting with the app should return a promise which the tester will wait for before executing the next operation. For example:

it('Does something', function(done) {

   return MM.loginAsStudent().then(function() {
       return MM.clickOnInSideMenu('Messages');
   }).then(function() {
       return MM.clickOn('Contacts');
   }).then(function() {
       expect(MM.getView().getText()).toMatch('Something');
       done();
   });

});

MM comes with some helper functions to make it easier to test various things. Helper methods can be added when they are useful however they should not be specific to addons. Should helper methods be required for addons we can improve the building process to include them. In general, the steps taken by helper methods should be at least tested once without the helper method. For instance if you implement a helper to login, one of the tests should manually follow the steps to login to confirm that it works as expected.

See the file e2e/lib.js for a list of helpers. The most helpful helpers might be the ones allowing you to follow a link in a certain region. Protractor often finds the first DOM element matching our selector, even if it's not visible on screen. Often leading to failures the test tries to click of that element. Here is an example of a click in the visible view:

MM.clickOn($('.my-button'), MM.getView()).then(function() {

   // It worked!

})

Global variables

All tests have access to global variables. These are useful to conditionally decide what tests to run, or how tests should behave. We generally want to write tests which are compatible with any site, but at times we will need to alter them, or to write other ones for specific scenarios. For example a site running Moodle 2.7 with or without local mobile will generally behave differently and the tests should be written to handle this.

Example:

MM.clickOn($('.my-button'), MM.getView()).then(function() {

   if (SITEHASLM) {
       // Assert something.
   } else {
       // Assert something else.
   }

})

These global variables are defined at the time when the protractor file is generated, hence the need for a different configuration file per site to be tested.

List of global variables:

  • ISANDROID
  • ISBROWSER
  • ISIOS
  • ISTABLET
  • DEVICEURL
  • DEVICEVERSION
  • SITEURL
  • SITEVERSION
  • SITEHASLM (has local mobile)
  • USERS.<role>.LOGIN
  • USERS.<role>.PASSWORD