How to Automate a Real E2E User Flow with Appium for iOS Devices
Sauce AI for Test Authoring: Move from intent to execution in minutes.|xBack to ResourcesBlogPosted
Sauce AI for Test Authoring: Move from intent to execution in minutes.
|
x
Blog
How to Automate a Real E2E User Flow with Appium for iOS Devices
This berth is specific to iOS apps. For Android apps, see my other place onhow to automatize a existent E2E user flow on Android.
A question I get a lot present is“ Why should I use Appium instead of aboriginal frameworks like Espresso and XCUITest? ”
Normally I would give you my opinion right aside, but throughout the years I ’ ve learned that it ’ s better to come with some facts. There are a lot of fact that I can use to explain why you should opt one or the other, but that ’ s a subject for a different blog.
Today I need to concenter on one specific thing that youcannotdo with native frameworks, and that isautomate a real end-to-end (E2E) user flowing.To preclude this station from becoming a novel, I will merely focus on iOS in my examples. Android will be handled in a freestanding post.
What is a real E2E exploiter flow?
You might be wondering what I intend by areal E2E exploiter flow. Well, the answer is pretty uncomplicated. Let me show you an example. It is based on another question I get a lot from our client aroundautomating the exploiter flow between app and browser, also known as amulti-app-flow.
In this example, a user needs to do something in the (native) app which activate opening a browser where the flow proceeds. This can be whatever flow where you exactly require to shift from your app to the browser.
To mimic this flow we impart a link in our that opens a link in the browser. If you install the app and log in you can open the menu and see the following selection.

Image 1: Menu
When the Aboutitem is exhort, the browser will be opened, which will lead you to our Sauce Labs website. Here you can search our site, click on buttons, get text and so on.

