SessionNotFoundException:会话 ID 为空.调用 quit() 后使用 WebDriver?(硒)

我正在尝试使用 Cucumber/Java 编写一些 selenium 自动化 UI 测试.如果我的功能文件中只有一个测试,那么一切正常.但是,如果我添加第二个测试,我会在 driver.get() 上收到此错误:

I am trying to write some selenium automated UI tests using Cucumber/Java. If I have only one test in my feature file, everything works fine. But if I add a second test, I get this error on driver.get():

org.openqa.selenium.remote.SessionNotFoundException: Session ID is null. Using WebDriver after calling quit()?
Build info: version: '2.51.0', revision: '1af067dbcaedd7d2ab9af5151fc471d363d97193', time: '2016-02-05 11:20:57'

基本上,我在一个包中的 InitializeWebdriver 类上初始化 webdriver 变量,然后在其他(步骤定义)类中引用它.我确实将下面列出的步骤定义作为 InitializeWebdriver 类的一部分,并且它工作得很好(直到移动到不同类中的不同步骤.所以我将该步骤移动到 CommonSteps.java 文件以查看它是否然后会失败,确实如此.所以现在我被卡住了.我正在考虑在 @Before 中执行 if (driver.equals(null)) 和如果已经初始化,则执行不同的操作,但我不知道其他操作会是什么.

Basically, I am initializing the webdriver variable on the InitializeWebdriver class in one package, and then referencing it in the other (step definition) classes. I did have the step definition listed below as a part of the InitializeWebdriver class, and it was working just fine (until moved on to a different step in a different class. So I moved that step to a CommonSteps.java file to see if it would then fail, and it did. So now I'm just stuck. I was thinking of doing an if (driver.equals(null)) in the @Before and doing a different action if had already been initialized, but I don't know what that other action would be.

这是我的代码:

tests.feature

tests.feature

Feature:  Two tests

Background:
    Given I navigate to "http://www.google.com"

Scenario: Test one
    When something happens

Scenario: Test two
    When something else happens

初始化WebDriver.java

InitializeWebDriver.java

public class InitializeWebDriver {

    public static WebDriver driver = null;

    @Before
    public void beforeScenario() {
        driver = new ChromeDriver();
    }

    @After
    public void afterScenario() {
        driver.quit();
    }
}

CommonSteps.java

CommonSteps.java

import myPackage.InitializeWebDriver;

public class CommonSteps {

    static WebDriver driver = InitializeWebDriver.driver;

    @Given("^I navigate to "([^"]*)"$")
    public void i_navigate_to(String url) {
        driver.get(value);
    }

谢谢!

推荐答案

我不认为 drivernull,那会导致 NullPointerException 并且它无法知道将其转换为 SessionNotFoundException.所以看起来 driver 已经创建然后结束,即 .quit() 被调用得太快,如错误消息中所建议的那样.

I don't think driver is null, that would cause a NullPointerException and it would have no way of knowing to convert it to a SessionNotFoundException. So it looks like driver has been created and then ended, i.e. .quit() has been called too soon, as suggested in the error message.

这是我认为正在发生的事情:

Here's what I think is happening:

  1. 它开始第一个测试并调用 @Before.这会导致 InitializeWebDriver.driver 被设置为新的 WebDriver.
  2. 只有在这之后才会加载类CommonSteps,所以CommonSteps.driver被设置为刚刚创建的WebDriver.李>
  3. 测试成功运行,.quit()WebDriver 调用,在 @After 方法中.
  4. 然后它开始第二次测试.在 @Before 方法中创建了一个新的 WebDriver.InitializeWebDriver.driver 已更新;但是,CommonSteps.driver 不会更新,因为 driver = InitializeWebDriver.driver; 仅在 CommonSteps 首次加载时发生.
  5. 因此,到driver.get(value)时,driver就是原来的WebDriver,已经是了.quit().
  1. It starts the first test and calls the @Before. This causes InitializeWebDriver.driver to be set as the new WebDriver.
  2. Only after that does it load the class CommonSteps, so CommonSteps.driver is set to the WebDriver that was just created.
  3. The test runs successfully, and .quit() is called on the WebDriver, in the @After method.
  4. Then it starts the second test. A new WebDriver is created in the @Before method. InitializeWebDriver.driver is updated; however, CommonSteps.driver is not updated, because the driver = InitializeWebDriver.driver; only happens when CommonSteps is first loaded.
  5. Therefore, when it gets to driver.get(value), driver is the original WebDriver, which has already been .quit().

这是假设您正在连续运行测试.如果它们是并行的,那就有点不同了.

This is assuming you're running the tests in series. If they're in parallel then it will be a bit different.

基本上,问题在于您为 WebDriver 使用静态属性,不应该在不同的测试运行之间共享这些属性.自从我做这些事情以来已经有一段时间了,我不记得您如何存储范围为测试运行的变量.(无论如何我都无法肯定地回答,因为你没有说你正在使用哪个测试框架:JUnit,还是别的什么?)所以你必须自己修复它,或者询问如何在您使用的任何框架中获取测试范围的变量.

Basically the problem is that you're using static attributes for WebDriver, which shouldn't be shared between different test runs. It's a while since I've done this stuff, and I don't remember how you store variables scoped to a test run. (In any case I wouldn't be able to answer with certainty, since you haven't said which test framework you're using: JUnit, or something else?) So you'll have to fix it yourself, or ask how to get test-scoped variables in whatever framework you're using.

如果你想正确地做到这一点.如果您只是想要一个便宜的修复,并且如果您不打算并行运行测试,我怀疑您可以通过将 driver.get(value); 更改为 InitializeWebDriver 来修复它.driver.get(value);.事实上,我建议你尝试改变它,以确保我在这方面是正确的.

That's if you want to do it properly. If you just want a cheap fix, and if you're not planning to run tests in parallel, I suspect that you can fix it by changing driver.get(value); to InitializeWebDriver.driver.get(value);. In fact, I suggest you try changing that anyway, just to make sure I'm right about this.

相关文章