So, you have an existing Ionic project and now you want to start unit testing and end-to-end testing it. A great way to configure your existing project for testing is use the
ionic-unit-testing-example project on Github. This post will provide you with step-by-step instructions on how to add modules and files from that project into your own project so you may begin testing your project.
While the name of the project is
ionic-unit-testing-example, the project actually sets up two kinds of testing: unit testing and end-to-end (E2E) testing. For the purposes of this tutorial, unit testing is isolating components for testing, and end-to-end testing automates the browser and simulates user interactivity to allow the testing of how the whole application works.
Testing and Test Driven Development can be controversial topics in some circles. How you go about testing is up to you and your team. Personally, I believe that you should have both unit tests for your components and E2E tests for your application. How you get there is up to you.
Trigger Warning: Unit testing and end-to-end testing can be challenging and frustrating even for experienced developers. Getting tests to pass can take patience and experience. You should learn as much as possible about testing before beginning your testing practice. Take your time, ask questions of your peers, seek assistance online, and above all, don’t let a continuosly failing test get the better of you. You will overcome it.
This tutorial was assembled with the following software installed (this information gathered by using the
ionic info command):
$ ionic info cli packages: (/Users/leifwells/.nvm/versions/node/v6.11.2/lib/node_modules) @ionic/cli-utils : 1.9.2 ionic (Ionic CLI) : 3.9.2 local packages: @ionic/app-scripts : 2.1.3 Ionic Framework : ionic-angular 3.6.0 System: Node : v6.11.2 npm : 3.10.10 OS : macOS Sierra
Step 1: Create a Project to Test (Optional)
Since we do not know anything about your project, so we will be using an Ionic starter project as our starting point. To create it, open up your terminal application, navigate to the folder where you would like to add a new project, and run the following command:
ionic start starter-with-testing sidemenu
This command will create a directory named
starter-with-testing and install the code for an Ionic application using the side menu template.
Please Note: This step is not necessary if you are adding content to your own project. Since we can’t see your project, we needed a point of reference to get these instructions started.
Now, navigate your terminal window to the installed folder and run the following command:
cd starter-with-testing ionic serve
Once you have the application running, you have completed this step.
Step 2: Get the Example Code
Head over to
ionic-unit-testing-example and download the code. You don’t need to load or run the project. We’ll be moving files and code from that project into our project code.
You can use the green “Clone or download” to download a .zip file of the project. Click the button to reveal the “Clone with SSH” popover and click on the “Download ZIP” button to begin the process.
Once the file is downloaded, decompress it and open the containing folder so that it is available when we need it.
Step 3: Install Required Node Modules
There are a handfull of Node modules required for testing to work with and Ionic application and need to be added to our project. While you can install each of these modules separately, we’ve organized the install process into one handy command:
npm install --save-dev angular2-template-loader html-loader jasmine jasmine-spec-reporter karma karma-chrome-launcher karma-jasmine karma-jasmine-html-reporter karma-sourcemap-loader karma-webpack karma-coverage-istanbul-reporter istanbul-instrumenter-loader null-loader protractor ts-loader ts-node @types/jasmine @types/node
This command adds these modules to the
"devDependencies" node of your project’s
package.json file. There are quite a few modules here, but the important modules are
karma is the Karma module which is our testing environment for unit testing.
jasmine is the Jasmine module which is the unit testing framework.
protractor is the Protractor module which is our testing environment for our end-to-end tests. The rest of the modules are utilities that allow this configuration to work.
Step 4: Add Scripts to the
There are a couple of scripts that need to be added to the
package.json to make running tests from the command-line possible. Open the
package.json file and add the following scripts to your
"test": "karma start ./test-config/karma.conf.js", "test-ci": "karma start ./test-config/karma.conf.js --single-run", "test-coverage": "karma start ./test-config/karma.conf.js --coverage", "e2e": "npm run e2e-update && npm run e2e-test", "e2e-test": "protractor ./test-config/protractor.conf.js", "e2e-update": "webdriver-manager update --standalone false --gecko false"
Important: Make sure you add a trailing comma on the line above this code or your
package.jsonwill stop working. Your code editor should inform you of the missing comma.
With the addition of these items, you will be able to enter the
npm run test command to begin unit testing, or
npm run e2e to begin end-to-end testing.
Step 5: Add the Configuration Files
The control center for this testing configuration are a set of files that are inside the
ionic-unit-testing-example project which need to be added to our project. Open the folder where
ionic-unit-testing-example was decompressed earlier and locate the
test-config folder. Copy and paste that folder into the root of our project.
Open the folder in your code editor and take a look. You should see five files:
karma-test-shim.js karma-config.js mocks-ionic.js protractor.conf.js webpack.test.js
karma-config.js file is the configuration file for Karma. It uses
karma-test-shim.js to link more modules required for testing and
webpack.test.js to configure and compile our code for testing.
protractor.conf.js file is the configuration file for Protractor.
mocks-ionic.js file is a collection of classes that are used to as a substitute for classes in the
ionic-angular module for testing. We will discuss mocking further later in this tutorial.
Step 6: Adding End-to-end Testing
Now that our unit testing configuration is set up, we need to add one more folder to our project so we can implement the end-to-end testing solution. Copy the
e2e folder found inside the location where you decompressed .zip file from the
ionic-unit-testing-example and paste that folder into the root of your project. This folder has the following files:
app.e2e-spec.ts app.po.ts tsconfig.json
tsconfig.json file is an important configuration file which assists with compiling the project and tests for end-to-end testing. The file is placed here because it isolates it from the project’s
app.e2e-spec.ts file is an actual E2E test file. Note the name of the test as our configuration file is looking for files that have the
.e2e-spec.ts as part of the name to identify it as an E2E test and not an unit test. The
app.po.ts is an example of a page object, a helper file that assists in providing utility methods for locating elements and processing expected results. You can find out more about page objects on the Protractor Website.
If you are following along with this tutorial, when you run the
npm run e2e command in your terminal window, this test should work. If you run this test with your project, it will probably fail. You will need to update the test to make it work for you.
Important: When you run E2E tests, make sure you are running
ionic servein another terminal window. The E2E configuration expects to have a connection to the server and if it is not it will fail with an error.
Adding Your First Unit Test
Before you can begin testing, you need to have a test file. To make sure the testing configuration is working, we’ll add a file to our project to test that the application loads.
src/app/ folder in your project and create a new file named
app.component.spec.ts. This will be our unit test file for the
MyApp class which is inside the
app.component file. Inside this new file, copy and paste the following code:
This is not a tutorial on how to create tests, but let’s take a brief look at this test code.
Angular Testing Utilities
As you can see, the test file has the typical methods for unit testing:
it. Inside the first
beforeEach is a call to the
TestBed is a module provided by the Angular team to facilitate testing. To find out more about testing in Angular, please read the Angular Testing Guide. Seriously, read that documentation a few times and let it sink in.
Now, take a look at places where
MyApp is listed.
MyApp is the component being tested here, and appears in the class import, inside the
TestBed.configureTestingModule() method inside the
declarations array, inside the
imports array, and also in the second
beforeEach method when the component is actually created. This is how each of your test files will work.
The first test, the code inside the first
it instance, checks to see if the
MyApp component is created. The second test checks that the
pages array created in the
MyApp class has two items.
Mocking Ionic Classes
Another note of interest: mocking Ionic classes. With unit testing, developers should try to isolate the component to be tested. If you include the actual classes, technically you would be testing the Ionic framework, which is unnecessary.
To understand how mocking works, look at the structure of items inside the
providers array. Typically,providers are listed simply by adding the class name to the array. In this case, we are mocking the classes using the
provide property to identify the name of the class to be mocked, and the
useClass property to identify the class to serve as the mock. We are using the mocks provided by the
ionic-unit-testing-example project found in the
test-config/mocks-ionic.ts file mentioned earlier.
If you choose to not use mocks for Ionic classes, what may happen is that errors will occur running you down a never-ending rabbit hole. Mocking Ionic classes is the best way to avoid this problem.
What to Expect When Unit Testing
This test is a sample test that will work with the project we are using in this tutorial and may not work for you. If you add this file to your own project and run the
npm run test command, what you may expect is an error stating that
no provider for or
no declaration for, at which point you will import that class into this file, add the class name to the
providers array or the
declarations array inside the
TestBed.configureTestingModule() method argument object.
You will probably need to create mock classes for your own providers. These mocks should accurately reflect the same methods but return expected values, for instance, mock data instead of data from a server.
Reviewing the Angular Testing documentation will help you with testing your Ionic application. There are concepts described there that will assist you with testing processes that are asynchronous, as well as best practices to follow.
Note: Sometimes when working on a unit test, you will not find a way to test a particular scenario. The problem may not be your test. It may be your code. Are the methods in your component too complex? Could you refactor your code to make your component more maintanable as well as more testable? Make sure you are looking at both sides, the test and the code you are testing, to ensure you have a successful testing practice.
Reviewing the E2E Test
Earlier, we added the
e2e folder to our project which contained our first E2E test. Let’s take a look at it.
Again, we see the typical testing methods of
it. One this of note here is the use of a second
describe method. This is used to help with organizing your tests.
Inside your E2E tests, you will be using Promises. A lot. Good tests will chain Promises. You can find out more about how to structure your tests by reviewing the Protractor Tutorial.
In this tutorial, we created an example Ionic (
ionic-angular) project to configure for unit and end-to-end testing. We used the
ionic-unit-testing-example project on Github as a guide for installing the necessary node modules and configuration files to the project to get unit testing and E2E testing to work. Then we took a brief look at the test files. Hopefully, this will give you enough information to get you started with testing your own Ionic applications.
Links for this article:
Added code coverage feature steps.
Replaced two Markdown code blocks with Github Gists.