أحاول إنشاء بنية قابلة للتطوير من الميزات وتعريفات الخطوة لتطبيق كبير وكانت لقطتي الأولى تحاول ربط ملفات تعريف الخطوة بالميزات حتى أتمكن من استخدام نمط الخطوة نفسه لتعريفات الخطوات المختلفة.
أعرض المثال الحالي الخاص بي:
هيكل مجلدي:
/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
أعلم أنه في 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؟
أحاول إنشاء بنية قابلة للتطوير من الميزات وتعريفات الخطوة لتطبيق كبير وكانت لقطتي الأولى تحاول ربط ملفات تعريف الخطوة بالميزات حتى أتمكن من استخدام نمط الخطوة نفسه لتعريفات الخطوات المختلفة.
مثير جدا. لا يحتوي 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.
هذا هو المنطق الخاص بي لتعريفات الخطوة المحددة النطاق:
أرى الأساليب التالية لحل المشكلة بالنسبة لنا:
glue
لـ cucumber.jscucumber.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 .
تم قفل سلسلة الرسائل هذه تلقائيًا نظرًا لعدم وجود أي نشاط حديث بعد إغلاقه. الرجاء فتح قضية جديدة للأخطاء ذات الصلة.
التعليق الأكثر فائدة
هناك حاجة بالتأكيد إلى تحديد نطاق المنظمة البحرية الدولية. مع نمو التطبيق الخاص بك ، يتسع عدد الميزات وسوف ينتهي بك الأمر مع أوصاف متضاربة في سياقات مختلفة.
في شركتي ، يحتوي منتجنا على المئات من الميزات و QA لديها حالات اختبار في نطاق 100 ألف.
إذا استخدمنا
cucumber
فسنواجه بالتأكيد هذه المشكلة.نعم ، أعتقد أنه يجب عليك التفكير في السياق بدلاً من تحديد النطاق.
يمكنك الحصول على معظم ، إن لم يكن كل ، تعريفات خطوتك في السياق الافتراضي (أو بدون سياق) ، ولكن يجب أن تكون هناك طريقة لتحديد السياق دون الحاجة إلى DSL مخصص.
يجب أن يكتب كل من BA و QA هذه الاختبارات وأي DSL مخصص مرتبط بإحداث الارتباك والمقاومة.
توفر الميزة / السيناريو بالفعل سياقات حسب التعريف ، ولهذا السبب تحتوي صيغة غيركين على المسافة البادئة.
تعد إضافة العلامات و DSL المخصص بمثابة حل بديل لقيود التنفيذ (أي اختراق ، IMO) بدلاً من حل.
ربما يمكنك التفكير في ذلك أثناء التفكير في https://github.com/cucumber/cucumber-js/issues/745 ؟
ماذا عن تمديد
Scenario
منdefineStep
وتمرير{Given, When, Then}
في رد الاتصال؟بمعنى آخر: