Getting started with Appium and WebdriverIO for mobile app testing

WebdriverIO is an advanced automation framework for web and mobile applications.

It’s a wrapper on top of selenium (WebDriver protocol with nodeJS) for web automation and a wrapper on top of appium for mobile app testing.

As per the appium client, Appium suggests to use webdriverio for appium with javascript/typescript instead of deprecated appium javascript client wd.

WebDriverIO is termed as wdio.

TypeScript is termed as TS.

If you prefer to watch the video session, refer below

wdio Installation –

Refer webdriverIO for browser testing to install wdio dependencies and create a basic project.

Appium prerequisites –

Please refer to the below links and follow the steps to install appium server, appium inspector, android setup and ios setup.

Appium philosophy and it’s architecture

Project customisations –

Open the project in Visual Studio Code.

The project structure will be as below –

Change the package.json script section to –

“scripts”: {
“wdio:android”: “wdio run wdio.android.conf.ts”,
“wdio:ios”: “wdio run wdio.ios.conf.ts”
}

Change package.json dependencies to –

We need to add appium-service dependency to run the appium.

“devDependencies”: {
@wdio/cli”: “^x.xx.x”,
@wdio/jasmine-framework”: “^x.xx.x”,
@wdio/local-runner”: “^x.xx.x”,
@wdio/spec-reporter”: “^x.xx.x”,
@wdio/appium-service”:”^x.xx.x”,
@wdio/selenium-standalone-service”: “^x.xx.x”,
“ts-node”: “^10.9.1”,
“typescript”: “^4.8.3”
},

Open the command prompt / COMMAND + ` to open the terminal – and type below to install the dependencies

npm install

Pull out tsconfig.json and wdio.conf.ts from ‘test’ directory to project root directory for best use.

Change the following lines –

wdio.conf.ts

Find the tsNodeOpts sections and change to the below project key –

tsNodeOpts: {
transpileOnly: true,
project: ‘tsconfig.json’
}

Add appium capabilities into wdio.conf.js

Add a new folder inside project as “apps” which will hold the app under test.

We are using saucelabs sample rn app for testing.

If you are using a different mobile application, then the appPackage, appWaitActivity & app will be changed.

Copy the default conf.ts and paste it with the name wdio.android.conf.ts and update as below.

Just override the capabilities section with the below content.

 //file - wdio.android.conf.ts

 port:4723,

 specs : [
        './appTest/specs/androidTest.ts'
    ],

 capabilities: [
    {
        'appium:platformName': 'android',
        'appium:automationName':'UiAutomator2',
        'appium:deviceName' : 'Nexus_10_API_30',
        'appium:platformVersion': '11',
        'appium:app': join(process.cwd(), 'apps/Android-MyDemoAppRN.1.3.0.build-244.apk'),
        'appium:appPackage':'com.saucelabs.mydemoapp.rn',
        'appium:appWaitActivity':'com.saucelabs.mydemoapp.rn.MainActivity',
        'appium:noReset': true
    }],

For ios – instead of appPackage and appWaitActivity, we will use appium:bundleId

Copy the default conf.ts and paste it with the name wdio.ios.conf.ts and update as below.

Just override the capabilities section with the below content.

 //file - wdio.ios.conf.ts

 port:4723,

 specs : [
        './appTest/specs/iOSTest.ts'
    ],

 capabilities: [
    {
        'appium:platformName': 'ios',
        'appium:automationName':'XCUITest',
        'appium:deviceName' : 'iPhone SE (3rd generation)',
        'appium:platformVersion': '16.0',
        'appium:bundleId':'com.saucelabs.mydemoapp.rn',
        'appium:noReset': true
    }],

Add appium test

Create a folder as “appTest” and subfolder “specs”

androidTest.ts

describe('My Login application', () => {
    it('should login with valid credentials', async () => {
        await (await $('~open menu')).click()
        await browser.pause(2000)
        await (await $("~menu item log in")).click();
        await browser.pause(2000)
        try{
            await (await $('~Go Shopping button')).click()

        }catch(e:any){
            await (await $("~Username input field")).setValue("bob@example.com");
            await (await $("~Password input field")).setValue("10203040");
            await (await $("~Login button")).click();

        }
        await browser.pause(2000)
    });
});

iostest.ts

describe('My Login application', () => {
    it('should login with valid credentials', async () => {
        await (await $('~tab bar option menu')).click()
        await browser.pause(2000)
        await (await $("~menu item log in")).click();
        await browser.pause(2000)
        try{
            await (await $('~Go Shopping button')).click()

        }catch(e:any){
            await (await $("~Username input field")).setValue("bob@example.com");
            await (await $("~Password input field")).setValue("10203040");
            await (await $("~Login button")).click();

        }
        await browser.pause(2000)
    });

Running test

Launch the android simulator for android tests and ios simulators for ios tests.

To run the test, open terminal from VSCode and type for android test (make sure you have android simulator or real device is ready)

npm run wdio:android

To run the test, open terminal from VSCode and type for ios test (make sure you have ios simulator is ready with app installed)

npm run wdio:ios

This will launch the app from simulator > click on menu > login > close the app