javatestngappiumbrowserstackbrowserstack-app-automate

How to quit mobile driver session in parallel execution - testng in Browserstack


I am working on TestNG framework which is integrated with Browserstack for Mobile automation. The framework behaved very well until we were running a single thread in browser stack for our test execution. The problem actually started when we integrated parallel execution. Our framework has a json file where we define all the device capabilities and call them for execution. Example is given below:

  "about": {
    "project": "Demo-DexAutomation",
    "team": "QE",
    "environment": "QA",
    "releaseVersion": "1.0"
  },
  "gui": {
    "ss:remoteExecutor": {
      "browserstack": {
        "ss:remoteAddress": "http://hub-cloud.browserstack.com/wd/hub",
        "browserstack.user": “<Username>”,
        "browserstack.key": “<access key>“
      }
    },
    "defaultProfile": "browserstack-oneplus-7T",
    "multiProfile": [
      "browserstack-samsung-galaxy-s21-plus",
      "browserstack-oneplus-7T",
      "browserstack-google-pixel-4"
    ],
    "randomProfile": [
      "browserstack-samsung-galaxy-s21-plus",
      "browserstack-google-pixel-4",
      "browserstack-oneplus-7T"
    ],
   "browserstack-samsung-galaxy-s21-plus": {
        "ss:remoteExecutor": "browserstack",
        "platformName": "Android",
        "app": "bs://fbac93a34795331e12e3949ac65d120e73422217",
        "automationName": "UiAutomator2",
        "device": "Samsung Galaxy S21 Plus",
        "os_version": "11.0",
        "project": "Android Automation",
        "build": "DEX Android Smoke Execution",
        "name": "Samsung Galaxy S21 Plus Tests",
        "browserstack.networkLogs": true,
        "autoGrantPermissions": "true",
        "autoAcceptAlerts": "true",
        "acceptInsecureCerts": true,
        "acceptSslCert" : true
      },
      "browserstack-google-pixel-4": {
        "ss:remoteExecutor": "browserstack",
        "platformName": "Android",
        "app": "bs://fbac93a34795331e12e3949ac65d120e73422217",
        "automationName": "UiAutomator2",
        "device": "Google Pixel 4",
        "os_version": "10.0",
        "project": "Android Automation",
        "build": "DEX Android Smoke Execution",
        "name": "Google Pixel 4 Tests",
        "browserstack.networkLogs": true,
        "autoGrantPermissions": "true",
        "autoAcceptAlerts": "true",
        "acceptInsecureCerts": true,
        "acceptSslCert" : true
      },
      "browserstack-oneplus-7T": {
        "ss:remoteExecutor": "browserstack",
        "platformName": "Android",
        "app": "bs://fbac93a34795331e12e3949ac65d120e73422217",
        "automationName": "UiAutomator2",
        "device": "OnePlus 7T",
        "os_version": "10.0",
        "project": "Android Automation",
        "build": "DEX Android Smoke Execution",
        "name": "One plus 7T Tests",
        "browserstack.networkLogs": true,
        "autoGrantPermissions": "true",
        "autoAcceptAlerts": "true",
        "acceptInsecureCerts": true,
        "acceptSslCert" : true
      },
    }
  },
  "dashboard": {
    "url": "http://localhost:4000",
    "disabled": true
  }
}

Now, We use RandomProfile from above json for running testcases. And the code will actually select random profile based on the availability of the device in the browserstack. We can also use Default profile and multiProfile.

Random profile -> selects differ devices for each test case picked for execution

Default profile -> calls the single device added to the profile for all testcases

multi profile -> runs each testcase in every device mentioned under the profile.

While running TestNG execution in Parallel, the driver quit does not work properly. Calling quit method after completing every test case inside @Test annotation, kills all the actively running session during parallel execution. Same behaviour observed when quit is called in @AfterMethod. Also tried calling driver.quit in @AfterTest and @AfterClass both does not work eventually end up in giving timeout session in browserstack.

