App & Browser Testing Made Easy

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators

Home Guide How to Test Deep Links on Android & iOS devices

How to Test Deep Links on Android & iOS devices

By The Nerdy Geek, Community Contributor -

Table of Contents

What are Deep Links?

Deep link is a technology that launches an app and opens a specific page in the app once the user clicks a URL on a web page or in another app. Implementing deep links is an exciting way to enhance the user experience by seamlessly allowing users to access the specific page without interruption. As a result of this, user engagement and retention increase significantly.

Let’s understand deep links with a simple example:

When searching the keyword “Floral Wallpaper” on Google, #floralwallpaper of Instagram appears as a preview among the search results.

Deep Linking Example

As the user clicks on the Search Result link, it opens the result page in the Instagram app that is already installed on the device. This is where Deep Linking comes into play, where the user gets redirected from the web search results page to the Instagram Application.

Deep Links Example on Android

The intent here is to allow the user to access the #floralwallpaper on the Instagram app seamlessly, as opposed to opening it on the website. This is done to enrich the overall user experience, allowing the user to access the app features seamlessly.

However, considering security aspects, Deep Links are easily exploitable if not used with due diligence for authorization purposes. Sometimes these deep links contain very sensitive data and when not tested properly, they might allow a malicious app to handle the deep link instead of the legitimate app. In such scenarios, Deep Link Testing plays a crucial role in improving the overall quality and security of the product.

Let’s deep dive into the world of Deep Links and learn the ways to test them!

Deep link is a URL, which navigates the user from the web to a specific page in a given app. When the user clicks a deep link, Android performs either of the following actions:

  • Opens the required app in the user’s device that can handle the link if the app is already available on the device.
  • If the required app isn’t available, it opens the only app that can handle the link or opens PlayStore from the user can download the required app.
  • In case when the URL can be handled by multiple apps, it opens a dialog allowing the user to select one app from the given list of compatible apps to open the link.

Why are Deep Links important?

Deep Linking makes any kind of transition between web and apps hassle-free and smooth for users. Given the seamless user experience, it helps advertisers have a better chance of converting the users into customers.

Retaining users is the key focus of deep linking. Deep linking is often used for re-engaging users and is often a key component of retargeting campaigns. Since it gives a seamless transition from a web link to an app, deep linking minimizes the chances of users not accessing the page redirected by the campaign URL.

Building Blocks of a Deep Link

Deep Link consists of several components, just like any URL. Let’s understand the components of a deep link with an example. Consider a dummy deep link https://www.browserstack.com/test/code=abcd. It can be categorized into:

  • https – It identifies the protocol used to access the resource on the internet.
  • www.browserstack.com – It is the host, i.e. the domain name or address of the web server that is being accessed.
  • /test – It is the path that specifies a particular page of the content.
  • code – The query parameter to extract from intents in your destination. abcd is the value of the parameter.

Types of Deep Links

Deep Links can be classified as Default, Deferred, and Contextual deep links.

1. Default Deep Links

These deep links function only to direct users to the required app if it’s already installed on the device. In case, where the app is not installed, the link is unable to reach the endpoint of an app, and thus an error message is displayed.

2. Deferred Deep Links

These deep links are more complex than default deep links. They can direct users to the App if it is available on the device. In case the app is not available on the device, it directs the users to Play Store or to another location, such as the app’s website for more information, and then open the original page that the user was directed to.

3. Contextual Deep Linking

Contextual deep linking involves links that ostensibly provide additional benefits. Contextual deep links are the usual default or deferred deep links with added parameters. Contextual deep links don’t exist by themselves, since the additional parameters are manually added. The parameters can be added by the marketers themselves. Such contextual deep links help in tracking the traffic source of the campaign.

How to test Deep Links on Android

Testing Deep Links are important to ensure a high-end user experience. Functioning of Deep Links directly impacts user engagement; that is why testing has to be performed diligently.

For getting accurate results, considering real user conditions is a must. Thus, it is recommended to perform Deep Link Testing on real devices. However, buying and maintaining real devices is costly. Hence using real device cloud, like BrowserStack, can be a great way to test deep linking under real user conditions on 3000+ browser device combinations.

Test Deep Link URL on Real Devices for Free

Following are the different ways of testing deep links on Android devices:

Using Android Debug Bridge

By using Android Debug Bridge (ADB) shell commands one can test the deep link flow. It is used to verify if the link navigates to the correct section of your app.

Open the terminal and enter the following command:

