【问题标题】:How to resolve the SessionID=null issue when running the test case from testng.xml从 testng.xml 运行测试用例时如何解决 SessionID=null 问题
【发布时间】:2017-08-03 12:26:10
【问题描述】:

我的问题与此类似- SessionNotFoundException: Session ID is null. Using WebDriver after calling quit()? (Selenium)

当我单独运行测试用例时,它运行良好,但是当我从 testng.xml 第二个测试用例开始运行它们时,由于会话 ID 为空,一切都失败了。我一直在寻找解决方案,并认为问题在于驱动程序的范围。谁能告诉我解决这个问题的最佳方法是什么?

这就是我的框架的样子-

测试用例

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";
    }

}

可重用操作

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");

      }

  }

}

记者类

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 类

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();
    }

}

【问题讨论】:

    标签: java selenium scope testng ui-automation


    【解决方案1】:

    你的代码中有很多复杂的地方,其中最大的一个是你有一个对ReusableActions#driver 的静态引用。所以这里发生的是ReusableActions 的所有子类,即您的TC001 最终共享driver 的相同静态数据成员。这会导致您出现竞争状况。

    因此,当您并行运行两个或多个 @Test 方法时,它们最终会共享相同的静态 WebDriver 引用。我想这就是导致问题的原因,因为您的 @Test 方法之一运行速度非常快,并且它在驱动程序对象上调用了 quit() 方法。现在,当第二个测试方法到达quit() 调用时,它会第二次调用quit()

    请删除整个代码中的静态引用。

    我还建议您减少代码中的继承层。它增加了代码的复杂性并使调试变得困难。您可能更喜欢组合而不是继承。

    查看我创建的 this 博客文章,其中您可以为您的 webdriver 测试实现相同类型的并行执行,但使用组合而不是继承。

    【讨论】:

    • 谢谢克里希南。我昨晚偶然发现了你的博客,并一直在引用它。我意识到我有很多需要修改的地方。感谢您的帮助
    • 完成。现在,当调用我的调用方法时,不会执行来自 webdriverlsiterner 类的调用前方法。它仅在执行 Invoke 方法后执行,然后 cz 的 NullPointerException 失败。
    • 这就是我在 ReusableActions 中定义 Invoke 方法的方式。知道我错过了什么吗? public void InvokeApp(String browser, String url) { try { LocalDriverManager.getDriver().get(url); } 捕捉(异常 e){ e.printStackTrace(); } }
    • 我建议您花一些时间阅读和理解该博客。我博客中的代码 sn-ps 在运行 @Test 注释方法之前求助于自动创建 webdriver。但是在您的情况下,InvokeApp() 方法是在 @Before 带注释的方法中调用的。我博客中的代码 sn-ps,如果上面没有 @Test 注释,请忽略任何方法。您应该使用我的博客文章代码 sn-ps 更像是一个指导,而不是尝试将其按原样改进到您现有的代码中。
    • 非常感谢克里希南。我发现了这个问题。实际上,我对 Listeners 及其作用一无所知。我希望我能先解决这个问题,然后再阅读它。但首先阅读它帮助我意识到我在哪里犯了错误。谢谢您的帮助。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 2021-07-18
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    相关资源
    最近更新 更多