0

My issue is similar to this- SessionNotFoundException: Session ID is null. Using WebDriver after calling quit()? (Selenium)

When i run the test cases individually it runs fine but when i run them from testng.xml 2nd test case onward everything fails due to session id being null. I have been looking around for solution and figured the issue is with scoping of driver. Can anybody tell me what is the best way to solve this?

This is what my framework looks like-

TestCase

package testCase;

import java.util.concurrent.TimeUnit;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import utility.Constant;
import utility.OpentapWrappers;
import utility.Reporter;

public class TC001 extends OpentapWrappers{

    @Test (description="Test")
    public void main() {
        WebDriverWait wait=new WebDriverWait(driver, 60);

        try {
            wait.until(ExpectedConditions.urlContains(Constant.Plumbing_URL));

            /* Validate navigation to Plumbing */
            ValidateUrl(Constant.Plumbing_URL);

        } catch (NoSuchElementException e) {
            e.printStackTrace();
            Reporter.reportStep("NoSuchElementException" , "FAIL");
        }
    }

    @BeforeClass
    public void beforeClass(){
        browserName="firefox";
        testCaseName = "TC001";
        testDescription = "Validate Header";
    }

}

ReusableActions

import java.util.List;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.Select;
import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import utility.Reporter;

public class ReusableActions {

    public static WebDriver driver;
    public ExtentReports extent;
    public static ExtentTest test;

    /* Invoke Browser and enter the URL */

    public static void InvokeApp(String browser, String url) {
        try {
            if (browser.equalsIgnoreCase("chrome")) {
                System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
                driver = new ChromeDriver();
            } else {
                System.setProperty("webdriver.gecko.driver", "D:\\geckodriver.exe");
                DesiredCapabilities capabilities = new DesiredCapabilities();
                capabilities.setCapability("acceptInsecureCerts",true);
                driver = new FirefoxDriver(capabilities);
            }

            //driver.manage().window().maximize();
            driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
            driver.get(url);
            Reporter.reportStep("The browser :" +browser+ " is launched with URL :" +url+ "successfully","PASS");

        } catch (Exception e) {
            e.printStackTrace();
            Reporter.reportStep("The browser :" +browser+ " could not be launched with URL :" +url+ "successfully","FAIL");
        }
    }

    /* Validate URL*/

    public static void ValidateUrl(String URL){
        try {
            if (driver.getCurrentUrl().contains(URL)) {
                Reporter.reportStep("Page is successfully loaded :"+URL, "PASS");
            } else {
                Reporter.reportStep("Page Title :"+driver.getCurrentUrl()+" did not match with :"+URL, "FAIL");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Reporter.reportStep("The URL did not match", "FAIL");
        }
    }


   /* Quit Browser*/

   public void quitBrowser() {

     try {

        driver.quit();

      } catch (Exception e) {

         Reporter.reportStep("The browser could not be closed.", "FAIL");

      }

  }

}

Reporter Class

public class Reporter extends OpentapWrappers{

    private static ExtentTest test;
    private static ExtentReports extent;

    public static void reportStep(String desc, String status) {
        long number = (long) Math.floor(Math.random() * 900000000L) + 10000000L;
        File src = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

        try {
            FileUtils.copyFile(src, new File("D:\\Reports\\Screenshots\\Scr_"+number+".png"));
        } catch (WebDriverException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Write if it is successful or failure or information
        if (status.toUpperCase().equals("PASS")) {
            test.log(LogStatus.PASS, desc + test.addScreenCapture(".\\Screenshots\\Scr_"+number+".png"));

        } else if (status.toUpperCase().equals("FAIL")) {
            test.log(LogStatus.FAIL, desc + test.addScreenCapture(".\\Screenshots\\Scr_"+number+".png"));
            throw new RuntimeException("FAILED");

        } else if (status.toUpperCase().equals("INFO")) {
            test.log(LogStatus.INFO, desc);
        }
    }

    public static void startResult() {
        extent = new ExtentReports("D:\\Reports\\SiteCoreUS.html", false);
        extent.loadConfig(new File("D:\\extentreports-java-2.41.2\\extent-config.xml"));
    }

    public static void startTestCase() {
        test = extent.startTest(testCaseName, testDescription);
    }

    public static void endResult() {
        extent.endTest(test);
        extent.flush();
    }

}

OpenTapWrapper Class

package utility;

public class OpentapWrappers extends ReusableActions {

    protected static String browserName;
    protected static String testCaseName;
    protected static String testDescription;

    @BeforeSuite
    public void beforeSuite() throws FileNotFoundException, IOException {
        Reporter.startResult();
    }

    @BeforeMethod
    public void beforeMethod() {
        Reporter.startTestCase();
        InvokeApp(browserName,Constant.SiteCoreUSURL);
    }

    @AfterSuite
    public void afterSuite() {
        Reporter.endResult();
    }

    @AfterMethod
    public void afterMethod() {
        quitBrowser();
    }

}

1 Answers1

1

You have a lot of complications in your code, the biggest one among them being you having a static reference to ReusableActions#driver. So what happens here is that all the sub-classes of ReusableActions viz., your TC001 end up sharing the same static data member of driver. This is causing a race condition for you.

So when you run two or more @Test methods in parallel they end up sharing the same static WebDriver reference. I guess that is what is causing the problem because one of your @Test method runs to completion very fast and it calls the quit() method on the driver object. Now when the second test method reaches the quit() call, it ends up calling the quit() second time.

Please remove the static references in your entire code.

I also would suggest that you trim down the layers of inheritance that you have in your code. It adds complexity to your code and makes debugging difficult. You might want to favor composition over inheritance.

Take a look at this blog post that I created, wherein you can achieve the same sort of parallel execution for your webdriver tests but by using composition rather than inheritance.

Krishnan Mahadevan
  • 14,121
  • 6
  • 34
  • 66
  • Thank you Krishnan. I stumbled upon your blog last evening and have been referring it. I realize i have a lot to modify. Thank you for the help – Anuradha Kumari Aug 03 '17 at 07:46
  • Done. Now when my invoke method is called, the before invocation method from webdriverlsiterner class is not executed. It executes only after Invoke method has been executed and then fails cz of NullPointerException. – Anuradha Kumari Aug 03 '17 at 08:50
  • This is how i have defined the Invoke method in the ReusableActions. Any idea what i missed? public void InvokeApp(String browser, String url) { try { LocalDriverManager.getDriver().get(url); } catch (Exception e) { e.printStackTrace(); } } – Anuradha Kumari Aug 03 '17 at 08:56
  • I would suggest that you please spend sometime reading and understanding that blog. The code snippets in my blog resort to automatic creation of webdriver before running a `@Test` annotated method. But in your case, the method `InvokeApp()` is being invoked in a `@Before` annotated method. The code snippets in my blog, ignore any method if it doesnt have the `@Test` annotation on top of it. You should be using my blog post code snippets more of like a guidance in terms of how to do it rather than try and retrofit it as is, into your existing code. – Krishnan Mahadevan Aug 03 '17 at 09:08
  • Thanks a lot Krishnan. I found the issue. I actually had no clue about Listeners and what it does. I was hoping I would solve the problem first and then read about it. But reading about it first helped me realize where i was making the mistake. Thanks for the help. :) – Anuradha Kumari Aug 03 '17 at 10:28
  • Cool. Glad to know you figured it out. – Krishnan Mahadevan Aug 03 '17 at 16:58