Cucumber-js: استدعاء الخطوات من تعريفات الخطوة

تم إنشاؤها على ١ يونيو ٢٠١١  ·  31تعليقات  ·  مصدر: cucumber/cucumber-js

السماح بخطوات الاتصال من تعريفات الخطوة.

https://github.com/cucumber/cucumber/wiki/Calling-Steps-from-Step-Definitions

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

: -1:: -1: -1:: -1:: -1:

يعد استدعاء الخطوات من stepdefs إحدى تلك الميزات التي أتمنى ألا أضيفها أبدًا إلى Cucumber (-Ruby) ، لأنها توفر الكثير من الحبال للناس للتعليق عليها. لقد حدث ذلك لأن روبيات روبي تستخدم عمليات إغلاق مجهولة لا يمكنك الاتصال بها من أي مكان آخر (ما لم تمر عبر الأطواق).

مع JavaScript الوضع مختلف ؛ تستخدم تعريفات الخطوة وظائف من الدرجة الأولى!

function x_is_something(x, cb) {
  console.log('x', x);
  cb();
}

Given(/x is (.*)/, x_is_something);

Given(/super x/, function(cb) {
  x_is_something(97, cb);
});

ال 31 كومينتر

عند تنفيذ ذلك ، ضع في اعتبارك أننا نخطط لإيقاف كل شيء بخلاف #steps للقيام بذلك في cucumber-rb. راجع https://github.com/cucumber/cucumber/issues/68

شكرا لك مات. -js ستدعم فقط الخطوات () بعد ذلك.

احب ذلك!

أي تقدم في هذا؟ يبدو وكأنه ميزة حيوية للغاية.

لم يتم التخطيط لهذا كجزء من المعلم الحالي (0.3). يجب أن يكون جزءًا من 0.4.

mattwynne أعتقد أننا نريد دعم step() أيضًا. هل انا صائب؟

تضمين التغريدة ربما يمكنك أن تبدأ بـ #step . من الأسهل تنفيذه لأنك تستدعي خطوة بدلاً من تحليل Gherkin.

أنا شخصياً سأكون سعيدًا باستخدام خيار بدون هذه الميزة ، ولا أستخدمه أبدًا وأعتبره ممارسة سيئة. أفضل دائمًا تفويض الأساليب بدلاً من ذلك.

في النهاية ، إذا أردنا دعم هذا ، أفضل أن أراه مطبقًا في غيركين ، لذلك لديك طريقة لتحديد خطوة ماكرو تحدد مجموعة من الخطوات الأخرى منخفضة المستوى. ثم يُطلب من الخيار فقط استدعاء المستويات الأدنى ولا يحتاج إلى معرفة أن هناك أي رسم خرائط جاري. وهذا هو تفضيلي.

TL ؛ DR: هل يجب أن نضيف حقًا steps() / step() إلى Cucumber.js (و -jvm ، -ruby 2 ، إلخ)؟

أتفق معك تمامًا يا مات. _ للأسف_ ، هذه هي الميزة الأكثر طلبًا الآن على Cucumber.js.

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

من منظور المبرمج ، تبدو تعريفات الخطوة تمامًا مثل الأساليب. أرى أنه نقطة ضعف في Cucumber_s_ اليوم. لا ينبغي أن يتم الكشف عن تعريفات الخطوة على أنها واجهة برمجة تطبيقات وإنما كخريطة ترجمة صريحة ، أو قاموس ، إذا جاز التعبير.

كان لدى msassak أفكار مثيرة للاهتمام حول هذا الأمر بالفعل وأعتقد أنه قام بعمل رائع في إعادة صياغة تلك "التعيينات" في Cucumber 2.0.

يجب أن أقول إنني متردد في العمل على هذه المشكلة بالذات في Cucumber.js في الوقت الحالي. من ناحية أخرى ، لا أريد الاحتفاظ بالميزات فقط بسبب ذوقي / آرائي الشخصية.

: -1:: -1: -1:: -1:: -1:

يعد استدعاء الخطوات من stepdefs إحدى تلك الميزات التي أتمنى ألا أضيفها أبدًا إلى Cucumber (-Ruby) ، لأنها توفر الكثير من الحبال للناس للتعليق عليها. لقد حدث ذلك لأن روبيات روبي تستخدم عمليات إغلاق مجهولة لا يمكنك الاتصال بها من أي مكان آخر (ما لم تمر عبر الأطواق).

مع JavaScript الوضع مختلف ؛ تستخدم تعريفات الخطوة وظائف من الدرجة الأولى!

function x_is_something(x, cb) {
  console.log('x', x);
  cb();
}

Given(/x is (.*)/, x_is_something);

Given(/super x/, function(cb) {
  x_is_something(97, cb);
});

CLOSED (WONTFIX) : مطرقة:

لست متأكدًا من أنني أفهم كيف سيكون step() أفضل من استدعاء دالة JS بسيط هنا. أليس هذا ما سينتهي به الأمر على أي حال ، مع طبقة إضافية من المراوغة (أي تعريف خطوة لتقديم طلب GET إلى مستخدم معين لا يزال بحاجة إلى ترجمته إلى وظيفة JS)؟

لقد لاحظت أنك كتبت - بما أنه ليس لدي طريقة لبدء سيناريو - ، هل تقصد خطوة أم أن هذا السيناريو عن قصد (في الحالة الأخيرة ، يمكنني رؤية ما تحاول القيام به ، على ما أعتقد).

لا يزال بإمكانك تحديد المستخدمين في الخلفية والتكرار عليهم في خطوتك When .

Feature:
  Background:
    Given a valid user called Simon
    And a valid user called Sarah
    And a valid user called Johnny

  Scenario Outline:
    When each valid user sends a GET request to /search<query>
    Then everyone's request response code is 400
    And everyone's request response body starts with <body>

  Examples:
    | query  | body |
    | ?foo=1 | ...  |

ونعم ، هذا يعني تخزين استجابات الطلبات في مصفوفة وتكرارها. غير أن سيئة؟

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

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

شكرا.

من المحزن جدًا أن هذا لن يتم إصلاحه ، كما يقول cono : استدعاء خطوة واحدة يكاد يكون مستخدمًا ، والحالات الحقيقية عمليات أكثر تعقيدًا.

سيكون هذا مفيدًا حقًا لإنشاء عدد قليل من السيناريوهات الدقيقة ثم سيناريوهات أخرى لتكرار هذه العمليات. خاصة عندما يتم تحديد الخطوات في أكثر من ملف واحد ، في هذه الحالة ، لا يكون بديل إعادة استخدام الوظيفة سهلًا ولا نظيفًا.

هاي! لقد قمت بإنشاء lib يقوم بما تطلبه بالضبط (اتصل بخطوة من خطوة أخرى) ، ألق نظرة هنا: https://github.com/hackhat/cucumberry
نرحب بالتعليقات!

hackhat يبدو رائعًا حقًا. أنا عادة أحب جزء مزامنة من تعريف الخطوة. هل cucumber-pro فقط مكون إضافي لـ cucumber.js؟

@ jlin412 لا أعرف حقًا كيف أتصل ، لكني أشبه بمساعد الخيار. شكرا لملاحظاتك

hackhat لإنشاء خطوة مزامنة ، سأحتاج إلى استخدام بناء الجملة: this.addStep (...)؟ هل سأحتاج إلى استخدام selenium-sync أيضًا بدلاً من protractor.js / webdriver.js؟

@ jlin412 ، يمكنك فقط استخدام المكون الإضافي للمزامنة ، انظر إلى المستندات حول كيفية القيام بذلك. أنا على الهاتف المحمول لذا لا يمكنني إخبارك بالخطوات الدقيقة. إذا استطعت الانتظار سأشرح بشكل أفضل حوالي الساعة 23:30 بتوقيت البرتغال.

hackhat يرجى تغيير اسم مشروعك إلى شيء آخر. انظر hackhat / cucumber-pro # 1

aslakhellesoy غير الاسم إلى https://github.com/hackhat/cucumberry

aslakhellesoy ثم كيف تسلسل المكالمات الخطوة؟ مثل المتابعة؟

function x_is_something(x, cb) {
  console.log('x', x);
  this.x = x;
  cb();
}
function y_is_something(y, cb) {
  console.log('y', y);
  this.y = y;
  cb();
}

Given(/super z/, function(cb) {
  x_is_something(97, cb);
  y_is_something(8, cb);
});

هذا لا يعمل بشكل جيد حيث أن x_is_something كان سيطلب رد الاتصال قبل أن تتاح الفرصة لـ y_is_something لإنهاء عمله.

وأيضًا ، إذا كانت مخازن الخطوة متغيرة في سياق العالم ، فسينتهي بها الأمر في كل مرة تستدعي فيها الوظيفة ، فنحن بحاجة إلى ربطها مثل:

Given(/super z/, function(cb) {
  x_is_something.bind(this)(97, cb);
  y_is_something.bind(this)(8, cb);
});

أي شخص لديه حلول لهذه القضايا؟

تحتاج إلى استخدام غير متزامن واستخدام الوظيفة المتوازية. بهذه الطريقة تتصل
cb الرئيسي فقط بعد انتهاء كلتا الاستدعاءات الفرعية.
حول الربط يمكنك إما استخدام هذا مع الربط أو استخدام متغير إغلاق.

في الخميس ، 14 مايو 2015 ، 00:15 كتب Yun Jia [email protected] :

aslakhellesoy https://github.com/aslakhellesoy ثم كيفية ربط ملف
مكالمات خطوة؟ مثل المتابعة؟

الوظيفة x_is_something (x، cb) {
console.log ('x'، x) ؛
this.x = x ؛
cb () ؛
} function y_is_something (y، cb) {
console.log ('y'، y) ؛
this.y = y ؛
cb () ؛
}

معطى (/ super z / ، الوظيفة (cb) {
x_is_something (97 ، cb) ؛
y_is_something (8 ، cb) ؛
}) ؛

هذا لا يعمل بشكل جيد لأن شيء ما قد يسمى x_is_som
رد الاتصال قبل أن تتاح الفرصة لـ y_is_something لإنهاء عملها.