Example of couple of testcases: - I have removed the driver.quit statement in the below code snippet, but have tried them as stated above.

    public void likeOrUnlikeAContent() {
        Profile deviceProfile = null;
        try {
            deviceProfile = singletonUtils.getUnusedRandomProfile(profile);
            SlingshotReporter.log("********************Test Case: Like or Unlike a Content Navigating from Home Page********************");
            DriverFactory.get().build(CommonUtils.setRunTimeCapability(deviceProfile, runTimeCapabilityUtils.getRuntimeCapabilities()));
            mobileDriver = DriverFactory.getDriver();
            CommonUtils.setSessionName(mobileDriver, "Like or Unlike a Content Navigating from Home Page");
            commonUtils.loginToAppWithSSO(mobileDriver, "username1", EMPLOYEE);
            HomePageFunctions homePageFunctions = new HomePageFunctions(mobileDriver);
            homePageFunctions.navigateToAltimetrikTab(CommonUtils.ScrollDirection.HORIZONTAL,CommonUtils.Direction.RIGHT);
            homePageFunctions.clickOnAltiverseCard();
            CommonUtils.scrollIntoViewIDWithDirection(mobileDriver,CommonUtils.ScrollDirection.VERTICAL,UP,"likeContent");
            Assert.assertTrue(homePageFunctions.verifyLikeButtonDisplayed());
            homePageFunctions.verifyLikeCount();
            CommonUtils.closeApp(mobileDriver);
            CommonUtils.setStatusForTestCase(mobileDriver, "Passed", "Test Execution Completed");
            singletonUtils.reAssignUsedDevices(deviceProfile.getProfileName());
        } catch (Exception e) {
            SlingshotReporter.log("-----------------Test case failed due to below error-----------------");
            CommonUtils.setStatusForTestCase(mobileDriver, "Failed", e.getMessage());
            singletonUtils.reAssignUsedDevices(Objects.requireNonNull(deviceProfile).getProfileName());
            Assert.fail(e.getMessage());
        }
    }



    @Test(groups = {"Smoke1"}, priority = 2)
    public void commentAndReplyToCommentOnAContent() {
        Profile deviceProfile = null;
        try {
            deviceProfile = singletonUtils.getUnusedRandomProfile(profile);
            SlingshotReporter.log("********************Test Case: Comment and Reply to a comment on a Content Navigating from Home "
                + "Page********************");
            DriverFactory.get().build(CommonUtils.setRunTimeCapability(deviceProfile, runTimeCapabilityUtils.getRuntimeCapabilities()));
            mobileDriver = DriverFactory.getDriver();
            CommonUtils.setSessionName(mobileDriver, "Comment and Reply to a comment on a Content Navigating from Home Page");
            commonUtils.loginToAppWithSSO(mobileDriver, "username1", EMPLOYEE);
            HomePageFunctions homePageFunctions = new HomePageFunctions(mobileDriver);
            homePageFunctions.navigateToAltimetrikTab(CommonUtils.ScrollDirection.HORIZONTAL,CommonUtils.Direction.RIGHT);
            homePageFunctions.clickOnAltiverseCard();
            CommonUtils.scrollIntoViewIDWithDirection(mobileDriver,CommonUtils.ScrollDirection.VERTICAL,UP,"commentCnt");
            homePageFunctions.commentOnAContent();
            Assert.assertTrue(homePageFunctions.verifyCommentOrReplyPosted());
            homePageFunctions.replyToAComment();
            Assert.assertTrue(homePageFunctions.verifyCommentOrReplyPosted());
            homePageFunctions.exitFromCommentDetailPage();
            CommonUtils.closeApp(mobileDriver);
            CommonUtils.setStatusForTestCase(mobileDriver, "Passed", "Test Execution Completed");
            singletonUtils.reAssignUsedDevices(deviceProfile.getProfileName());
        } catch (Exception e) {
            SlingshotReporter.log("-----------------Test case failed due to below error-----------------");
            CommonUtils.setStatusForTestCase(mobileDriver, "Failed", e.getMessage());
            singletonUtils.reAssignUsedDevices(Objects.requireNonNull(deviceProfile).getProfileName());
            Assert.fail(e.getMessage());
        }
    }

Testng Xml looks like this:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="Mobile Automation" verbose="1" thread-count="3" parallel="methods">
    <listeners>
        <listener class-name="com.altimetrik.qe.slingshot.reporter.SlingshotTestNGReporter"/>
        <listener class-name="com.altimetrik.qe.slingshot.testng.listeners.NeedsDriverListener"/>
    </listeners>

    <test name="DEX UI Tests">
        <classes>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.SmokeTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.SuccessStoryTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.EmployeeLandingTest"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.InnovateAndInspireTest"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.TweetTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.ContributorTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.ReviewerTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.CandidateLandingTest"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.JobOpportunitiesTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.JobDetailsPageTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.MySpaceTests"/>
            <class name="com.altimetrik.pp.dexapp.mobileAutomation.DiscoverDexTest"/>

        </classes>
    </test>
</suite>

Kindly help me to resolve this issue, been trying every solution provided over internet, but nothing works.


Solution

  • Used BeforeTest and AfterTest Annotation with getdriver() method getting the current driver from the pool drivers in the parallel.

    AfterTest contains simply getdriver().quit();