AICODEAgentic Programming · 67723 · 2026-7

Week 5 · video 3 of 8 · transcript

Testing GUIs and the Logic Behind Them

ترجمة آلية لم يراجعها إنسان.AI translation, not reviewed by a person.

0:00

عندما تطلبون من وكيل أن يبني ميزة، فقد ينهي العمل دون أن يكتب اختبارات أو يشغّلها، ما لم تطلبوها. وفي تطبيق له واجهة رسومية، اطلبوا منه أيضًا أن يختبر ما يفعله المستخدم فعلًا. سنرى كيف تفتح أداة اسمها Playwright صفحة وتختبر تفاعلًا. ثم سننظر في بنية التطبيق نفسه، لأن بعض البُنى تجعل الاختبار أسهل بكثير. عندما يُفصل المنطق عن الواجهة، يمكن اختبار معظمه مباشرة، دون رسم أي شاشة. ولهذا الفصل فائدة ثانية. فالمنطق لم يعد مرتبطًا بمكتبة الواجهة التي يستخدمها حاليًا، لذا يمكن تحديث أيّ من الجانبين أو استبداله دون إعادة كتابة الآخر. سنستخدم تصميمًا اسمه Model View ViewModel لنوضّح كيف يعمل ذلك.

0:46

يتيح Playwright للاختبار أن يتحكّم في متصفح حقيقي. يخبر الاختبار Playwright بما يجب فعله، فيفتح Playwright الصفحة في المتصفح، وينقر، ويكتب، ويقرأ ما يظهر على الشاشة.

0:57

هذه هي الصفحة التي سنختبرها. إنها تطبيق صغير لقائمة مهام، وإلى جانبه كود الـ HTML الخاص به. فيها مربع يحمل التسمية «New item» لإدخال عنصر جديد، وزر «Add»، وقائمة تبدأ فارغة.

1:10

التسمية هي ما يميّز مربع «New item». لذا يستطيع الاختبار أن يطلب من Playwright المربع ذا التسمية «New item».

1:18

اسم الزر «Add». لذا يستطيع الاختبار أن يطلب الزر الذي اسمه «Add». يستخدم الاختبار هذه التسميات والأسماء ليجد عناصر التحكّم اللازمة، الأسماء نفسها التي يراها المستخدم على الشاشة. وإعطاء عناصر التحكّم تسميات ذات معنى يسهّل كتابة هذه الاختبارات.

1:35

وهذا الآن اختبار متصفح كامل لتطبيق المهام، مكتوب بلغة Python. التطبيق يعمل على هذا الحاسوب، وقائمته تبدأ فارغة. الصفحة التي يتلقّاها الاختبار هي صفحة متصفح يوفّرها Playwright. الخطوة الأولى تفتح عنوان التطبيق في تلك الصفحة.

1:52

بعد ذلك يجد الاختبار مربع «New item» من خلال تسميته، ويكتب فيه «Buy milk».

1:58

ثم يجد زر «Add» وينقر عليه. وفي الصفحة، يظهر الآن «Buy milk» في القائمة.

2:05

السطر الأخير يتحقّق من أن القائمة فيها عنصر واحد بالضبط، هو «Buy milk». ينتظر Playwright هذه النتيجة ضمن مهلة محدّدة، ثم يستسلم. هذا الفحص الأخير هو ما يجعله اختبارًا. فالنقر بنجاح لا يكفي. إذا لم يظهر العنصر أبدًا، يفشل الاختبار، ويستطيع الوكيل أن يقرأ هذا الفشل.

2:26

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

2:48

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

3:07

لنفترض الآن أن دالة الإضافة ما زالت صحيحة، لكن زر «Add» لم يعد موصولًا بها. اختبار المنطق ما زال ينجح، لأنه لا يمرّ بالزر أصلًا. ينقر المستخدم على «Add»، ولا يحدث شيء.

3:19

أما اختبار المتصفح فيكشف ذلك، لأنه يمرّ عبر الزر الحقيقي ويفحص النتيجة. فهو ينقر على «Add»، وينتظر ظهور «Buy milk»، ثم يفشل لأن القائمة فارغة. هذه هي المُخرَجات الفعلية لتشغيل ذلك الاختبار على صفحة زرّها غير موصول.

3:36

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

3:51

اختبار المتصفح هذا يخبرنا هل الواجهة تعمل. نريد الآن أن نختبر المنطق دون فتح الصفحة، وهذا يعتمد على طريقة تنظيم التطبيق. سنترك تطبيق المهام هنا ونستخدم مثالًا أصغر، هو محوّل لدرجات الحرارة. يُدخل المستخدم درجة حرارة مئوية، وينقر على «Convert»، فيرى النتيجة بالفهرنهايت. 20 درجة مئوية تصبح 68 درجة فهرنهايت.

4:15

حتى هذا المحوّل الصغير له ثلاث مهام. الأولى هي الحساب نفسه، وهو يتعامل مع درجة الحرارة كعدد. المهمة الثانية تحتفظ بما تحتاجه الشاشة، على شكل قيم بسيطة في البرنامج. فيها سلسلة نصية تحمل ما كُتب حتى الآن، وإجراء «Convert» يشغّل التحويل، وسلسلة نصية فيها النتيجة المعروضة، ورسالة خطأ عندما يكون المُدخَل غير صحيح. المهمة الثالثة هي عناصر التحكّم نفسها. مربع الإدخال يعرض ذلك النص ويتيح للمستخدم تغييره. الزر يشغّل إجراء «Convert» عند النقر عليه. وتسمية تعرض النتيجة أو الخطأ. عناصر التحكّم هذه لا توجد إلا عندما تُرسم الشاشة. أما قيم المهمة الثانية فيمكن ضبطها وفحصها دون رسم أي شيء.

4:57

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

5:15

هذه الطريقة في تنظيم التطبيق اسمها Model View ViewModel، أو MVVM. الأسماء الثلاثة متشابهة إلى حدّ ما، فلنربط كلًّا منها بمهمته في المحوّل.

5:26

الـ Model يحتفظ ببيانات التطبيق وقواعده، وهو هنا الدالة التي تحوّل من المئوية إلى الفهرنهايت. الـ Model هنا بالمعنى البرمجي، وليس نموذج ذكاء اصطناعي.

5:37

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

5:51

الـ ViewModel يحتفظ بالقيم والإجراءات التي يحتاجها الـ View. فكّروا فيه كنموذج لحالة الشاشة وللإجراءات المتاحة عليها. إنه ليس الشاشة نفسها، ولا يتعامل مع عناصر التحكّم. عندما يكتب المستخدم abc، يحتفظ الـ ViewModel بهذا النص كسلسلة نصية. ويحتفظ أيضًا برسالة الخطأ «Enter a number»، وبنتيجة فارغة.

6:13

ولماذا الـ ViewModel أصلًا؟ درجة الحرارة كعدد تنتمي إلى الحساب. لكن النص الذي كتبه المستخدم، مثل abc، ورسالة الخطأ المتعلقة به، والنتيجة المنسّقة، كلها تنتمي إلى التفاعل مع الشاشة. ومكانها هو الـ ViewModel.

6:28

والآن إلى الروابط. الـ View يمرّر ما يُدخله المستخدم إلى الـ ViewModel ويستدعي أوامره، مثل «Convert». والـ ViewModel يستخدم الـ Model لإجراء الحساب. والـ View يعرض القيم التي يتيحها الـ ViewModel. صلة عناصر التحكّم بقيم الـ ViewModel وأوامره تُسمّى الربط (binding). الربط يجعل الكتابة في مربع الإدخال تحدّث قيمة، ويجعل النتيجة الجديدة تظهر على الشاشة. وهكذا يتعامل الـ ViewModel مع قيم، لا مع مربع نص في صفحة.

6:59

لنرَ كيف تُنتج هذه الأجزاء الثلاثة، رغم انفصالها، محوّلًا واحدًا يعمل. سنتتبّع تفاعلًا واحدًا. في الـ View، يكتب المستخدم 20 وينقر على «Convert». يمرّر الـ View النص وأمر «Convert» إلى الـ ViewModel، فيصبح نص الـ ViewModel الآن السلسلة النصية «20».

7:17

يقرأ الـ ViewModel نص الإدخال على أنه العدد 20، ويطلب من الـ Model أن يحوّله.

7:23

يُرجع الـ Model العدد 68.

7:27

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

7:40

وهنا تظهر فائدة هذه البنية للاختبار. يمكن للاختبار فعل ما فعله الـ View دون فتح صفحة. فهو يضبط نص الـ ViewModel، ويستدعي «Convert»، ويفحص النص الذي كانت الشاشة ستعرضه. هنا النص المكتوب هو 20 مع مسافات حوله. يتحقّق الاختبار من أن الـ ViewModel يتجاهل المسافات، ولا يُظهر خطأ، ويضبط نص النتيجة على 68 درجة فهرنهايت، مع وحدة القياس. ويمكننا أيضًا أن نغيّر تخطيط الشاشة دون تغيير قاعدة التحويل. لكننا نُبقي اختبار المتصفح، لنتحقّق من أن عناصر التحكّم الحقيقية تستدعي الأمر وتعرض نتيجته.

8:13

اختبار ثانٍ يغطّي المُدخَلات الخاطئة. إذا كان نص الإدخال abc، فاستدعاء «Convert» يجب أن يضبط الخطأ على «Enter a number»، ويمسح أي نتيجة سابقة.

8:24

فأيّ اختبار يكشف أيّ خلل في المحوّل؟ لنبدأ بالـ Model. يمكننا أن نفحص الحساب مباشرة، مثلًا أن 0 درجة مئوية تساوي 32 درجة فهرنهايت. ما يبقى لاختبار GUI هو التحقّق من أن المستخدم يصل إلى الحساب عبر الصفحة.

8:40

بعد ذلك، الـ ViewModel. يمكننا أن نتحقّق مباشرة من أن المُدخَل abc يضبط خطأً ويمسح النتيجة. ما يبقى لاختبار GUI هو التحقّق من أن الخطأ يظهر فعلًا على الشاشة.

8:53

أما الـ View وروابطه فليس لها فحص مباشر. لا يُثبت إلا اختبار GUI أن النقر على «Convert» يشغّل الأمر ويعرض النتيجة.

9:02

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

9:35

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

9:57

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

10:29

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

10:58

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

11:18

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

11:40 of video · 1,563 words · 38 slides← Back to the video