Cucumber-js: كيف يمكنني تحديد ملف تعريف الخطوة لكل ملف ميزة؟

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

هدفي

أحاول إنشاء بنية قابلة للتطوير من الميزات وتعريفات الخطوة لتطبيق كبير وكانت لقطتي الأولى تحاول ربط ملفات تعريف الخطوة بالميزات حتى أتمكن من استخدام نمط الخطوة نفسه لتعريفات الخطوات المختلفة.

رمز بلدي

أعرض المثال الحالي الخاص بي:

هيكل مجلدي:

/features/sample.feature
/features/example.feature
/features/step_definitions/sample_steps.js
/features/step_definitions/example_steps.js
/features/step_definitions/common/common_steps.js

في sample.feature لدي:

  Scenario: Launching Cucumber
  Given I have some step definitions
   When I check some step definition with parameter "any"
   Then I should see all green "sample"

في example.feature لدي:

  Scenario: Launching Cucumber
  Given I have some step definitions
   When I check some step definition with parameter "any"
   Then I should see all green "example"

يتم تحديد الخطوات Given و When في ملف /common/common_steps.js وتعمل بشكل جيد.

يتم تحديد الخطوة Then لكل من sample_steps.js و example_steps.js لكن بشكل مختلف.

في sample_steps.js لدي:

Then('I should see all green {stringInDoubleQuotes}', (arg) => {
   if (arg !== 'sample') {
     throw 'I should see all green when the argument is "sample"';
   }
   return;
 });

وأخيرًا ، في example_steps.js لدي:

Then('I should see all green {stringInDoubleQuotes}', (arg) => {
   if (arg !== 'example') {
     throw 'I should see all green when the argument is "example"';
   }
   return;
 });

الخطأ

هدفي الرئيسي هو الحصول على اللون الأخضر هنا ، لكن بالطبع ، لا يعمل ، وأحصل على هذا الخطأ الواضح:

Multiple step definitions match:
   I should see all green {stringInDoubleQuotes} - features\step_definitions\example_steps.js:6
   I should see all green {stringInDoubleQuotes} - features\step_definitions\sample_steps.js:6

الخيار- JVM

أعلم أنه في cucumber-jvm يمكننا تحديد سمة glue التي تربط الميزات والتعريفات الخطوة وهذا بالضبط ما أبحث عنه ، ولكن في cucumber-js. مثال في Java:

@RunWith(Cucumber.class)
@Cucumber.Options( glue = { "com.app.stepdefinitions.common", "com.app.stepdefinitions.sample" } )
public class SampleFeature{
}

@RunWith(Cucumber.class)
@Cucumber.Options( glue = { "com.app.stepdefinitions.common", "com.app.stepdefinitions.example" } )
public class ExampleFeature{
}

أخيرا

كيف يمكنني تحقيق نفس الشيء مثل cucumbr-jvm باستخدام cucumber-js؟

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

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

في شركتي ، يحتوي منتجنا على المئات من الميزات و QA لديها حالات اختبار في نطاق 100 ألف.
إذا استخدمنا cucumber فسنواجه بالتأكيد هذه المشكلة.

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

يجب أن يكتب كل من BA و QA هذه الاختبارات وأي DSL مخصص مرتبط بإحداث الارتباك والمقاومة.

توفر الميزة / السيناريو بالفعل سياقات حسب التعريف ، ولهذا السبب تحتوي صيغة غيركين على المسافة البادئة.

تعد إضافة العلامات و DSL المخصص بمثابة حل بديل لقيود التنفيذ (أي اختراق ، IMO) بدلاً من حل.

ربما يمكنك التفكير في ذلك أثناء التفكير في https://github.com/cucumber/cucumber-js/issues/745 ؟

ماذا عن تمديد Scenario من defineStep وتمرير {Given, When, Then} في رد الاتصال؟

بمعنى آخر:

import {defineSupportCode} from 'cucumber'

defineSupportCode(({ Scenario, Given, When, Then }) => {
  Given(...)
  When(...)
  Then(...)
  Scenario('<match scenario description>', ({ Given, When, Then}) => {
    Given('<take precedent of non-contexted>', ...)
    ...
  })
})

ال 18 كومينتر

أحاول إنشاء بنية قابلة للتطوير من الميزات وتعريفات الخطوة لتطبيق كبير وكانت لقطتي الأولى تحاول ربط ملفات تعريف الخطوة بالميزات حتى أتمكن من استخدام نمط الخطوة نفسه لتعريفات الخطوات المختلفة.

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

نحن في الواقع لدينا نفس الحاجة لهذا. نحن نستخدم Nightwatch-cucumber لإجراء اختبارات السيلينيوم والحل الوحيد في الوقت الحالي هو إضافة بادئة لكل خطوة:

Given [comp1] I click on "Open dialog"

ضد

Given [comp2] I click on "Open dialog"

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

هل يمكن تحقيق ذلك ببعض الخطافات أو عوالم بديلة؟

leipert ما هي واجهة المستخدم التي تتخيلها؟ أعتقد أن هذا المنطق يجب أن يعيش في العالم أو يدعم كائنات عالمية متعددة. ثم تتعامل تعريفات الخطوة فقط مع تحليل أعواد الخيش وتمريرها إلى وظيفة العالم المناسبة. يمكننا إضافة خيار CLI لاختيار أي كائن عالمي لاستخدامه.

في الوقت الحالي ، إذا كنت ترغب في الحصول على عوالم / تعريفات متعددة للخطوات ، يمكنك تحقيق ذلك عن طريق وضع الكود الخاص بك في مجلدات منفصلة وطلب واحد فقط منهم في كل مرة (باستخدام الخيار --require CLI).

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

حتى الآن ، تعد العلامات فقط قريبة من هدفك في cucuber.js. لكن الخطافات فقط هي التي يمكنها التصريح بأنها خاصة بالعلامات. إذا كنت متأكدًا من أنها الطريقة الصحيحة لموظفيك ، فيمكنك اختراع DSL ، ربما يكون بسيطًا مثل [اسم الميزة] في نمط الخطوة.

شكرا pinxue . استجابة مفيدة جدا. ومع ذلك ، لا يمكنني فهم ذلك:

حسنًا ، "كتاب الخيار" على وجه التحديد لا تشجع هذه الطريقة في تصميم الخطوات.

يمكن أن يكون لعبارة العمل نفسها معاني مختلفة في سياقات مختلفة. ولكن كل شيء على مايرام. من الجيد معرفة الخيارات المتوفرة لدي ، في الواقع ، نحن نسير بالفعل على DSL داخلي لتحقيق ذلك ،

شكرا جزيلا.

شكرا لإجاباتك pinxue و @ robsonrosa.
هذا هو المنطق الخاص بي لتعريفات الخطوة المحددة النطاق:

  1. _المتغيرات العالمية سيئة ولا يمكن قياسها _:
    لدينا حوالي 15 ملفًا مميزًا مع 10 سيناريوهات لكل منها ، ومن الصعب بالفعل هيكلة جميع تعريفات الخطوات وملفات الميزات. بالنسبة للتطبيقات الكبيرة (على سبيل المثال ، 100 ملف مميز مع 10 سيناريوهات بمتوسط ​​5 خطوات) ، فإن تحديد جميع الخطوات على مستوى العالم يبدو مجنونًا ، لأنه من الصعب حقًا تتبع أي ملف مميز يستخدم الخطوات.
  2. _لا يتحكم المطورون في الصياغة في ملفات الميزات _:
    في حالة الاستخدام لدينا ، تكتب "إدارتنا" ملفات مميزة ، من الصعب بيعها: نحن نقوم بعمل BDD رائع ، ولكن عليك أن تقتصر على DSL مخصص غير ملائم.
  3. _If cucumber-jvm لديه الخيار ، فلماذا لا cucumber-js؟ _
    قد تكون هذه حجة سيئة 💃

أرى الأساليب التالية لحل المشكلة بالنسبة لنا:

  1. قم بإنشاء DSL مخصص مع البادئات في تعريفات الخطوة
    السلبيات: ليس من الجيد العمل معها.
    الايجابيات: لا يحتاج الى تغييرات في cucumber.js
  2. أنشئ glue لـ cucumber.js
    السلبيات: قد يتعارض مع فكرة "كتاب الخيار".
    الإيجابيات: ميزة التكافؤ مع cucumber.js
  3. غيّر طريقة إجرائنا للاختبارات
    السلبيات: ستتوفر هذه الميزة لعدد أقل من الأشخاص.
    الايجابيات: لا يحتاج الى تغييرات في cucumber.js

ومع ذلك ، فربما نختار 3. ، إذا اعتقد مشرفو cucumber.js أن تعريفات الخطوة المحددة خارج النطاق (يقصد التورية) لهذا المشروع.

robsonrosa ، سأكون مهتمًا بالحل الخاص بك ، بمجرد أن يكون لديك حل.

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

في شركتي ، يحتوي منتجنا على المئات من الميزات و QA لديها حالات اختبار في نطاق 100 ألف.
إذا استخدمنا cucumber فسنواجه بالتأكيد هذه المشكلة.

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

يجب أن يكتب كل من BA و QA هذه الاختبارات وأي DSL مخصص مرتبط بإحداث الارتباك والمقاومة.

توفر الميزة / السيناريو بالفعل سياقات حسب التعريف ، ولهذا السبب تحتوي صيغة غيركين على المسافة البادئة.

تعد إضافة العلامات و DSL المخصص بمثابة حل بديل لقيود التنفيذ (أي اختراق ، IMO) بدلاً من حل.

ربما يمكنك التفكير في ذلك أثناء التفكير في https://github.com/cucumber/cucumber-js/issues/745 ؟

ماذا عن تمديد Scenario من defineStep وتمرير {Given, When, Then} في رد الاتصال؟

بمعنى آخر:

import {defineSupportCode} from 'cucumber'

defineSupportCode(({ Scenario, Given, When, Then }) => {
  Given(...)
  When(...)
  Then(...)
  Scenario('<match scenario description>', ({ Given, When, Then}) => {
    Given('<take precedent of non-contexted>', ...)
    ...
  })
})

تعلمت BDD من http://fitnesse.org/ لذلك قد أنظر إلى BDD بشكل مختلف عن مجتمع الخيار.

الاستدعاءrichardlawrence

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

في الحالات النادرة التي يحتوي فيها التطبيق على عدة سياقات محددة محددة (بمصطلحات DDD) ، يمكنك ببساطة تقسيم مجموعة Cucumber الخاصة بك على نفس الأسطر التي يتم تقسيم التطبيق الخاص بك ليعكس تلك الحدود ، وستكون محددات الخطوة عامة داخل كل سياق محدد.

مقال حول العمل مع الخيار وخلق الحدود. يقوم بتنفيذ بعض الأفكار الواردة في هذه الصفحة ولكنه لا يقدم أي حلول رائعة كما ذكر richardlawrence أنه لا يمكنك تكوين الخيار للتركيز على فئة معينة لتعريفات الخطوة. http://confessionsofanagilecoach.blogspot.com/2017/05/teaching-cucumbers-about-boundaries.html

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

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

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

أنا أفهم هدفك ، لكنني لا أوصي به.
أوصي أيضًا بوجود ملفات ميزات صريحة ، مع بيان الخلفية أو خطوة معطاة إضافية تجعل هذا واضحًا.

بدلاً من ذلك ، يمكنك إنشاء ملفي تكوين مختلفين.
واحد للعينة وآخر على سبيل المثال.
ثم يمكنك الإشارة إلى مجلدات خطوات مختلفة.

robsonrosaleipert أشارككم رأيك
ما يقرب من عامين بعد المنشور الأصلي ...
هل حصلت على أي تقدم مع ذلك؟ أي حل؟

@ cristianmercado19 آسف ، لا. أنا لا أستخدم شبيبة الخيار بعد الآن.

Ups ... أحب طريقة كتابة ملف ميزة معزول تمامًا عن تنفيذ الخطوة.
حاولت أن أحقق نفس الهدف مع _mocha لكني لست سعيدًا.
إذا كان لديك أي بديل آخر يلبي هدفي ، فسأكون سعيدًا للغاية لتجربته.
نقدر مساعدتك leipert .

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

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