Waldo sessions now support scripting! – Learn more
Testing

Beginner's Guide to Testing With Ionic

Nabendu Biswas
Nabendu Biswas
Beginner's Guide to Testing With Ionic
December 20, 2022
9
min read

Ionic is a framework that developers can use to create hybrid mobile apps. But is Ionic difficult to learn and use? Some experience with popular JavaScript frameworks—particularly Angular—is required. However, if you have the requisite knowledge, Ionic makes managing your mobile apps easy, as you'll create a single codebase for both Android and iOS.

In this post, we'll give a deep dive into Ionic and testing. After that, we're going to learn the difference between unit testing and end-to-end (E2E) testing in Angular apps. Next, we'll learn about Cypress and Jasmine, two frameworks for testing Angular apps. Finally, we'll learn to create a simple Ionic app using Angular. We'll then see how to test an Ionic application using Jasmine and Karma for unit testing and Cypress for E2E testing.

Ionic is a completely open-source and free-to-use mobile app development platform.

What Is Ionic?

Ionic is a completely open-source and free-to-use mobile app development platform. As mentioned earlier, it follows the principle of having one codebase for both major stores—iOS and Android. In that way, it's quite similar to React Native and Flutter, which are also used to create hybrid apps. But React Native and Flutter are limited in that each is attached to a platform. Additionally, React Native requires knowledge of React, while Flutter users must learn a completely new language, Dart.

Ionic originally started as an Angular project, but the latest version is not dependent on any JavaScript platform. With the latest version of Ionic, you can write your code in any of these three popular JavaScript frameworks/libraries: React, Angular, and Vue.

Ionic has built-in web components for everything from input boxes to buttons. So, the learning curve is very low in comparison to React Native and Flutter. But Ionic also has the same performance issues as React Native and Flutter. Apps built with native languages like Kotlin and Java for Android or Swift and Objective-C for iOS are faster than these platforms. You can find a detailed comparison of native and cross-platform app development in this post.

Angular Unit Testing vs. E2E Testing

Two popular ways to test web apps or mobile apps are unit and E2E testing. Unit testing is always done by the developer. In most enterprise projects, multiple developers work on a project. This project is divided into small components, and each developer is responsible for their component. Through unit testing, we write test cases to check if our component is working properly.

E2E testing is generally done by testers. It can be performed manually or automated to check the functionality of the apps. Automation testing requires the unique IDs of each element. Scripts are created to interact with the elements like clicking on a button.

Angular comes with Jasmine built-in for unit testing. This means you don't have to install any third-party library. For E2E testing, Angular promotes Cypress, although it isn't a default E2E framework. Before Angular 12, Protractor was the default for E2E testing in Angular. We can use these same two frameworks to test our Angular app in Ionic. Let's learn a bit more about each.

Unit Testing Ionic Apps With Jasmine

Jasmine is a popular BDD unit testing tool. In addition to being the default unit testing tool in Angular, it's also the default in Ionic. To use Jasmine, we need to write all tests inside a describe block. It also has a beforeEach and afterEach function, which runs before and after all tests. So, before beforeEach, we can do the basic configuration for the app, which is required in each test. And in afterEach, we can do cleanup if required.

Tests are written inside the it function, in which we expect to check the result. Jasmine tests are pretty easy to write. The basic syntax for Jasmine tests is below:


   describe('All tests for Tab app', () => { // Test Suite
      beforeEach(() => { 
       // Setup Code
      });
      it('should create component', () => { // Test Case
        expect(component).toBeTruthy();
      });
      afterEach(() => { 
        // Cleanup
      });
    });

E2E Testing Ionic Apps With Cypress

Cypress is a front-end E2E testing framework for web apps. It's different from Selenium in that it isn't an automation framework—a tester or developer needs to manually perform test cases in it. But like Selenium, Cypress tests target elements and checks their functionality. For example, you can target a button and perform a click operation.

Cypress's test syntax is quite similar to Jasmine's. We have the beforeEach, afterEach, and it statements. But then we use the powerful cy command to perform different tasks.


   describe('My App test', () => {
      beforeEach(() => {
       cy.visit('/');
      });
    
     it('has the correct title', () => {
       cy.title().should('equal', 'Todo');
     });
    
      it('Add an Item', () => {
       cy.byTestId('add-button').first().click();
       cy.byTestId('display').first().should('have.text', 'Coding');
      });
    });

How Do You Test an Ionic Application?

To test our Ionic application, we're going to use Jasmine for unit testing and Cypress for E2E testing. Ionic was originally developed to work with Angular. Now, it works with React and Vue, too, but the ecosystem is still best with Angular. So, we're going to start by creating an Ionic app with Angular.

The Setup

We need to install the Ionic CLI globally on our system. So, in the terminal, give the below command. Because I'm using a Mac, I also need to give sudo to install the package globally.


   npm install -g @ionic/cli
install ionic

Now, we'll create a new Ionic app called testing-ionic with Angular. This will be a tabbed mobile app, with tabs created. Capacitor is the open-source library that Ionic uses to create hybrid apps. So, we require it as well.


   ionic start testing-ionic tabs --type=angular --capacitor
testing ionic with angular

Now our Ionic app will be created, and we'll also get instructions to start it:

  • Go to your new project: cd ./testing-ionic.
  • Run ionic serve within the app directory to see your app in the browser.
  • Run ionic capacitor add to add a native iOS or Android project using Capacitor.
follow the next steps

Per the instructions, we've changed the folder and started the Ionic app with the ionic serve command.