وأيضًا ، إذا كانت مخازن الخطوة متغيرة في سياق العالم ، فسوف ينتهي بها الأمر
في كل مرة نستدعي الوظيفة ، نحتاج إلى ربطها مثل:

معطى (/ super z / ، الوظيفة (cb) {
x_is_something.bind (هذا) (97 ، cb) ؛
y_is_something.bind (هذا) (8 ، cb) ؛
}) ؛

أي شخص لديه حلول لهذه القضايا؟

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub
https://github.com/cucumber/cucumber-js/issues/11#issuecomment -101845619
.

+1 ، يجب أن يكون هذا جزءًا من lib.

ما الذي اقترحه mattwynne (أضف ميزة gherkin التي تدعم قابلية إعادة استخدام الكود):

    When a
    Then x
    When b
    Then y

---------------------------------

    Define x
        Then p
        And y
        And q

---------------------------------

    Step a
        ...
    Step b
        ...
    Step p
        ...
    Step q
        ...
    Step y
        ...

---------------------------------

ماذا اقترح aslakhellesoy (استخراج الكود المكرر لوظائف js):

    When a
    Then x
    When b
    Then y

---------------------------------

    Step a
        ...
    Step b
        ...
    Step x
        ...
        Call f(p)
        ...
    Step y
        Call f(p)

---------------------------------

    Function f(p)
        ...

---------------------------------

استدعاء الخطوات من تعريفات الخطوة

    When a
    Then x
    When b
    Then y

---------------------------------

    Step a
        ...
    Step b
        ...
    Step x
        ...
        Call y(p)
        ...
    Step y
        ...

---------------------------------

ما زلت لا أفهم لماذا نحتاج إلى مستوى تجريد آخر غير ضروري ، هل لديك أي تفسير؟

yunjia هذه هي نظرية رد الاتصال الأساسية:

Given(/super z/, function(cb) {
  x_is_something(97, function () {
    y_is_something(8, cb);
  });
});

بالنسبة لمسألة الربط ، يجب عليك تحديد هذه الوظائف كوسائل على عالمك :

function World(callback) {
    this.x_is_something = function (x, callback) {
      this.x = ...
    };

    this.y_is_something = function (y, callback) {
      this.y = ...
    };

    callback(); // tell Cucumber we're finished and to use 'this' as the world instance
  };
}
module.exports.World = World;

ثم في خطوتك التعريفات:

Given(/super z/, function(cb) {
  var self = this;
  self.x_is_something(97, function () {
    self.y_is_something(8, cb);
  });
});

أيضًا ، يرجى ملاحظة أن تعريفات الخطوة المتزامنة مدعومة بواسطة Cucumber.js 0.5+:

Given(/super z/, function() {
  this.x_is_something(97);
  this.y_is_something(8);
});

تعد تعريفات الخطوة @ inf3rno طبقة ترجمة رفيعة بين كود اللغة الإنجليزية البسيطة ورمز JS. من خلال السماح بخطوات الاستدعاء من الخطوات ، نجعل تلك الطبقة أكثر بدانة. تصبح الخطوات مقترنة ببعضها البعض ، مما يجعل صيانتها صعبة للغاية.

كما أنه يشجع الناس على استخدام Gherkin كلغة برمجة نصية ، وهي ليست كذلك على الإطلاق.

@ inf3rno إذا كنت تريد إعادة استخدام التعليمات البرمجية في stepdefs ، فقم بنقل جسم stepdef إلى دالة جافا سكريبت عادية وأعد استخدامها.

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

كما أنه يشجع الناس على استخدام Gherkin كلغة برمجة نصية ، وهي ليست كذلك على الإطلاق.

يمكنك وضع الثابتة والمتنقلة. أنا لا أفهم ما هو الرابط ، لأن تعريفات الخطوة ليست في صيغة gherkin ، فقط نمط النص هو ما هو مشابه.

@ inf3rno إذا كان بإمكانك استدعاء الخطوات من الخطوات ، فأنت تقفز مرة أخرى مرة أخرى إلى "Gherkinland": يجب تحليل أسماء الخطوات ومطابقتها مع تعريفات الخطوة التي يمكن تنفيذها. أنت تكتب بشكل أساسي نصوص غيركينية داخل gherkin (إنها مخفية في تعريفات خطوة JS ، لكن هذه التفاصيل تجعل الأمر أسوأ من POV للصيانة).

aslakhellesoyjbpros الفكرة هي أن الخطوات يجب أن تكون من النوع الجبري القابل للإنشاء ، وهو ليس كذلك.

jbpros ، سأستخدم الحل الخاص بك لأنني معتاد على البرمجة في Java ولا أقلق بشأن الوعود :)

هل توصل أحد من قبل إلى امتداد للخيار لتحديد الخطوات من حيث الخطوات الأخرى؟ شيء مثل

Understand I log in to {site} as {user}, {pass}
    I visit {site}
    I log in as {user}, {pass}

أتساءل ما إذا كان هذا امتدادًا مفيدًا لوصف رحلات المستخدم الطويلة عبر النظام بشكل أفضل وأفضل العمل مع أي حالة فنية سابقة.

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

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