When

MW 9:30am - 11:00am

Where

Tech LR 5

Who

Chris Riesbeck

Resources

Ionic Testing Task

This is an in-class activity to prepare you for automating the testing of an Ionic application. Testing web applications uses many of the same tools. [Jump to Day 1 steps] [Jump to Day 2 steps]

Two kinds of testing are involved: unit and end to end tests.

There are several good sites that go into detail about testing Ionic and Ionic 2 apps, e.g., this site. Unfortunately, they require many installation steps and editing of configuration and JavaScript files. I've encountered fatal typos, especially in specifying subdirectories, and out-of-date library names, e.g., angular-cli instead of @angular/cli. Several reporting tools have changed names.

For now, the simplest starting point is this Github starter project. There are many more things you could add, as described on other Ionic and Angular testing sites. This will give you a working test set up. Then you can add the rest.

The Ionic developers have said that eventually the testing framework will be included in Ionic and this repository will be unnecessary. We'll see.

Install and Run Ionic 2 Test Demos

First, make sure testing works for you.

cd to your projects directory, then do the following:

git clone https://github.com/driftyco/ionic-unit-testing-example.git

cd ionic-unit-testing-example

npm install

There should be no errors at any step. There may be some warnings.

If, and only if, Github is not responding, download and extract files from this possibly out of date archive.

Run the unit tests

If everything installed, now run the unit tests with the following command:

npm test

The Chrome browser should open a new window showing the Karma home page. Click on the Debug button to see a report on the test results. It should say 4 tests were run, with 0 failures.

The default test script keeps running. Stop it with a command-C or control-C. Normally you would leave it running until there no failing tests. The script watches for code file changes and reruns the tests within a few seconds of any saved change. Reload the Debug page to see the new results, when tests finish.

Run the end-to-end tests

To run the end-to-end tests, you have to start the app first:

ionic serve

Assuming it starts without error, open a new command shell, cd to the project root, and run

npm run e2e

The results of the end-to-end tests are given in the console. There's just one end-to-end test in the demo. See end-to-end tests below.

Common Errors and Fixes

Update!

If any errors occur, the first thing to do it make sure you have an up-to-date NodeJS and up-to-date packages. Run

ionic info

If it shows a version of Node older than version 6, update Node.

When or not you updated Node, you should also update your package dependencies.

Unit test errors

These are errors that occur when running npm test:

End-to-end test errors

These are errors that occur when running npm run e2e:

Adding Testing to An Existing Ionic App

Once the above works, add the testing tools to an existing app.

Install and Test the Sample Reddit Reader App

Reddit Reader is a hybrid app that displays posts on Reddit. It's not complete, but it works, looks nice, has a decent amount of complexity, and has absolutely no testing in it.

git clone https://github.com/DreamWebTeam/ionic2-reddit-reader.git

cd ionic2-reddit-reader

npm install
If, and only if, Github is not responding, download and extract files from this possibly out of date archive.

If everything installs, then test that it runs.

ionic serve

A page should appear showing some current reddit items.

Stop the server.

Add testing to the Reddit Reader

Use ionic-unit-testing-example as the basis for what needs to be added to the Reddit Reader.

Copy the directories e2e and test-config from ionic-unit-testing-example to ionic2-reddit-reader.

Update ionic2-reddit-reader/tsconfig.json to exclude test files from the normal build, i.e., the exclude: field should look like this:

tsconfig.json
  ...
  "exclude": [
    "node_modules",
    "src/**/*.spec.ts"
  ],
  ...

Update the ionic2-reddit-reader/package.json to include the additional dependencies and scripts needed for testing. You can do this manually, or use a tool, like this:

Now update the project modules and trying running again.

npm install
    
ionic serve

Add end-to-end tests

While the app is running, try the existing end-to-end test that you copied over from ionic-unit-testing-example.

Open a new commmand window. cd to the ionic2-reddit-reader project. Run the end-to-end tests.

npm run e2e

You should get a test failure, because the test looks for the page title "Page One" and this doesn't exist.

Now fix that test to look for a title that contains "Reddit Reader" instead. See the Jasmine documentation for examples of standard matchers.

Try running the test again. Repeat until it passes.

Congratulations! You just developed your first end-to-end test!

Add unit tests

Verify unit testing is working

To make sure that any unit tests are being found and executed, create a toy unit test. Use the example test in the Angular Testing tutorial.

Add app component test

For the next step, go to Ionic 2 Unit Testing: The Best Way.

Copy the file src/app/app.component.spec.ts from the article. Most of the boilerplate can stay. Two things need to change.

Open src/app/app.component.ts. There'll you find the name of the app to use in the test. You'll also see that the app class has a rootPage member. Change the test for 2 pages to be a test that the root page is the Posts page.

Save the changes. The tests should re-run automatically, if you have not force-quit the test script.

Congratulations! You just developed your first app component test!

Testing Tools

Three standard tools are used in this demo project:

These are general tools. In addition, there is a fourth tool, specifically for Angular:

Configuration Files

A number of configuration files have to be correctly defined for everything to work. Should something break, or should you need to add more tools, this is where to look.

Test Files

Most of the time, what you need to do is create test files. There are two kinds: unit tests, for testing components, and end-to-end tests, for testing the app, i.e., integration testing.

Unit Tests

Unit tests by definition test some unit of code, e.g., a function or a class, not an entire system. Unit tests should run very fast and not depend on external modules, the network, a database, etc.

The demo project includes two examples of unit tests. Both are testing Angular components. That means they are testing objects that normally are created and interacting inside an Angular app. To test these as independent units, the rest of the app has to be "mocked". The library for doing that is TestBed.

The recommended practice in Angular is to create a separate unit test file for every component you want to test, rather than one big test file. The file is placed next to the component, for convenience. The file name is the same as the component, but ending in .spec.ts.

Because this is such a simple app, there are only two unit tests. One is for the component representing the app itself, app.component.ts. Next to it is the test file, app.component.spec.ts

The other unit test is for one of the two HTML pages in the app. While it's easy to write code to look at HTML and test for certain properties, this quickly leads to fragile hard to read tests that break with minor changes in the user interface.

To avoid that problem, best practice is to create page objects. These are JavaScript objects that provide controlled access to the parts of a web page. The object takes care of the specific details of the page. If the page changes, the object may need to change. But all the testing is done using the page object's public functions, and this rarely changes.

The demo project has an example of a page object and the test for that object:

End-to-end Tests

End-to-end tests test the actual app, using Protractor and Selenium to communicate with a running web version of the app.

Because the tests are not component-specific, the tests are stored together in the directory e2e, and no mocking is done.

The example project has one end-to-end test, app.e2e-spec.ts, that just checks to see if opening the app displays a page that appears to have the right content. As with the page component unit test, it uses a page object, app.po.ts to insulate the test from small changes in the web page.

A test like this serves as a good "is it up?" test that you run to make sure you haven't completely broken the app with some change.