Automated iOS Testing with Appium and wd

Apparently someone checked out this blog during working hours and decided to tell me that I need to do an update.

Last month I was working on this mobile version of GitHub built with React-Native. The framework itself uses the same principle as React, which is component-oriented (is that a real word). However, I had most fun working on the automated testing on simulator and real device with Appium, the JSONWireProtocol implemented by wd, and Mocha.

Appium is a local server which accepts requests for UI testing. It supports languages including Java, Python and JavaScript with the same essential protocol. wd is one of the JavaScript libraries that implements the protocol AND has the most stars on GitHub, which is why I chose to use this one. Appium uses WebDriverAgent developed by Facebook to ‘control’ real devices and simulators. It also uses xcode dev tools to install apps and to inspect elements etc.

Appium has this concept called ‘desired capabilities’, which configures the testing environment. The capabilities I used for this UI test include:

  • udid, the unique identifier of the real device or simulator
  • platformName:’iOS’
  • platformVersion:’11.2′
  • app, the installation package of the app to be tested, .ipa for simulator, .app for device
  • xcodeOrgId, XCode devloper identifier
  • xcodeSigningId:’iPhone Developer’
  • deviceName, duh

here is the documentation for the desired capabilities. One important thing to note is that .ipa is the package extension for simulators and .app is the extension for devices. Methods to obtain them are documented in the README of my repository (link below).

With these in mind, I could start writing the tests. First and foremost, I needed to connect to Appium server with wd API like this:

const server = {
  host: 'localhost',
  port: 4723,
};
const driver = wd.promiseChainRemote(server);
const desired = {
  // desired capabilities above
};
driver.init(desired);

With the mapping provided on wd GitHub repo, I was then able to gradually implement my UI tests.

it('should display every tab', () => {
    return driver.waitForElementByName('Xuanyu Zhou', 6000)
      .then(el => {
        return driver.elementByName('Xuanyu Zhou').text();
      })
      .then(result => {
        result.should.be.equal('Xuanyu Zhou');
        return driver
          .elementByXPath('//XCUIElementTypeButton[contains(@name, "Public Repos")]')
          .click()
          .sleep(200)
      });
});

The above snippet is a mocha test that first waits for an element with name ‘Xuanyu Zhou’ to mount, then inspects the text ion that element. Afterwards, it uses XPath to select a button with name ‘Public Repos’, before it clicks on the button and sleeps for 200 milliseconds.

Apparently XPath’s documentation is hard to be found so it took me several StackOverflows to figure it out.

One neat thing about Appium-Desktop is that it has this inspector feature that lets you inspect the elements on the phone screen by clicking on them, just like Chrome’s developer tools. This is tremendously useful especially for the annoying XPaths.

Another interesting thing to note is that during testing I had this weird bug that although I had username and password inputs as different components, I could not click on them by themselves in the inspector. I also couldn’t select based on their names. It turned out I needed to make the input fields ‘accessible’ with React Native, documentation here. I guess Apple uses accessibility fields to give the elements names in testing. An Apple employee would be helpful here.

Repository

Testing Demo Episode 1:

Testing Demo Episode 2:

Leave a Reply

Your email address will not be published. Required fields are marked *