ionic serve command

Our Ionic app will open in a browser on port 8100. And we'll see a nice tabbed mobile app.

 we'll see a nice tabbed mobile app.

Ionic and Angular apps come with Karma built-in. Karma helps run tests in the browser. We write the unit test in Jasmine, which is also installed by default. So, just run npm test from the terminal to see the unit tests.

run npm test to see unit tests

Simple To-Do App

Now, we'll create a simple to-do app in Tab 1 of our tabbed app. So, open the tab1.page.ts file and add the below code in it. Here, we have a todoList array that contains the initial values as the object. Then, we have a randomValue() function, which gives us a random object from an array. The addNewItem() function is calling the randomValue() function and inserts a random object in todoList array.

Simple To-Do App

Now, we'll add new code in our tab1.page.html file. It's similar to an Angular HTML file, but the difference is that we can't use any HTML elements. So, instead of the div and the button, we have to use Ionic components.

Here, in an ion-card, we're looping through the todoList with the ngFor directive. Then, we're showing the category, name, and due from each object. We also have an ion-fab-button. On click, it will fire the addNewItem() function.

 On click, it will fire the addNewItem() function.

Our app will now show all three initial items. We also have a button at the bottom.

Our app will now show all three initial items.

On clicking the button, a random item will be added to our app.

On clicking the button, a random item will be added to our app.

Unit Testing With Jasmine

Our Ionic app already has unit testing set up with Jasmine. We just need to add test cases to it. We'll update the unit test for our tab1.page.ts file in the tab1.page.spec.ts file.

Here, we have the familiar describe function containing all of our code. In beforeEach(), we're using TestBed to create the Tab1Page. After that, the detectChanges() function is checking for any changes in the test.

We've added two new tests in it blocks. The first test is checking whether todoList is an array. The second test is calling the addNewItem() function and checking whether the array length is greater than three.


   it('todoList should be an array', () => {
      expect(component.todoList.length).toBeDefined();
    });
    
    it('addNewItem should add the item object to todoList array', () => {
      component.addNewItem();
      expect(component.todoList.length).toBeGreaterThan(3);
    });
Unit Testing With Jasmine

Since our test was already running because of the ng test command, we got the updated result. Both of our new tests ran successfully.

Since our test was already running because of the ng test command, we got the updated result

E2E Testing With Cypress

Our Ionic app, like the Angular app, doesn't have a default E2E testing framework. So, we'll add Cypress in our app with the below ng add command. And we also need to give Yes when asked if we'd like to proceed.


   ng add @cypress/schematic
E2E Testing With Cypress

In the cypress.config.ts file, update the baseUrl to point to 8100. This is because our Ionic app runs on that port.

In the cypress.config.ts file, update the baseUrl to point to 8100

Now, from the terminal, run npx cypress open. It will open the browser. Here, click the Continue button.

Now, from the terminal, run npx cypress open

In the next window, select E2E testing.

In the next window, select E2E testing.

In a new window, we'll see the supported browsers, including Chrome and Firefox. Click the button Start E2E Testing in Chrome.

Click the button Start E2E Testing in Chrome.

In the next window, click on the spec.cy.ts file to start our Cypress testing.

In the next window, click on the spec.cy.ts file to start our Cypress testing.

Our Cypress test failed because we've updated the default app.

Our Cypress test failed because we've updated the default app.

Now, open the spec.cy.ts file inside the cypress > e2e folder. Here, we can see some basic Cypress code with a describe-it block. Cypress uses the cy command to do different things. The command visit('/') will take us home from the app. And the command contains will check if the item is in our mobile app. We've updated it from 'app is running'  to Coding because our updated app has this item.


   describe('My First Test', () => {
      it('Visits the initial project page', () => {
       cy.visit('/')
       cy.contains('Coding')
      })
    })
Now, open the spec.cy.ts file inside the cypress > e2e folder

Now, our new Cypress test ran successfully in the browser.

Now, our new Cypress test ran successfully in the browser.

Back to our spec.cy.ts file, we've added one more test in an it block. Here, we're first selecting the button and clicking on it. After that, we're checking whether we have a subtitle text as Work.

We've also added a beforeEach block, where we've moved the command cy. visit('/'). So, now this statement will run before both it statements. And we don't have to repeat it.


   describe('My First Test', () => {
      beforeEach(() => {
       cy.visit('/')
      })
      it('Visits the initial project page', () => {
       cy.contains('Coding')
      })
    
      it('Click the add button', () => {
        cy.get('ion-fab-button').click()
        cy.get('ion-card-subtitle').should('contain.text', 'Work')
     })
    })
spec cy test code

Our new Cypress test ran successfully in the browser.

Our new Cypress test ran successfully in the browser.

What You've Learned

In this post, you learned about testing with the Ionic framework. First, we learned all about Ionic. After that, we discussed how Angular handles unit and E2E testing. You've also learned to create a simple mobile app with Ionic. After that, you learned to test an Ionic app with Jasmine and Cypress.

If you want to test your mobile apps easily, then try Waldo. You only need to provide the APK or IPA file. After that, you interact with the mobile app like a real user. Waldo automatically generates test cases and sends the result in an email to you.

Automated E2E tests for your mobile app

Waldo provides the best-in-class runtime for all your mobile testing needs.
Get true E2E testing in minutes, not months.

Reproduce, capture, and share bugs fast!

Waldo Sessions helps mobile teams reproduce bugs, while compiling detailed bug reports in real time.