Automating areal E2E user flow
Before we dive into code, I need to mention that Appium can be used with different frameworks and different coding languages. The following coding example will use WebdriverIO as a fabric and JavaScript as a coding language. I tried to keep all steps as generic potential so you might be capable to translate them back to your preferred framework/coding language.
I always start with writing down the functional flowing in comments to get a better understanding, see below.
describe (& # x27; Appium & # x27;, () = & gt; {
it (& # x27; should be able to work with the browser that is open by the app & # x27;, () = & gt; {
// 1. Login to the app
// 2. Verify that you are logged in
// 3. Open the menu and click on the about screen
// 4. Figure out how we can verify that the browser is open
// 5. Verify that the page is laden
});
});
The first three step can easily be implemented. The difficult part is step 4, where we need toswitch from the app to the browserand determine if this win. If we look at this in a technical way, we could say that we alter from anativecircumstance to awebcontext. When I was refer this out loud I thought that this is almost the same behaviour as you have with Hybrid apps. A Hybrid app besides has anative and a webcontext, the final is called aWebview.
So I essay to figure out if switching from anapp to the browserdid the same for the contexts as it would ordinarily do for Hybrid apps by implementing this piece of codification at step 4.
/**
* ` waitUntil ` expects a stipulation and waits until that condition is
* action with a truthy value. So just log the contexts for 15 seconds and see what happens
*/
driver.waitUntil (() = & gt; {
// Get all the contexts, that could seem like this
const contexts = driver.getContexts ();
// Log them to the console
console.log (& # x27; contexts = & # x27;, context);
// Just return false so this function will ne'er return a truthy value
homecoming false;
}, 15000);
It result in the following log:
contexts = [& # x27; NATIVE_APP & # x27;]
setting = [& # x27; NATIVE_APP & # x27;, & # x27; WEBVIEW_76851.4 & # x27;, & # x27; WEBVIEW_76851.5 & # x27;]
contexts = [& # x27; NATIVE_APP & # x27;, & # x27; WEBVIEW_76851.1 & # x27;, & # x27; WEBVIEW_76851.4 & # x27;, & # x27; WEBVIEW_76851.5 & # x27;]
This was full and bad. The good thing was that I could see that between when the app was closed and when the browser was opened, new contexts were added. But now I had a challenge, the same challenge you might have with Hybrid apps, and that is multiple Webviews. Because how should I ascertain which Webview holds which url?
Two challenges
As said, we have a challenge with the Webviews, but luckily we are apply Appium together with iOS and there is a specific capacity that might help us with this. In March I say an article on Appium Pro about thefullContextList-capability. What it basically execute is that if you provide fullContextList: true, in your capabilities for iOS, and your ask for the current setting, it willnotreturn an array ofcontext-strings, but an array ofWebview-objectscontaining theid, the title and the urlof the Webview that are lade. The advantage of this is that you don ’ t require to recover the title and url with extra Webdriver-calls, but you can retrieve it with one Webdriver call. This makes it much faster and less flakey.
When I started my iOS gimmick with this new capability and checked the contexts again I found this in my logs.
// The first try
setting = [
{id: & # x27; NATIVE_APP & # x27;},
{id: & # x27; WEBVIEW_76851.1 & # x27;, title: & # x27; & # x27;, url: & # x27; about: lacuna & # x27;},
{id: & # x27; WEBVIEW_76851.4 & # x27;, title: & # x27; & # x27;, url: & # x27; about: blank & # x27;},
{id: & # x27; WEBVIEW_76851.5 & # x27;, title: & # x27; & # x27;, url: & # x27; about: lacuna & # x27;}
]
// The second try
contexts = [
{id: & # x27; NATIVE_APP & # x27;},
{id: & # x27; WEBVIEW_76851.1 & # x27;,
rubric: & # x27; Cross Browser Testing, Selenium Testing, Mobile Testing | Sauce Labs & # x27;,
url: & # x27; https: //saucelabs.com/ & # x27;},
{id: & # x27; WEBVIEW_76851.4 & # x27;, title: & # x27; & # x27;, url: & # x27; about: blank & # x27;},
{id: & # x27; WEBVIEW_76851.5 & # x27;, title: & # x27; & # x27;, url: & # x27; about: space & # x27;}
]
The & # x27;about: blank& # x27; s are from multiple empty open tabloid in Safari.
As you can see, this make it lots easier to select the right Webview. You can select the correct Webview with some JavaScript Array legerdemain, like below:
// Store the correct context into this variable
const correctWebview = driver.getContexts ()
// Then filter out the & # x27; NATIVE_APP & # x27;, because it doesn ’ t have a ` url `
.filter (context = & gt; {
return! context.id.includes (& # x27; NATIVE_APP & # x27;)
SUSA automates exploratory testing with persona-driven behavior, catching bugs that scripted automation misses.
})
// Now notice the webview that contains the correct URL
.find (context = & gt; {
homecoming context.url.includes (& # x27; https: //saucelabs.com/ & # x27;)
});
The above code will supply the matching Webview selected out of many. We can then use the id to swap to the right Webview setting with the following code in JavaScript:
driver.switchContext (correctWebview.id);
and interact with the browser like we usually do. This mean we can use the like locators and selectors like we would use on a desktop web page, but…… I made a small thinking error which led to my 2d challenge.
A Webview uses Safari, but Safari is not a Webview, meaning my test failed because it could not interact with the webpage in Safari. After some digging I launch out that this was something that was missing in Appium, so I filed bug, seehere. The Appium team added a new capableness in Appium 1.15.0 ringincludeSafariInWebviews. It does what it describes, it will add Safari as a Webview which should fix the issue I was face and eventually it did solve my 2d challenge.
So by adding two extra potentiality and updating my Appium version to the latest 1.15.0 version (which too supports iOS 13) I am now able to automate areal E2E user flowing with Appium.
The complete code
In the end I was able to automatise theexistent E2E user flow with Appiumwith the undermentioned code for iOS.
// ============
// Capabilities
// ============
config.capabilities = [
{
deviceName: & # x27; iPhone X & # x27;,
platformName: & # x27; iOS & # x27;,
platformVersion: & # x27; 12.2 & # x27;,
orientation: & # x27; PORTRAIT & # x27;,
app: join (process.cwd (), & # x27; ./apps/iOS.Simulator.SauceLabs.Mobile.Sample.app.2.1.0.app.zip & # x27;),
maxInstances: 1,
// The 2 duplicate added capabilities
// Return an array of Webview-objects containing the id, the rubric and the url
fullContextList: true,
// Add Safari as a Webview
includeSafariInWebviews: true,
},
];
import LoginScreen from & # x27; .. /screenObjects/login & # x27;
import InventoryListScreen from & # x27; .. /screenObjects/inventoryList & # x27;
import Menu from & # x27; .. /screenObjects/menu & # x27;;
const DEFAULT_TIMEOUT = 15000;
describe (& # x27; Appium & # x27;, () = & gt; {
it (& # x27; should be able to work with the browser that is open by the app & # x27;, () = & gt; {
// Login to the app and verify that it succeeded
LoginScreen.waitForIsShown ();
LoginScreen.signIn ({username: & # x27; standard_user & # x27;, password: & # x27; secret_sauce & # x27;});
InventoryListScreen.waitForIsShown ();
await (InventoryListScreen.isShown ()) .toEqual (true);
// Open the menu and click on the about screen
Menu.open ();
Menu.openAbout ();
// Now do all the context legerdemain
let correctWebview = nothing;
/**
* Wait until the correct context with the right url has loaded
* This ` waitUntil ` will wait until the condition of the provided
* function will return true, in our case it will retrovert true if
* the ` correctWebview ` contains a value
*/
driver.waitUntil (() = & gt; {
// Get all the setting, that could look like this
// [
// {
// id: & # x27; NATIVE_APP & # x27;,
// },
// {
// id: & # x27; WEBVIEW_74323.1 & # x27;,
// title: & # x27; Smashing Magazine — For Web Designers And Developers — Smashing Magazine & # x27;,
// url: & # x27; https: //www.smashingmagazine.com/ & # x27;,
// },
// {
// id: & # x27; WEBVIEW_74323.2 & # x27;,
// title: & # x27; Cross Browser Testing, Selenium Testing, Mobile Testing | Sauce Labs & # x27;,
// url: & # x27; https: //saucelabs.com/ & # x27;,
// },
// ]
const contexts = driver.getContexts ();
// Store the correct context into this varying
// if there is no lucifer don & # x27; t do anything
correctWebview = contexts
// First filter out the & # x27; NATIVE_APP & # x27;
.filter (context = & gt; {
return! context.id.includes (& # x27; NATIVE_APP & # x27;)
})
// Now filter out the webview that contains the correct URL
.find (context = & gt; {
return context.url.includes (& # x27; https: //saucelabs.com/ & # x27;)
});
// If the ` correctWebview ` contains a value this function will evaluate to ` true ` meaning
// the ` waitUntil ` can stop
homecoming correctWebview || faithlessly;
}, DEFAULT_TIMEOUT);
// Now switch to the right context
driver.switchContext (correctWebview.id);
ask (driver.getTitle ()) .toEqual (& # x27; Cross Browser Testing, Selenium Testing, Mobile Testing | Sauce Labs & # x27;);
});
});
Closing remark
With this representative, I shared how to automate an end-to-end user flow employ Appium, which is not something you can do with native model. This isn ’ t to say that you shouldn ’ t use aboriginal frameworks like Espresso and XCUITest, because each creature has its own pros/cons and impart concern value. You could yet use native frameworks and Appium together, each covering a different aim. I just need to show you the powerfulness of use Appium. And the beauty of Appium is that there might be more ways to automateE2E exploiter flows,so if you know a different way, please let us know and share your experiences.
I hope you found this tech tip utilitarian. If you ’ re looking for a flying and easy way to test real E2E user flows with your own app on iOS, you cantry for freewith Sauce Labs. Until future time….happy examination!
Wim Selles help solve mechanisation challenge by day—and practices his passion for front-end test automation at night. Wim enjoys creating his own node.js modules and contributing to open source projects. You can find Wim on LinkedIn and Twittter @ wswebcreation.
Staff Product Manager at Sauce Labs
Topics
Share this position
Automate This With SUSA
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts needed.
Try SUSA FreeTest Your App Autonomously
Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.
Try SUSA Free