adb shell am start -W -a android.intent.action.VIEW -d "your deep link url"

This command starts the ADB shell with the VIEW action and specifies the deep link URL to be tested.

Using Appium Driver

The below example shows two ways of testing that the logged-in experience works correctly: first by navigating the login UI with Appium, and then by using the deep linking trick described in this edition.

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileBy;
import io.appium.java_client.android.AndroidDriver;
import java.io.IOException;
import java.net.URL;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

@RunWith(JUnit4.class)
public class Appium_Deep_Linking {

private String APP_ANDROID = "https://github.com/cloudgrey-io/the-app/releases/download/v1.2.1/TheApp-v1.2.1.apk";

private String AUTH_USER = "alice";
private String AUTH_PASS = "mypassword";

@Test
public void testLoginSlowAndroid() throws IOException {
AndroidModel model = new AndroidModel();
AndroidDriver driver = new AndroidDriver(new URL("http://localhost:4723/wd/hub"), model.caps);
runStepByStepTest(driver, model);
}

private void runStepByStepTest(AppiumDriver driver, Model model) {
WebDriverWait wait = new WebDriverWait(driver, 10);

try {
wait.until(ExpectedConditions.presenceOfElementLocated(model.loginScreen)).click();
wait.until(ExpectedConditions.presenceOfElementLocated(model.username)).sendKeys(AUTH_USER);
wait.until(ExpectedConditions.presenceOfElementLocated(model.password)).sendKeys(AUTH_PASS);
wait.until(ExpectedConditions.presenceOfElementLocated(model.loginBtn)).click();
wait.until(ExpectedConditions.presenceOfElementLocated(model.getLoggedInBy(AUTH_USER)));
} finally {
driver.quit();
}
}


@Test
public void testDeepLinkForDirectNavAndroid () throws IOException {
AndroidModel model = new AndroidModel();
AndroidDriver driver = new AndroidDriver(new URL("http://localhost:4723/wd/hub"), model.caps);
runDeepLinkTest(driver, model);
}

private void runDeepLinkTest(AppiumDriver driver, Model model) {
WebDriverWait wait = new WebDriverWait(driver, 10);

try {
driver.get("theapp://login/" + AUTH_USER + "/" + AUTH_PASS);
wait.until(ExpectedConditions.presenceOfElementLocated(model.getLoggedInBy(AUTH_USER)));
} finally {
driver.quit();
}
}

private abstract class Model {
public By loginScreen = MobileBy.AccessibilityId("Login Screen");
public By loginBtn = MobileBy.AccessibilityId("loginBtn");
public By username;
public By password;

public DesiredCapabilities caps;

abstract By getLoggedInBy(String username);
}

}

private class AndroidModel extends Model {
AndroidModel() {
username = MobileBy.AccessibilityId("username");
password = MobileBy.AccessibilityId("password");

caps = new DesiredCapabilities();
caps.setCapability("platformName", "Android");
caps.setCapability("deviceName", "Android Emulator");
caps.setCapability("app", APP_ANDROID);
caps.setCapability("automationName", "UiAutomator2");
}

public By getLoggedInBy(String username) {
return By.xpath("//android.widget.TextView[@text=\"You are logged in as " + username + "\"]");
}
}
}

Test Deep Links using Appium

Using ActivityTestRule and Espresso Intent

Follow the steps mentioned below to test Deep Links:

Step 1 Start with an activity rule

@Rule public ActivityTestRule<YourAppMainActivity> mActivityRule = new ActivityTestRule<>(YourAppMainActivity.class, true, false);

Step 2 Parse the URI (Uniform Resource Identifier) from the link and return the intent

String uri = "http://your_deep_link_from_gmail"; 
private Intent getDeepLinkIntent(String uri){ 
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri))
.setPackage(getTargetContext()
.getPackageName()); 
return intent;
}

Step 3 Launch the intent using the Activity Rule

Intent intent = getDeepLinkIntent(deepLinkUri); mActivityRule.launchActivity(intent);

Here’s a sample test that captures the above steps of Deep Link Testing using ActivityTestRule and Espresso Intent

import android.support.test.espresso.intent.Intents
import android.support.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent
import android.support.test.rule.ActivityTestRule
import android.support.test.runner.AndroidJUnit4
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import android.content.Intent
import android.net.Uri

