Cucumber-js: "معرف الجلسة فارغ. هل تستخدم WebDriver بعد استدعاء quit ()؟" أو "NoSuchSessionError: مثيل برنامج التشغيل هذا ليس به معرّف جلسة صالح (هل اتصلت بـ WebDriver.quit ()؟) وربما لم يعد مستخدمًا." عند تشغيل السيناريو التالي

تم إنشاؤها على ٢٩ ديسمبر ٢٠١٦  ·  14تعليقات  ·  مصدر: cucumber/cucumber-js

الشرط المسبق:
_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;

خطوات التكاثر:
1. لقد انخفض السيناريو الأول بواسطة DefaultTimeout (أكثر من 30 ثانية كما هو مذكور سابقًا في _world.js_)

  1. يبدأ السيناريو الثاني

نتيجة فعلية:
فشل السيناريو الثاني مع "معرف الجلسة فارغ. هل تستخدم WebDriver بعد استدعاء quit ()؟" استثناء. لكن
تم تمرير الثالث.

نتيجة متوقعة
يجب أن يمر السيناريو الثاني أيضًا. يجب ألا تؤثر الاختبارات السابقة على اختبارات أخرى

التعليق الأكثر فائدة

ThaKing ماذا تقصد بإعادة كتابة الاختبارات للوعود ، من فضلك؟

ال 14 كومينتر

هل يمكنك تقديم الإخراج من فضلك؟ لقد اختبرت للتو مثالًا صغيرًا جدًا حيث قمت بإنشاء محرك ويب في مُنشئ العالم وتركته في خطاف تلو الآخر وهو يعمل بشكل جيد مع سيناريوهات متعددة (باستخدام محرك الويب السيلينيوم مباشرة ، وليس منقلة).

charlierudolph هل جربت حالتي (الملفات المذكورة أعلاه)؟

_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]

_ وحدة التحكم بالخيار_

(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 مثالك ضخم ويبدو أنه يفتقد بعض التبعيات.

تشير الكود إلى ملف get.base.url.js وهو غير مضمن.
يبدو أيضًا أنه يتضمن تشغيل السيلينيوم في عملية أخرى غير موثقة.

يبدو أنه قد لا يتم الإبلاغ عن بعض الأخطاء في خطافك After بسبب طريقة مزج الوعود وعمليات رد النداء.

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

باستخدام الكود أعلاه ، لا تغطي حالة فشل quit . تحتاج إلى إضافة .catch أو تمرير دالة ثانية إلى .then . لديك مشكلة مماثلة في كل مكان تقريبا.

خطوات دعم الخيار / الخطافات التي ترجع الوعود ، لذلك أنصح بالتحول إلى استخدام الوعود فقط. كما أنني أحاول عدم ترك مهلة خطوة / ربط. إذا قمت بتنفيذ المهلات الخاصة بك على الخطوات الداخلية ، فستتلقى رسالة خطأ مفيدة حول سبب فشل الخطوة بدلاً من الرسالة غير المفيدة للغاية: function timed out after 10000 milliseconds

بشكل عام ، أنا واثق من أن الخيار لا يسمح لسيناريو واحد بالتأثير على سيناريو آخر ، ونأمل من خلال الإبلاغ عن تلك الأخطاء الأخرى ، ستتمكن من تحديد المشكلة.

هذه المهلة
_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();
        });
    });

اعتدت على سبيل المثال. في الحياة الواقعية لدي طريقة تفعل شيئًا ما ، لكنها فشلت
_world.js_
this.setDefaultTimeout(30000); <----- default timeout

وبعد هذه المهلة ، يفشل السيناريو التالي عن طريق الاستثناء.

get.base.url.js بإرجاع عنوان url للتطبيق وعنوان url لمركز السيلينيوم.

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

ربما ، هذه ليست مشكلة cucumber-js من شكرًا لك على المساعدة

تضمين التغريدة

أهلا،

أواجه نفس المشكلة. (مهلة السيناريو الأول ، يظهر الخطأ الثاني على الفور خطأ "WebDriverEriver: معرف الجلسة فارغ. هل تستخدم WebDriver بعد استدعاء quit ()؟")

هل وجدت أي حل لذلك؟

pantherqin بدأنا في إعادة كتابة اختباراتنا للوعود ويبدو أن الخطأ قد اختفى

ThaKing ماذا تقصد بإعادة كتابة الاختبارات للوعود ، من فضلك؟

لقد قمت بحل واحد لهذا الفشل عندما استخدمت اختبارات إعادة التشغيل: إعادة تشغيل المتصفح ، فقد المراجع بسبب عدم تمكنه من التفاعل مع الصفحة ، لحل هذه المشكلة ، عليك القيام بوظيفة واحدة في كائن للتهيئة محددات الموقع ، يجب استدعاء هذه الوظيفة دائمًا ، وسوف تقوم بإجراء الاختبار.

في مستودعي لدي حل قمت به: https://github.com/tuliobluz/protractor-cucumber-pageobject

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

ملف المواصفات: 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!')
});

فعلت نفس الكود ولكن حتى أحصل على "خطأ: انتهت مهلة الوظيفة ، تأكد من تنفيذ رد الاتصال خلال 72000 مللي ثانية"

فعلت نفس الكود ولكن حتى أحصل على "خطأ: انتهت مهلة الوظيفة ، تأكد من تنفيذ رد الاتصال خلال 72000 مللي ثانية"

لقد أرسلت لك كيفية إصلاح هذا.

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

كنت أعاني من نفس المشكلة. عند التحقيق وتصحيح الأخطاء لساعات ، لاحظت أن إطار العمل الخاص بنا يقوم بإنشاء مثيل برنامج تشغيل جديد فقط عندما يكون مثيل برنامج التشغيل فارغًا ويعيد المثيل السابق إذا لم يكن فارغًا. أفترض أن استدعاء driver.quit () لا يقوم تلقائيًا بتعيين قيمة فارغة لمثيل برنامج التشغيل الحالي ، ومن ثم قمت بحل المشكلة عن طريق تعيين القيمة بشكل صريح على أنها خالية في خطاف ما بعد.
آمل أن يساعد هذا شخصًا ما في مشكلة مماثلة.

@ sumbhatt11 كيف يبدو الرمز الذي كتبته لمعالجة هذه المشكلة؟

كنت أتلقى نفس الخطأ. كما فعل @ sumbhatt11 ، بحثت عنه لساعات. لدي فئة Driver.java لأتمكن من الحصول على سائق واحد فقط. إنه المنطق المفرد. إذا كان هناك برنامج تشغيل بالفعل ، فأنا أستخدمه عن طريق استدعاء طريقة Driver.getDriver التي قمت بترميزها. باستخدام هذه المنهجية ، قمت بحل الخطأ. إنه يوفر فقط سائق واحد ومعرف جلسة واحد فقط بقدر ما فهمت. لا تستخدم WebDrivers ثابتة في كل فئة. قم بإنشاء فئة Driver ، وقم بتشفير مُهيئ برنامج التشغيل وطريقة getter.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات