اختبار فن التخطيط مع إطار جالين
نشرت: 2022-03-10عند تصميم واجهة مستخدم رسومية ، هناك دائمًا سؤال مفتوح: كيف يمكننا أتمتة اختبارها؟ وكيف نتأكد من أن تصميم موقع الويب يظل مستجيبًا ويعرض بشكل صحيح على جميع أنواع الأجهزة ذات الدقة المختلفة؟ أضف إلى ذلك التعقيدات الناشئة عن المحتوى الديناميكي ، ومتطلبات التدويل والتعريب ، ويصبح تحديًا حقيقيًا.
في هذه المقالة ، سأوجهك عبر تقنية اختبار تخطيط جديدة مثيرة للاهتمام. باستخدام Galen Framework ، سأقدم برنامجًا تعليميًا مفصلاً لكتابة اختبارات تخطيط عامة ذات مغزى ، والتي يمكن تنفيذها في أي متصفح وعلى أي جهاز وفي نفس الوقت تستخدم كمصدر واحد للحقيقة في وثائق التصميم الخاصة بك.
مزيد من القراءة على SmashingMag:
- التطوير المرئي الذي يحركه الاختبار لتصميم واجهة مستجيبة
- أساسيات اختبار التشغيل الآلي للتطبيقات والألعاب والويب المحمول
- أطر عمل أتمتة الاختبار المتنوعة للتطبيقات الأصلية للتفاعل
سأوضح أيضًا كيف توصلت إلى اختبار محسن لصفحة مراسلة على موقع الإعلانات المبوبة لدينا Marktplaats. سوف نتعلم كيفية توسيع بناء جملة Galen مع لغتنا الخاصة ، وكيفية تحسين كود الاختبار وكيفية تحويل روتين اختبار التخطيط إلى فن.
مقدمة في إطار جالين
تمت تغطية إطار عمل جالين قبل عام في "التطوير المستند إلى الاختبار البصري لتصميم واجهة مستجيبة". في ذلك الوقت ، كان تركيبها محدودًا. لقد تحسنت كثيرًا منذ ذلك الحين وحصلت على العديد من الميزات الجديدة ، والتي سنلقي نظرة عليها هنا.
إذا لم تكن معتادًا على Galen Framework ، فهو أداة لاختبار تخطيط متجاوب ومتعدد المستعرضات واختبار وظيفي ، مع لغة الاختبار الخاصة به ، المسماة Galen Specs. يعتمد على Selenium WebDriver ويحتوي أيضًا على واجهة برمجة تطبيقات JavaScript غنية تتيح لك العمل مع WebDriver مباشرة. نظرًا لأنك تتحكم في WebDriver ، يمكنك إجراء الاختبارات في أي متصفح ، في السحابة (SauceLabs ، BrowserStack ، PerfectoMobile ، إلخ) أو على أجهزة محمولة حقيقية باستخدام Appium.
التثبيت والتنفيذ
يعد إعداد Galen Framework أمرًا سهلاً. ما عليك سوى تنفيذ الأمر التالي لتثبيته عبر npm:
npm install -g galenframework-cli
إذا كنت لا تستخدم npm ، فما عليك سوى تنزيل أحدث أرشيف لـ Galen Framework ، واستخراج الحزمة واتباع إرشادات التثبيت.
بمجرد التثبيت ، يمكن تشغيل Galen Framework بعدة طرق. على سبيل المثال ، يمكنك استخدام الأمر check
لبدء اختبار سريع لصفحة واحدة. بالنسبة لهذا الأمر ، تحتاج إلى توفير ملف .gspec
مع عمليات التحقق من صحة التخطيط ، ومن ثم يمكنك استدعاؤه على النحو التالي:
galen check loginPage.gspec --url https://example.com --size 1024x768 --include desktop --htmlreport reports
سيؤدي هذا الأمر إلى تشغيل المتصفح ، وفتح عنوان URL المحدد ، وتغيير حجم نافذة المتصفح إلى 1024 × 768 بكسل وتنفيذ جميع عمليات التحقق من الصحة المعلنة في ملف loginPage.gspec
. نتيجة لذلك ، سوف تحصل على تقرير HTML مفصل.
إدارة مجموعات الاختبار
في العالم الحقيقي ، لا يتكون تطبيق الويب الفعلي من صفحات ثابتة فقط. في كثير من الأحيان سيكون عليك القيام ببعض الإجراءات للوصول إلى المكان الذي تريد التحقق منه. في هذه الحالة ، يقدم Galen مجموعات اختبار JavaScript وواجهة برمجة تطبيقات GalenPages JavaScript لتنفيذ نموذج كائن الصفحة. فيما يلي مثال بسيط لاختبار JavaScript Galen:
test("Home page", function() { var driver = createDriver("https://galenframework.com", "1024x768"); checkLayout(driver, "homePage.gspec", ["desktop"]); });
وهنا تنفيذ لنموذج كائن الصفحة لصفحة تسجيل الدخول ، مأخوذ من مشروع حقيقي.
WelcomePage = $page("Welcome page", { loginButton: "#welcome-page .button-login" }); LoginPage = $page("Login page", { username: "input[name='login.username']", password: "input[name='login.password']", loginButton: "button.button-login" loginAs: loggedFunction ("Log in as ${_1.username} with password ${_1.password}", function(user) { this.username.typeText(user.username); this.password.typeText(user.password); this.loginButton.click(); }) }); test("Login page", function() { var driver = createDriver("https://testapp.galenframework.com", "1024x768"); var welcomePage = new WelcomePage(driver).waitForIt(); welcomePage.loginButton.click(); new LoginPage(driver).waitForIt(); checkLayout(driver, "loginPage.gspec", ["desktop"]); });
للاستخدام المتقدم ، أنصحك بإلقاء نظرة على مشروع Galen Bootstrap. إنه امتداد JavaScript مصمم خصيصًا لـ Galen. يوفر بعض الوظائف الإضافية لاختبار واجهة المستخدم وطريقة أسهل لتكوين المتصفحات وتنفيذ مجموعات اختبار معقدة.
اختبار تخطيط بسيط
اسمحوا لي أن أبدأ بتقديم اختبار تخطيط بسيط في Galen Framework. بعد ذلك ، سأنتقل إلى حالات الاستخدام المتقدمة وأشرح كيفية توسيع بنية Galen Specs. لهذا ، سوف ننظر إلى رأس مع رمز وتعليق:

في كود HTML ، قد يبدو مشابهًا لما يلي:
<body> <!-- … --> <div> <img class="header-logo" src="/imgs/header-logo.png"/> <h1>My Blog</h1> </div> <!-- … --> </body>
إن أبسط شكل من أشكال اختبار تخطيط Galen سيبدو مشابهًا لما يلي. أولاً ، علينا أن نعلن عن الكائنات باستخدام محددات CSS.
@objects header #header icon #header img caption #header h1
@أشياء@objects header #header icon #header img caption #header h1
بعد ذلك ، نعلن عن قسم اختبار باسم ذي معنى ونضع جميع عمليات التحقق من الصحة تحته.
= Icon and Caption = icon: left-of caption 10 to 15px width 32px height 32px inside header 10px top caption: aligned horizontally all header inside header
لقد اختبرنا هنا عنصرين من عناصر الرأس: الرمز والتعليق. جميع عمليات التحقق المدرجة تحت الرمز وعناصر التسمية التوضيحية هي في الواقع مواصفات Galen القياسية. هذه المواصفات هي اللبنات الأساسية التي يمكنك من خلالها تجميع حل اختبار التخطيط الخاص بك. تتحقق كل مواصفات من خاصية واحدة (مثل العرض والارتفاع والنص) أو تحديد الموضع النسبي (مثل الداخل أو اليسار أو أعلى) أو وحدات البكسل في لقطة الشاشة (مثل نظام الألوان والصورة).
اختبار عناصر متعددة باستخدام كل حلقة
يوضح المثال السابق سيناريو بسيط. دعونا نرى كيف يمكننا التعامل مع موقف أكثر تعقيدًا: قائمة أفقية. أولاً ، لنجرب أسلوب اختبار تخطيط مباشر.

ابدأ بمطابقة عدة عناصر على الصفحة. باستخدام الكود التالي ، نطلب من Galen البحث عن العناصر التي تطابق #menu ul li
CSS selector.
@objects menu #menu item-* ul li
@أشياء@objects menu #menu item-* ul li
في وقت لاحق ، يمكننا الرجوع إلى هذه العناصر بأسماء مثل menu.item-1
و menu.item-2
عبر جميع عناصر القائمة باستخدام حلقة @forEach
.
= Menu = menu.item-1: inside menu 0px top left bottom @forEach [menu.item-*] as menuItem, next as nextItem ${menuItem}: left-of ${nextItem} 0px aligned horizontally all ${nextItem}
كما ترى ، على الرغم من أن الفحص الفعلي ليس بهذا التعقيد ، فقد أصبح الرمز بالفعل أقل سهولة. تخيل لو كان لدينا كود أكثر تشابهًا في اختباراتنا. في مرحلة ما ، ستصبح فوضى لا يمكن الحفاظ عليها. يجب أن تكون هناك طريقة لتحسينه.
إعادة التفكير في اختبار التخطيط
إذا فكرت في المثال السابق ، فيبدو أنه يمكننا التعبير عن التخطيط في جملة واحدة أو جملتين فقط. على سبيل المثال ، يمكننا أن نقول شيئًا مثل ، "يجب محاذاة جميع عناصر القائمة أفقيًا ، مع عدم وجود هامش بينهما. يجب وضع عنصر القائمة الأول على الجانب الأيسر من القائمة ، بدون هامش. نظرًا لأننا قمنا بصياغة جمل لشرح التصميم الذي نريده ، فلماذا لا يمكننا استخدامها فقط في الكود الخاص بنا؟ تخيل لو تمكنا من كتابة الكود مثل هذا:
= Menu = |first menu.item-* is in top left corner of menu |menu.item-* are aligned horizontally next to each other
في الواقع ، هذا رمز عمل حقيقي ، منسوخ من مشروعي. في هذين السطرين الأخيرين (بدءًا من الأنبوب ، |
) ، نستدعي الدالات المخصصة التي تجمع وسيطاتها عن طريق تحليل هاتين العبارتين. بالطبع ، لن يعمل المثال أعلاه كما هو. من أجل التحويل البرمجي ، نحتاج إلى تنفيذ المعالجات لهاتين العبارتين. سنعود إلى هذا التنفيذ لاحقًا.
النقطة الأساسية في المثال أعلاه هي أن اختبار التخطيط قد تحول من الاختبار المستند إلى الكائن إلى الاختبار المستند إلى التعبير . قد لا يكون واضحًا من مثل هذا المثال البسيط ، لكنه بالتأكيد ملحوظ على نطاق أوسع. إذن ، لماذا هذا مهم؟ الإجابة المختصرة هي أن هذا يغير طريقة تفكيرنا ويؤثر على طريقة تصميمنا لبرنامجنا وكتابة الاختبارات له.
باستخدام هذه التقنية ، لا نتعامل مع صفحتنا على أنها مجموعة كائنات لها علاقات محددة فيما بينها. نحن لا نختبر خصائص CSS للعناصر الفردية. ونتجنب كتابة تعليمات برمجية معقدة غير تافهة. بدلاً من ذلك ، نحاول التفكير في أنماط التخطيط الشائعة والبيانات ذات المغزى. بدلاً من اختبار عنصر القائمة 1 ، عنصر القائمة 2 وما إلى ذلك بشكل منفصل ، نطبق العبارات العامة التي:
- قابلة للتكرار على عناصر أخرى ؛
- لا تحتوي على قيم بكسل مشفرة ؛
- يتم تطبيقها على التجريدات وليس على الأشياء الملموسة ؛
- وأخيرًا وليس آخرًا ، يكون منطقيًا عندما نقرأها.
كيف تعمل
اسمحوا لي أن أشرح آلية تعبيرات التنسيق المخصصة باستخدام هذا المثال البسيط:

في هذا المثال ، من المفترض أن نتحقق من أن الزر يمتد إلى اللوحة ، بدون هامش على الجانب الأيسر أو الأيمن. بدون القواعد المخصصة ، يمكننا التعامل معها بطرق مختلفة ، لكنني أفضل الحل التالي:
button: inside some_panel 0px left right
يمنحنا الكود أعلاه المرونة في إعلان الهامش المخصص على الجانبين ، كما أنه يختبر ضمنيًا أن الزر موجود بالكامل داخل اللوحة. الجانب السلبي هو أنه ليس قابلاً للقراءة تمامًا ، ولهذا السبب سأضع هذا التحقق من الصحة خلف button stretches to some_panel
. لكي يعمل ذلك ، نحتاج إلى كتابة قاعدة مخصصة مثل هذه:
@rule %{elementName} stretches to %{parentName} ${elementName}: inside ${parentName} 0px left right
هذا هو. الآن يمكننا وضعها في اختبارنا في سطر واحد فقط:
| button stretches to some_panel
كما ترى ، تأخذ هذه القاعدة وسيطتين: elementName
و parentName
. هذا يسمح لنا بتطبيقه على عناصر أخرى أيضًا. فقط استبدل أسماء هذين الشيئين.
| login_panel stretches to main_container | header stretches to screen | footer stretches to screen # etc.
تنفيذ لغة الاختبار الخاصة بك
دعنا نعود إلى الأمثلة الأولية لتعبيرات التخطيط للقائمة الأفقية.
= Menu = | first menu.item-* is in top left corner of menu | menu.item-* are aligned horizontally next to each other
يمكننا تنفيذ القاعدة الأولى بالطريقة التالية:
@rule first %{itemPattern} is in %{cornerSides} corner of %{parentElement} @if ${count(itemPattern) > 0} ${first(itemPattern).name}: inside ${parentElement} 0px ${cornerSides}
عند استخدامها في مثالنا ، فإنها ستحلل الوسيطات على النحو التالي:
-
itemPattern
=menu.item-*
-
cornerSides
=top left
-
parentElement
=menu
لأننا انتهينا من التعبير الأول ، يمكننا الانتقال إلى التعبير التالي. في التعبير الثاني ، من المفترض أن نختبر المحاذاة الأفقية لجميع عناصر القائمة. أقترح ثلاث خطوات بسيطة:
- البحث عن كافة عناصر القائمة.
- كرر كل منهم حتى العنصر قبل الأخير.
- تأكد من أن العنصر
n
يقع على يسار العنصرn+1
وأن حافتيهما العلوية والسفلية محاذاة.
لجعلها تعمل ، نحتاج إلى استخدام حلقة @forEach
والمواصفات left-of
aligned
. لحسن الحظ ، يمكنك في Galen الرجوع إلى العنصر السابق أو التالي في حلقة. في حالة الإعلان عن مرجع للعنصر التالي ، فسوف يتكرر فقط حتى العنصر قبل الأخير ، وهو بالضبط ما نحتاجه.
@rule %{itemPattern} are aligned horizontally next to each other @forEach [${itemPattern}] as item, next as nextItem ${item}: left-of ${nextItem} 0px aligned horizontally all ${nextItem}
قد تسأل ، ماذا لو كان علينا تحديد هامش في اختبارنا (مثل ~ 20px
أو 10 to 20px
)؟ بعد ذلك ، أقترح إما تنفيذ قاعدة منفصلة أو توسيع القاعدة الحالية لدعم وسيطة %{margin}
.
@rule %{itemPattern} are aligned horizontally next to each other with %{margin} margin @forEach [${itemPattern}] as item, next as nextItem ${item}: left-of ${nextItem} ${margin} aligned horizontally all ${nextItem}
هذا هو! لقد أنشأنا تعبيرًا عامًا يساعدنا في التحقق من صحة القائمة الأفقية. ومع ذلك ، نظرًا لمرونته ، يمكننا أن نفعل أكثر من ذلك بكثير. يمكننا استخدامه لاختبار أي عناصر أخرى على الصفحة. يمكننا حتى استخدامه لاختبار محاذاة زرين:

| menu.item-* are aligned horizontally next to each other with 0px margin | submit_button, cancel_button are aligned horizontally next to each other with 20px margin
قد تلاحظ في هذين المثالين أننا أعلنا الحجة الأولى بطريقتين مختلفتين. في التعبير الأول ، تكون الوسيطة الأولى هي “menu.item-*”
، وفي التعبير الثاني يتم التصريح عنها على أنها “submit_button, cancel_button”
. هذا ممكن لأن الحلقة @forEach
تسمح لنا باستخدام قائمة كائنات مفصولة بفواصل مع عامل التشغيل النجمي. لكننا ما زلنا لم ننتهي من إعادة الهيكلة. يمكننا تحسين الكود بشكل أكبر وجعله أكثر قابلية للقراءة. إذا أنشأنا مجموعات لعناصر القائمة وأزرار نموذج تسجيل الدخول ، فيمكننا تحقيق شيء مثل هذا:

@groups menu_items menu_item-* login_form_buttons submit_button, cancel_button = Testing login page = | &menu_items are aligned horizontally next to each other with 0px margin | &login_form_buttons are aligned horizontally next to each other with 20px margin
في هذه الحالة ، يتعين علينا استخدام الرمز &
، والذي يرمز إلى إعلان المجموعة. هذا بالفعل اختبار جيد. أولاً ، إنه يعمل فقط ، ونحن قادرون على اختبار ما نحتاج إليه. أيضا ، الكود واضح ومقروء. إذا سألك شخص آخر عن الشكل الذي يجب أن تبدو عليه صفحة تسجيل الدخول وما هي متطلبات التصميم ، فيمكنك إخباره بالاطلاع على الاختبار.
كما ترى ، فإن تنفيذ التعبيرات المخصصة لأنماط التخطيط المعقدة ليس بالأمر المهم حقًا. قد يكون الأمر صعبًا في البداية ، لكنه لا يزال يشبه نشاطًا إبداعيًا.
هوامش ديناميكية
لنلقِ نظرة على نمط تخطيط نادر آخر قد تجده أحيانًا على مواقع الويب المختلفة. ماذا لو أردنا اختبار أن العناصر لها مسافة متساوية بين بعضها البعض؟ دعنا نحاول تطبيق قاعدة أخرى لذلك ، ولكن هذه المرة باستخدام تطبيق JavaScript. أقترح مثل هذا البيان: “box_item-* are aligned horizontally next to each other with equal distance”
. سيكون هذا صعبًا بعض الشيء لأننا لا نعرف الهامش بين العناصر ولا يمكننا فقط قيم البكسل الثابت. لذلك ، فإن أول شيء يتعين علينا القيام به هو استرداد الهامش الفعلي بين العنصر الأول والعنصر الأخير.

بمجرد حصولنا على هذا الهامش ، يمكننا التصريح عنه في حلقة @forEach
مشابهة لما فعلناه من قبل. أقترح تنفيذ هذه القاعدة باستخدام JavaScript API لأن المنطق المطلوب أكثر تعقيدًا قليلاً من جميع الأمثلة السابقة. لنقم بإنشاء ملف باسم my-rules.js
واكتب هذا الكود:
rule("%{objectPattern} are aligned horizontally next to each other with equal margin", function (objectName, parameters) { var allItems = findAll(parameters.objectPattern), distance = Math.round(Math.abs(allItems[1].left() - allItems[0].right())), expectedMargin = (distance - 1) + " to " + (distance + 1) + "px"; if (allItems.length > 0) { for (var i = 0; i < allItems.length - 1; i += 1) { var nextElementName = allItems[i + 1].name; this.addObjectSpecs(allItems[i].name, [ "aligned horizontally all " + nextElementName, "left-of " + nextElementName + " " + expectedMargin ]); } } });
في كود الاختبار الخاص بنا ، سوف نستخدمه على النحو التالي:
@script my-rules.js # … = Boxes = | box_item-* are aligned horizontally next to each other with equal distance
كما ترى ، في Galen Framework ، يمكننا الاختيار بين لغتين عند تنفيذ القواعد: Galen Specs و JavaScript. بالنسبة للتعبيرات البسيطة ، فإن Galen Specs أسهل في الاستخدام ، ولكن بالنسبة للتعبيرات المعقدة ، فأنا دائمًا أختار JavaScript. إذا كنت تريد معرفة المزيد حول قواعد JavaScript ، فارجع إلى الوثائق.
إضافات جالين
بعد أن لعبت بشكل كافٍ مع أنماط تخطيط مختلفة ، أدركت أنه يمكن تطبيق كل قواعد Galen هذه بسهولة في أي مشروع اختبار آخر. أعطاني ذلك فكرة لتجميع أكثر التعبيرات التخطيطية شيوعًا في مكتبتهم الخاصة. هذه هي الطريقة التي أتيت بها لإنشاء مشروع Galen Extras. فيما يلي بعض الأمثلة لما تستطيع هذه المكتبة القيام به:
| header.icon should be squared | amount of &menu_items should be > 3 | &menu_items are aligned horizontally next to each other | &list_items are aligned vertically above each other with equal distance | every &menu_item is inside menu 0px top and has width > 50px | first &menu_item is inside menu 0px top left | &menu_items are rendered in 2 column table | &menu_items are rendered in 2 column table, with 0 to 1px vertical and 10px horizontal margin | &login_form_elements sides are vertically inside content_container with 20px margin login_panel: | located on the left side of panel and takes 70 % of its width # etc …
تحتوي مكتبة Galen Extras على العديد من أنماط التخطيط التي قد تجدها عادةً على مواقع الويب ، وأواصل تحديثها بمجرد اكتشاف نمط مفيد. بمجرد إنشاء هذه المكتبة ، قررت تجربتها في مشروع اختبار حقيقي.
اختبار تطبيق المراسلة
أعمل حاليًا كمهندس برمجيات في Marktplaats. في مرحلة ما ، قررت تطبيق كل الخبرة التي اكتسبتها في مشروع حقيقي. كنت بحاجة لاختبار صفحة الرسائل على موقعنا. هذا هو الشكل الذي تبدو عليه:

لأكون صادقًا ، كان إجراء اختبارات لمثل هذه الصفحات دائمًا مخيفًا بعض الشيء بالنسبة لي ، خاصة اختبارات التخطيط. ولكن مع وجود مكتبة Galen Extras في مكانها الصحيح ، سارت الأمور بسلاسة تامة ، وسرعان ما تمكنت من التوصل إلى هذا الرمز:
@import ../selected-conversation.gspec @groups (message, messages) messenger.message-* first_two_messages messenger.message-1,messenger.message-2 first_message messenger.message-1 second_message messenger.message-2 third_message messenger.message-3 (message_date_label, message_date_labels) messenger.date_label-* first_date_label messenger.date_label-1 second_date_label messenger.date_label-2 = Messages panel = = Messages and Date labels = |amount of visible &message_date_labels should be 1 |first &message_date_label has text is "17 november 2015" |amount of visible &messages should be 3 |&first_two_messages should be located at the left inside messenger with ~ 20px margin |&third_message should be located at the right inside messenger with ~ 20px margin |&messages are placed above each other with 10 to 15px margin |text of all &messages should be ["Hi there!", "I want to buy something", "Hello! Sure, it's gonna be 100 euros"] = Styling = |&first_two_messages should be styled as others message |&third_message should be styled as own message
استخراج نطاقات البكسل
بدا الاختبار جيدًا: لقد كان مضغوطًا ومقروءًا ولكنه لا يزال بعيدًا عن الكمال. لم تعجبني حقًا كل تعريفات الهامش هذه ( ~ 20px
، 10 to 15px
). تم تكرار بعضها ، وكان من الصعب فهم ما يمثله كل منهم. لهذا السبب قررت إخفاء كل هامش خلف متغير ذي مغزى.
# ... @set messages_side_margin ~ 20px messages_vertical_margin 10 to 15px = Messages panel = = Messages and Date labels = |amount of visible &message_date_labels should be 1 |first &message_date_label has text is "17 november 2015" |amount of visible &messages should be 3 |&first_two_messages should be located at the left inside messenger with ${messages_side_margin} margin |&third_message should be located at the right inside messenger with ${messages_side_margin} margin |&messages are placed above each other with ${messages_vertical_margin} margin # ...
كما ترى ، لقد قمت بنقل الهوامش إلى messages_vertical_margin
و messages_side_margin
. لقد أعلنت أيضًا عن minimal
للهامش ، وهو يتراوح بين 0 و 1 بكسل.
# ... @set minimal 0 to 1px = Conversations Panel = | &conversations are aligned above each other with ${minimal} margin # ...
التحقق من الصحة المستند إلى الصور والتعبيرات المخصصة
بعد أن غطيت مواضع جميع العناصر الرئيسية على الصفحة ، قررت أيضًا اختبار التصميم. أردت التحقق من أن كل رسالة لها لون خلفية خاص بدور المستخدم. عندما يقوم المستخدمون بتسجيل الدخول ، ستظهر الرسائل بخلفية زرقاء فاتحة. الرسائل الخاصة بالمستخدمين الآخرين تكون ذات خلفية بيضاء. في حالة عدم إرسال رسالة ، سيكون للتنبيه بالخطأ خلفية وردية. هذه هي القاعدة التي ساعدتني في التحقق من صحة هذه الأنماط:
@set OWN_MESSAGE_COLOR #E1E8F5 OTHERS_MESSAGE_COLOR white ERROR_MESSAGE_COLOR #FFE6E6 @rule %{item} should be styled as %{style} message ${item}: @if ${style === "own"} color-scheme > 60% ${OWN_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR} @elseif ${style === "error"} color-scheme > 60% ${ERROR_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR} @else color-scheme > 60% ${OTHERS_MESSAGE_COLOR}, 0.2 to 20 % ${MAJOR_TEXT_MESSAGE_COLOR}
تتحقق مواصفات color-scheme
الألوان من التوزيع النسبي للألوان داخل عنصر ما. يقوم بقص لقطة شاشة للصفحة وتحليل توزيع الألوان. لذلك ، للتحقق من لون الخلفية لعنصر ما ، نتحقق فقط من أن توزيعه أكبر من 60٪ من إجمالي نطاق الألوان. في الاختبار ، يتم استدعاء هذه القاعدة على النحو التالي:
= Styling = |&first_two_messages should be styled as others message |&third_message should be styled as own message
تكوين مجموعات الاختبار
تطبيق المراسلة هو تطبيق ديناميكي يعمل مع RESTful Messaging API. لذلك ، لاختبار تخطيطاته في جميع الحالات المختلفة ، يتعين علينا إعداد بيانات الاختبار. قررت إنشاء محاكاة لواجهة برمجة تطبيقات المراسلة حتى أتمكن من تكوين جميع رسائل الاختبار الخاصة بي في مجموعة الاختبار. هذا جزء من مجموعة الاختبار الخاصة بي الذي يوضح كيف يتم تنظيم اختباراتنا.
// ... testOnAllDevices("Unselected 2 conversations", "/", function (driver, device) { mock.onGetMyConversationsReturn(sampleConversations); refresh(driver); new MessageAppPage(driver).waitForIt(); checkLayout(driver, "specs/tests/unselected-conversations.gspec", device.tags); }); testOnAllDevices("When clicking a conversation it should reveal messages", "/", function (driver, device) { mock.onGetMyConversationsReturn(sampleConversations); mock.onGetSingleConversationReturn(sampleMessages); refresh(driver); var page = new MessageAppPage(driver).waitForIt(); page.clickFirstConversation(); checkLayout({ driver: driver, spec: "specs/tests/three-simple-messages-test.gspec", tags: device.tags, vars: { expectedTextProvider: textProvider({ "messenger.message-1": "Hi there!\n11:02", "messenger.message-2": "I want to buy something\n12:02", "messenger.message-3": "Hello! Sure, it's gonna be 100 euros\n13:02" }) } }); }); // ...
اصطياد البق
إن تنفيذ هذه التعبيرات البسيطة يؤتي ثماره بسرعة كبيرة. دعنا نتعرف على نوع الأخطاء التي يمكننا اكتشافها من خلال مجموعة الاختبار الخاصة بنا.
قضية التصميم
فيما يلي مثال على حدوث خطأ ما في قاعدة رموز CSS الخاصة بنا ، ونتيجة لذلك ، يتم عرض جميع الرسائل بنفس الخلفية.

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

بالنسبة للكائن المميز ، فإنه يعرض color #e1e8f5 on “messenger.message-3” is 0% but it should be greater than 60%
. لكي نكون صادقين ، لا تبدو رسالة الخطأ هذه واضحة تمامًا ، ولكن نظرًا لأن هذا التحقق تم إنشاؤه من قاعدة مخصصة ، يمكننا دائمًا البحث عن اسمه الأصلي في فرع التقرير:

إذا قمت بالتمرير لأعلى ، فسترى أن العبارة الأصلية هي &third_message should be styled as own message
. هذه فائدة أخرى لاستخدام التعبيرات المخصصة: فهي تساعدك على فهم الفشل وتصف بشكل جيد كل عمليات التحقق من الصحة التي تم إنشاؤها.
قضية تحديد المواقع
فيما يلي مثال آخر عندما يحدث خطأ في التخطيط بسبب المحاذاة غير الصحيحة للعنصر. في لقطة الشاشة التالية ، يمكنك أن ترى أن الرسالة الأخيرة موضوعة على الجانب الأيسر من منفذ عرض الرسائل ، بدلاً من الجانب الأيمن.

دعنا ننظر مرة أخرى إلى لقطة الشاشة مع رسالة الخطأ:

تسلط لقطة الشاشة الضوء على حاوية الرسائل وعنصر الرسالة الأخير. إلى جانب ذلك ، تظهر رسالة الخطأ التالية: “messenger.message-3” is 285px right which is not in range of 22 to 28px
. قد لا يكون واضحًا لمطور الويب سبب توقع هامش من 22 إلى 28 بكسل على الجانب الأيمن. مرة أخرى ، يجب أن تبحث عن بيان تحقق في فرع التقرير:

البيان الأصلي لهذا الشيك هو &third_message should be located at the right inside messenger with ~ 25px margin
. وهذا يجعل الشعور أكثر بكثير. علاوة على ذلك ، سيفهم مهندسو الواجهة الأمامية تقرير الاختبار هذا ، حتى لو لم يكتبوا الاختبارات.
إرشادات اختبار التخطيط
مع وضع كل هذه التجارب المختلفة في الاعتبار ، قررت إضفاء الطابع الرسمي على كل التعلم في إرشادات عامة لاختبار التخطيط. فيما يلي قائمة تحقق سريعة من الخطوات التي يجب اتباعها لتسهيل روتين الاختبار.
- تحديد أنماط التخطيط في التصميم.
- قم بتعميم بيانات التحقق من الصحة. حاول تلخيص معظم عمليات التحقق في جمل منفردة.
- مكون! من الأفضل دائمًا نقل اختبارات العناصر المتكررة إلى مكونات مخصصة.
- استخدم أسماء ذات معنى للأقسام والقواعد والكائنات.
- تجنب البكسل. حاول استبدال قيم البكسل (سواء كانت قيمًا أو نطاقات دقيقة) بمتغيرات ذات معنى.
- اضبط رمز موقع الويب الخاص بك لتسهيل الاختبار. سيساعدك هذا في هيكلة كلاً من كود الإنتاج والاختبار والحفاظ عليهما.
معايير القبول للإنقاذ
غالبًا ما أتلقى أسئلة مثل ، "إذن ما مدى تفصيل اختبار التخطيط؟ وما الذي يجب أن نختبره على وجه التحديد؟ " من الصعب إعطاء إجابة عامة. المشكلة هي أنه عندما تكون تغطية الاختبار صغيرة ، فإنك تفوت الأخطاء. من ناحية أخرى ، إذا كانت لديك اختبارات مفصلة للغاية ، فقد تحصل على الكثير من الإيجابيات الخاطئة ، وفي المستقبل قد تضيع في صيانة الاختبار. لذا ، هناك مقايضة. لكنني اكتشفت دليلًا عامًا لنفسي. إذا قمت بتقسيم العمل إلى قصص مستخدم أصغر ، فسيصبح من الأسهل هيكلة تصميم الصفحة في شكل معايير القبول. في النهاية ، قد تضع معايير القبول هذه في كود الاختبار الخاص بك. على سبيل المثال ، يمكن تعريف بعض هذه العبارات في شكل قواعد مخصصة ، كما هو موضح في جميع أمثلة التعليمات البرمجية السابقة. من الأمثلة الجيدة على معايير القبول شيء من هذا القبيل:
- يجب توسيط النوافذ المنبثقة رأسياً وأفقياً على الشاشة.
- يجب أن تكون بعرض 400 بكسل.
- يجب محاذاة الأزرار أفقيًا.
- وما إلى ذلك وهلم جرا
بمجرد وصف التصميم في جمل بسيطة ، يصبح من الأسهل تحويلها إلى عبارات قابلة لإعادة الاستخدام وتنظيم كود الاختبار الخاص بك.
خاتمة
كما ترى ، يساعدك هذا التمرين في هيكلة التصميم واكتشاف أنماط التخطيط العامة التي يمكن مشاركتها عبر مكونات متعددة للصفحة. حتى إذا كانت الصفحة معقدة وتتكون من الكثير من العناصر ، يمكنك دائمًا العثور على طريقة لتجميعها في تعبيرات التخطيط. باستخدام هذا النهج ، يصبح اختبار التخطيط أكثر من مجرد أداة للتطوير القائم على الاختبار ، مما يساعدك على تصميم البرامج وتنفيذها وتقديمها بشكل تدريجي ، وهو أمر مفيد بشكل خاص في بيئة رشيقة.
موارد
- Galen Framework (الموقع الرسمي)
- إطار جالين ، جيثب
- إضافات جالين (مكتبة) ، جيثب
- جالين بوتستراب ، جيثب
- "دروس Galen Framework التعليمية" ، يوتيوب