Cucumber-js: "O ID da sessão é nulo. Usando o WebDriver depois de chamar quit ()?" ou "NoSuchSessionError: esta instância do driver não tem um ID de sessão válido (você chamou WebDriver.quit ()?) e não pode mais ser usado." quando o próximo cenário for executado

Criado em 29 dez. 2016  ·  14Comentários  ·  Fonte: cucumber/cucumber-js

Condição prévia:
_test.feature_

Feature:  Three tests

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

Scenario: one
    When something happens     <------ failed by timeout

Scenario: two
    When something else happens

Scenario: three
    When something else happens

_world.js_

var pc = require('../../../lib/index.js');
var url = require('../../../lib/get.base.url.js');

var world = function () {
    this.setDefaultTimeout(30000);   <-----   default timeout
    var seleniumAddress = url.getSeleniumHubURL();
    var options = {baseUrl: url.getBaseURL()};
    this.World = pc.world(seleniumAddress, options);
    this.After(function (scenario, callback) {
        this.takeSc(scenario, callback);
    });
};
module.exports = world;

_index.js_

var protractor = require('protractor');
var World = (function (seleniumAddress, options) {
        var desiredCapabilities = options.desiredCapabilities || {};
        var browserOpt = options.browser || desiredCapabilities.browser || "chrome";
        var timeout = options.timeout || 100000;

        function World() {
            var capabilities = protractor.Capabilities[browserOpt]().merge(desiredCapabilities);
            var driver = new protractor.Builder()
                .usingServer(seleniumAddress)
                .withCapabilities(capabilities)
                .build();

            driver.manage().timeouts().setScriptTimeout(timeout);
            var winHandleBefore;
            driver.getWindowHandle().then(function (result) {
                winHandleBefore = result;
            });

            this.browser = protractor.wrapDriver(driver);
            this.protractor = protractor;
            this.by = new protractor.ProtractorBy;

            if (options.assert) this.assert = options.assert;
            if (options.baseUrl) this.baseUrl = options.baseUrl;
            if (options.properties) this.properties = options.properties;

            console.log("Base URL:" + this.baseUrl);

            this.takeSc = function (scenario, callback) {
                if (scenario.isFailed()) {
                    driver.takeScreenshot().then(function (png) {
                        var decodedImage = new Buffer(png, 'base64');
                        scenario.attach(decodedImage, 'image/png');
                    }).then(function () {
                        driver.quit().then(function () {
                            callback();
                        });
                    });
                }
                else {
                    driver.quit().then(function () {
                        callback();
                    });
                }
            };
        }

        return World;
    });
module.exports.world = World;

_steps.js_

var steps = function () {
    this.When(/^something happens$/, function (callback) {
        this.browser.sleep(13000);
        this.browser.findElement(this.by.xpath("//somexpath")).getText().then(function (result) {
            callback();
        });
    });

    this.When(/^something else happens$/, function (callback) {
        this.browser.ignoreSynchronization = false;
        this.browser.get("http://gmail.com").then(function () {
            callback();
        });
    });

    this.When(/^Given I navigate to "([^"]*)"$/, function (site, callback) {
        this.browser.ignoreSynchronization = true;
        this.browser.get(site).then(function () {
            callback();
        });
    });
};

module.exports = steps;

Passos para reproduzir:
1. O primeiro cenário caiu por DefaultTimeout (mais de 30 segundos, conforme mencionado antes em _world.js_)

  1. O segundo cenário começa

Resultado atual:
O segundo cenário falhou com "ID de sessão é nula. Usando WebDriver após chamar quit ()?" exceção. Mas
o terceiro é aprovado.

Resultado esperado
O segundo cenário também deve ser aprovado. Os testes anteriores não devem impactar outro

Comentários muito úteis

@ThaKing, o que você quer dizer com reescrever testes para as promessas, por favor?

Todos 14 comentários

Você pode fornecer a saída? Acabei de testar um pequeno exemplo em que crio um webdriver no construtor do mundo e saio em um after hook e funciona bem com vários cenários (usando selênio webdriver diretamente, não transferidor).

@charlierudolph Você tentou meu caso (arquivos mencionados acima)?

_webdrive console_

17:13:29.349 INFO - Executing: [new session: Capabilities [{browserName=chrome}]])
17:13:29.351 INFO - Creating a new session for Capabilities [{browserName=chrome}]
Starting ChromeDriver 2.25.426924 (649f9b868f6783ec9de71c123212b908bf3b232e) on port 17569
Only local connections are allowed.
17:13:29.883 INFO - Done: [new session: Capabilities [{browserName=chrome}]]
17:13:29.904 INFO - Executing: [set script timeout: 100000])
17:13:29.910 INFO - Done: [set script timeout: 100000]
17:13:29.919 INFO - Executing: [get current window handle])
17:13:29.924 INFO - Done: [get current window handle]
17:13:29.932 INFO - Executing: [get: http://google.com/])
17:13:31.265 INFO - Done: [get: http://google.com/]
17:13:41.298 INFO - Executing: [take screenshot])
17:13:41.521 INFO - Done: [take screenshot]
17:13:41.531 INFO - Executing: [delete session: 8e88decd-d531-4f0c-af3c-3b5ad4136793])
17:13:41.602 INFO - Done: [delete session: 8e88decd-d531-4f0c-af3c-3b5ad4136793]
17:13:41.624 INFO - Executing: [new session: Capabilities [{browserName=chrome}]])
17:13:41.626 INFO - Creating a new session for Capabilities [{browserName=chrome}]
Starting ChromeDriver 2.25.426924 (649f9b868f6783ec9de71c123212b908bf3b232e) on port 25151
Only local connections are allowed.
17:13:42.284 INFO - Done: [new session: Capabilities [{browserName=chrome}]]
17:13:52.328 INFO - Executing: [new session: Capabilities [{browserName=chrome}]])
17:13:52.331 INFO - Creating a new session for Capabilities [{browserName=chrome}]
Starting ChromeDriver 2.25.426924 (649f9b868f6783ec9de71c123212b908bf3b232e) on port 22830
Only local connections are allowed.
17:13:52.828 INFO - Done: [new session: Capabilities [{browserName=chrome}]]
17:13:52.838 INFO - Executing: [set script timeout: 100000])
17:13:52.843 INFO - Done: [set script timeout: 100000]
17:13:52.857 INFO - Executing: [get current window handle])
17:13:52.861 INFO - Done: [get current window handle]
17:13:52.869 INFO - Executing: [get: http://google.com/])
17:13:54.128 INFO - Done: [get: http://google.com/]
17:13:54.143 INFO - Executing: [get: data:text/html,<html></html>])
17:13:54.221 INFO - Done: [get: data:text/html,<html></html>]
17:13:54.229 INFO - Executing: [execute script: window.name = "NG_DEFER_BOOTSTRAP!" + window.name;window.location.replace("http://gmail.com/");, []])
17:13:55.136 INFO - Done: [execute script: window.name = "NG_DEFER_BOOTSTRAP!" + window.name;window.location.replace("http://gmail.com/");, []]
17:13:55.146 INFO - Executing: [execute script: return window.location.href;, []])
17:13:55.168 INFO - Done: [execute script: return window.location.href;, []]
17:13:55.179 INFO - Executing: [execute async script: try { return (function (attempts, ng12Hybrid, asyncCallback) {
  var callback = function(args) {
    setTimeout(function() {
      asyncCallback(args);
    }, 0);
  };
  var check = function(n) {
    try {
      if (!ng12Hybrid && window.getAllAngularTestabilities) {
        callback({ver: 2});
      } else if (window.angular && window.angular.resumeBootstrap) {
        callback({ver: 1});
      } else if (n < 1) {
        if (window.angular) {
          callback({message: 'angular never provided resumeBootstrap'});
        } else {
          callback({message: 'retries looking for angular exceeded'});
        }
      } else {
        window.setTimeout(function() {check(n - 1);}, 1000);
      }
    } catch (e) {
      callback({message: e});
    }
  };
  check(attempts);
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [10, false]])
17:14:04.174 INFO - Executing: [take screenshot])
17:14:05.299 INFO - Done: [execute async script: try { return (function (attempts, ng12Hybrid, asyncCallback) {
  var callback = function(args) {
    setTimeout(function() {
      asyncCallback(args);
    }, 0);
  };
  var check = function(n) {
    try {
      if (!ng12Hybrid && window.getAllAngularTestabilities) {
        callback({ver: 2});
      } else if (window.angular && window.angular.resumeBootstrap) {
        callback({ver: 1});
      } else if (n < 1) {
        if (window.angular) {
          callback({message: 'angular never provided resumeBootstrap'});
        } else {
          callback({message: 'retries looking for angular exceeded'});
        }
      } else {
        window.setTimeout(function() {check(n - 1);}, 1000);
      }
    } catch (e) {
      callback({message: e});
    }
  };
  check(attempts);
}).apply(this, arguments); }
catch(e) { throw (e instanceof Error) ? e : new Error(e); }, [10, false]]
17:14:05.546 INFO - Done: [take screenshot]

_cucumber console_

(node:20927) DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
Feature: Three tests

Base URL:http://google.com
  Scenario: one
  ✔ Given Given I navigate to "http://google.com"
  ✖ When something happens

Base URL:http://google.com
  Scenario: two
  ✖ Given Given I navigate to "http://google.com"
  - When something else happens

Base URL:http://google.com
  Scenario: three
  ✔ Given Given I navigate to "http://google.com"
  ✖ When something else happens
[17:14:05] E/protractor - Could not find Angular on page http://gmail.com/ : retries looking for angular exceeded

Failures:

1) Scenario: one - src/test/features/test.feature:6
   Step: When something happens - src/test/features/test.feature:7
   Step Definition: src/test/features/step_definitions/steps.js:3
   Message:
     function timed out after 10000 milliseconds

2) Scenario: two - src/test/features/test.feature:9
   Step: Given Given I navigate to "http://google.com" - src/test/features/test.feature:4
   Step Definition: src/test/features/step_definitions/steps.js:17
   Message:
     NoSuchSessionError: This driver instance does not have a valid session ID (did you call WebDriver.quit()?) and may no longer be used.
       at checkHasNotQuit (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/webdriver.js:395:15)
       at /home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/webdriver.js:382:7
       at TaskQueue.execute_ (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:2913:14)
       at TaskQueue.executeNext_ (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:2896:21)
       at asyncRun (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:2775:27)
       at /home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:639:7

     From: Task: WebElement.getText()
       at WebDriver.schedule (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/webdriver.js:377:17)
       at WebElementPromise.schedule_ (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/webdriver.js:1744:25)
       at WebElementPromise.getText (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/webdriver.js:2025:17)
       at World.<anonymous> (/home/thaking/test/tests-ui-js/src/test/features/step_definitions/steps.js:5:64)
       at _combinedTickCallback (internal/process/next_tick.js:67:7)
       at process._tickCallback (internal/process/next_tick.js:98:9)


3) Scenario: two - src/test/features/test.feature:9
   Step: After 
   Step Definition: src/test/features/step_definitions/support/world.js:9
   Message:
     function timed out after 10000 milliseconds

4) Scenario: three - src/test/features/test.feature:12
   Step: When something else happens - src/test/features/test.feature:13
   Step Definition: src/test/features/step_definitions/steps.js:10
   Message:
     function timed out after 10000 milliseconds

5) Scenario: three - src/test/features/test.feature:12
   Step: After 
   Step Definition: src/test/features/step_definitions/support/world.js:9
   Message:
     Error: Angular could not be found on the page http://gmail.com/. If this is not an Angular application, you may need to turn off waiting for Angular. Please see https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load
       at /home/thaking/test/tests-ui-js/node_modules/protractor/built/browser.js:503:23
       at ManagedPromise.invokeCallback_ (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:1379:14)
       at TaskQueue.execute_ (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:2913:14)
       at TaskQueue.executeNext_ (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:2896:21)
       at asyncRun (/home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:2775:27)
       at /home/thaking/test/tests-ui-js/node_modules/selenium-webdriver/lib/promise.js:639:7
       at process._tickCallback (internal/process/next_tick.js:103:7)

3 scenarios (3 failed)
6 steps (3 failed, 1 skipped, 2 passed)
0m35.995s

Process finished with exit code 1

@ThaKing seu exemplo é enorme e parece estar faltando algumas dependências.

Seu código faz referência a um arquivo get.base.url.js que não está incluído.
Também parece incluir a execução de selênio em outro processo que não está documentado.

Parece que alguns erros podem não estar sendo relatados em seu gancho After por causa de como você está misturando promessas e retornos de chamada.

driver.quit().then(function () {
  callback();
})

Com o código acima, você não está cobrindo o caso de quit falhar. Você precisa adicionar .catch ou passar uma segunda função para .then . Você tem um problema semelhante em quase todos os lugares.

Passos / ganchos de suporte de pepino que retornam promessas, por isso, recomendo mudar para apenas promessas. Também tento nunca deixar um timeout de step / hook. Se você implementar seus próprios limites de tempo nos componentes internos da etapa, receberá uma mensagem de erro útil sobre o motivo da falha da etapa, em vez da mensagem muito inútil: function timed out after 10000 milliseconds

No geral, estou confiante de que o Pepino não está permitindo que um cenário tenha efeito em outro e, felizmente, ao obter esses outros erros relatados, você será capaz de determinar o problema.

Este tempo limite
_steps.js_

 this.When(/^something happens$/, function (callback) {
        this.browser.sleep(13000);   <----------- timeout
        this.browser.findElement(this.by.xpath("//somexpath")).getText().then(function (result) {
            callback();
        });
    });