@RunWith(AndroidJUnit4::class)
class DeepLinkingTest {

@Rule
@JvmField
val activityTestRule = ActivityTestRule(MainActivity::class.java)

@Before
fun setUp() {
Intents.init()
}

@After
fun tearDown() {
Intents.release()
}

@Test
fun should_launch_secondActivity_when_deepLinkingToActivityTwo() {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("myapp://example.com?screen=activitytwo"))
activityTestRule.launchActivity(intent)
intended(hasComponent(SecondActivity::class.java!!.getName()))
}

}

How to Deep Links on iOS

Following is the method to test deep links on iOS devices:

Using XCUITest

Use XCUIApplication class to launch, monitor, and terminate your app in a UI Test.

  • For Launching the Application, enter the below command.
    app.launch()
  • For Terminating the Application, use the following command.

    app.terminate()
    
  • For Activating the Application, enter the following command.

    app.activate()
    
    

To perform a UI test of a Safari deeplink, it is recommended that the required app should run in the background. If any other app is launched during an ongoing UI test, it is similar to launching the required app, but with a different bundle identifier. For launching Safari, the bundle identifier “com.apple.mobilesafari” is triggered.

To launch the required app and switch back to Safari right after, run the following code:

func testDeeplinkFromSafari() {
let app = XCUIApplication()
app.launch()
let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")
safari.launch()
}

For deeplinking back to the app, Safari has to be controlled similar to any regular UI test. This can be done in three steps:

  • identify the address bar,
  • type the deep link URL,
  • click on the “Go” button.

Ideally, Safari will deeplink back to the required app, depicting that the deeplink logic in the app is working as expected.

func testDeeplinkFromSafari() {
// Launch our app
let app = XCUIApplication()
app.launch()
// Launch Safari and deeplink back to our app
openFromSafari("swiftrocks://profile")
// Make sure Safari properly switched back to our app before asserting
XCTAssert(app.wait(for: .runningForeground, timeout: 5))
// Assert that the deeplink worked by checking if we're in the "Profile" screen
XCTAssertTrue(app.navigationBars["Profile"].exists)
}

private func openFromSafari(_ urlString: String) {
let safari = XCUIApplication(bundleIdentifier: "com.apple.mobilesafari")
safari.launch()
// Make sure Safari is really running before asserting
XCTAssert(safari.wait(for: .runningForeground, timeout: 5))
// Type the deeplink and execute it
let firstLaunchContinueButton = safari.buttons["Continue"]
if firstLaunchContinueButton.exists {
firstLaunchContinueButton.tap()
}
safari.buttons["URL"].tap()
let keyboardTutorialButton = safari.buttons["Continue"]
if keyboardTutorialButton.exists {
keyboardTutorialButton.tap()
}
safari.typeText(urlString)
safari.buttons["Go"].tap()
_ = confirmationButton.waitForExistence(timeout: 2)
if confirmationButton.exists {
confirmationButton.tap()
}
}

It is best to add the additional wait (for: .runningForeground) assertion for safety. Inserting additional wait allows checking whether the app switching worked before the attempt to assert. If it fails, then it is evident that the failure is because the app failed to switch, and not due to something not being present in the UI of the app.

Testing Deep Links on Real Device Cloud

Deep Links play an important role in driving user traffic to an application from URLs; hence it is essential to test its functionality thoroughly to identify any bottlenecks. When testing deep linking on Real Devices, one can decipher the issues that could cause interruptions or altered behavior of the deep link. Testing on BrowserStack’s real device cloud includes all the real user conditions while performing tests. Thus, allowing developers to test on 3000+ browser-device combinations for cross-compatibility testing.

BrowserStack App Automate offers cloud-based access to both the latest and legacy devices (Android, iOS, and Windows) installed with real operating systems. App Automate also requires no additional setup, helping testers save precious time and meet their deadlines that much faster.

Since users demand high-functioning and engaging campaigns, deep link testing is an absolute requirement before releasing any campaign. By running deep link tests on real Android devices, testers can ensure that apps are working as expected in real user conditions. Run as many tests as possible on as many real Android devices to offer a consistently optimal user experience.

Tags
Android Appium iOS Mobile App Testing

Featured Articles

How to Download and Install Appium

How to Run Android Apps in a Browser

Curated for all your Testing Needs

Actionable Insights, Tips, & Tutorials delivered in your Inbox
By subscribing , you agree to our Privacy Policy.
thank you illustration

Thank you for Subscribing!

Expect a curated list of guides shortly.

BrowserStack Logo Run Appium tests on real Android and iOS devices Contact us Get Started Free