Eu usei por exemplo. Na vida real eu tenho um método que faz algo, mas falhou por
_world.js_
this.setDefaultTimeout(30000); <----- default timeout

e após esse tempo limite, o próximo cenário falha por exceção.

get.base.url.js me retorna o url do aplicativo e o url do hub de selênio.

var url = function () {
    url.prototype.getBaseURL = function () {
        var URL = process.env.BASE_URL;
        return (URL === undefined ? 'http://google.com' : URL);
    };

    url.prototype.getSeleniumHubURL = function () {
        var SELENIUM_URL = process.env.SELENIUM_HUB_URL;
        return (SELENIUM_URL === undefined ? 'http://localhost:4444/wd/hub' : SELENIUM_URL);
    };
};

module.exports = new url();

Talvez este não seja um problema do pepino, então obrigado pela ajuda

@ThaKing

Oi,

Eu estou experimentando o mesmo problema. (Tempo limite do primeiro cenário, segundo mostra imediatamente o erro de "WebDriverError: ID da sessão é nula. Usando WebDriver após chamar quit ()?")

Você encontrou alguma solução para isso?

@pantherqin começamos a reescrever nossos testes para as Promessas e parece que o erro desapareceu

@ThaKing, o que você quer dizer com reescrever testes para as promessas, por favor?

Eu fiz uma solução para essa falha quando você usou o restartBrowserBetweenTests: true, quando o navegador reiniciou ele perdeu as referências por não poder interagir com a página, para resolver esse problema você tem que fazer uma função em um objeto para inicializar os localizadores, essa função deve ser chamada sempre que você vai executar o teste.

No meu repositório tem uma solução que eu fiz: https://github.com/tuliobluz/protractor-cucumber-pageobject

Arquivo PageObejct: e2e / pages / spec.po.js

'use strict';

let nameInput,
  greeting;

module.exports = {
  init: () => {
    nameInput = element(by.model('yourName'));
    greeting = element(by.binding('yourName'));

  },
  get: (string) => {
    return browser.get(string);
  },
  setName: (name) => {
    return nameInput.sendKeys(name);
  },
  getGreetingText: () => {
    return greeting.getText();
  }
}

Arquivo de especificações: e2e / specs / spec.spec.js

let specPage = require('../pages/spec.po.js');

let chai = require('chai');
let chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
let expect = chai.expect;
var {setDefaultTimeout} = require('cucumber');
setDefaultTimeout(60 * 1200);

Before(function(){
    specPage.init();
})

Given('The user go to {string}', function (string) {
    specPage.get(string);
});

When('The user adds {string} in the name field', function (string) {
    specPage.setName(string);
});

Then('The user should see Hello with the username', function () {
    expect(specPage.getGreetingText())
        .to.eventually.equal('Hello Tulio!')
});

Fiz o mesmo código, mas até obter o "Erro: a função atingiu o tempo limite, certifique-se de que o retorno de chamada seja executado em 72.000 milissegundos"

Fiz o mesmo código, mas até obter o "Erro: a função atingiu o tempo limite, certifique-se de que o retorno de chamada seja executado em 72.000 milissegundos"

Eu enviei para você, como consertar isso.

https://medium.com/@melayer.sima/spec -spec-js-6d4d8f6d7b1a

Eu estava tendo o mesmo problema. Investigando e depurando por horas, percebi que nosso framework está criando uma nova instância do driver apenas quando a instância do driver é nula e está retornando a instância anterior se não for nula. Presumo que chamar driver.quit () não atribui automaticamente um valor nulo à instância do driver atual, portanto, resolvi o problema definindo explicitamente o valor como nulo em meu gancho After.
Espero que isso possa ajudar alguém com um problema semelhante.

@ sumbhatt11 Qual é a aparência do código que você escreveu para resolver esse problema?

Eu estava recebendo o mesmo erro. Como @ sumbhatt11 fez, eu procurei por horas. Tenho uma classe Driver.java para poder ter apenas 1 driver. É a lógica singleton. Se já houver um driver, eu o utilizo chamando o método Driver.getDriver que codifiquei. Usando essa metodologia, resolvi o erro. Ele fornece apenas 1 driver e apenas 1 ID de sessão, tanto quanto eu entendi. Não use WebDrivers estáticos em todas as classes. Crie uma classe Driver, codifique um inicializador de driver e um método getter.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

travi picture travi  ·  5Comentários

pellekrogholt picture pellekrogholt  ·  3Comentários

hdorgeval picture hdorgeval  ·  3Comentários

NoNameProvided picture NoNameProvided  ·  5Comentários

edwinwright picture edwinwright  ·  3Comentários