الفرق بين المراجعتين ل"ReactNative/testing overview"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'== الاختبار Testing ==')
 
سطر 1: سطر 1:
 
== الاختبار Testing ==
 
== الاختبار Testing ==
 +
يمكن أن تتحول الأخطاء الصغيرة التي لا تتوقعها إلى حالات فشل أكبر مع توسع قاعدة الشيفرة، حيث تؤدي الأخطاء إلى تجربة مستخدم سيئة والتي ستؤدي في النهاية خسائر تجارية. تتمثل إحدى طرق منع البرمجة الضعيفة في اختبار شيفرتك قبل إصدارها.
 +
 +
سنغطّي طرقًا آلية مختلفة لضمان عمل تطبيقك كما هو متوقع بدءًا من التحليل الساكن إلى الاختبارات الشاملة.
 +
 +
=== أهمية عملية الاختبار ===
 +
نحن بشر والبشر يخطئون. الاختبار مهم لأنه يساعدك في الكشف عن هذه الأخطاء والتحقق من عمل شيفرتك، ويضمن الاختبار استمرار عمل شيفرتك في المستقبل عند إضافة ميزات جديدة، أو إعادة بناء الميزات الموجودة، أو ترقية الاعتماديات الرئيسية لمشروعك.
 +
 +
من أفضل الطرق لإصلاح خطأ في شيفرتك هي كتابة اختبار فاشل يفضح هذا الخطأ، ثم إن نجح هذا الاختبار عند إصلاح الخطأ وإعادة تشغيله، فهذا يعني أن الخطأ قد أُصلِح، ولن يُعاد إدخاله في قاعدة الشيفرة مطلقًا.
 +
 +
يمكن أيضًا أن تكون الاختبارات بمثابة توثيق للأشخاص الجدد الذين ينضمون إلى فريقك، إذ يمكن أن تساعد اختبارات القراءة الأشخاص الذين لم يروا قاعدة بيانات من قبل على فهم كيفية عمل الشيفرة الموجودة.
 +
 +
وأخيرًا، يؤدي إجراء المزيد من الاختبارات الآلية إلى قضاء وقت أقل في عملية ضمان الجودة اليدوية، مما يوفر وقتًا ثمينًا.
 +
 +
=== التحليل الساكن Static Analysis ===
 +
تتمثل الخطوة الأولى لتحسين جودة الشيفرة في البدء في استخدام أدوات التحليل الساكنة، إذ يفحص التحليل الساكن شيفرتك بحثًا عن الأخطاء أثناء كتابتها دون تشغيل أي من تلك الشيفرة.
 +
 +
* تحلّل أدوات '''Linter''' الشيفرة للكشف عن الأخطاء الشائعة مثل الشيفرة غير المستخدمة وللمساعدة في تجنب المخاطر، ولإعلام دليلٍ من النمط المحرَّم مثل استخدام مفايتح tab بدلًا من المسافات (أو العكس اعتمادًا على الإعداد الخاص بك).
 +
 +
* يضمن التحقق من النوع '''Type checking''' تطابق البنية التي تمرّرها إلى دالة ما صُمِّمت الدالة لقبوله، كمنع تمرير سلسلة إلى دالة حسابية تقبل أعدادًا.
 +
 +
يأتي إطار عمل React Native مع أداتين من هذا القبيل هما: [https://eslint.org/ ESLint] للكشف عن الأخطاء و [https://flow.org/en/docs/ Flow] للتحقق من النوع. يمكنك أيضًا استخدام لغة [[ReactNative/typescript|TypeScript]]، وهي لغة مكتوبة تُصرَّف إلى لغة JavaScript صِرفة.
 +
 +
=== كتابة شيفرة قابلة للاختبار ===
 +
تحتاج لبدء الاختبارات أولًا إلى كتابة شيفرةٍ قابلة للاختبار. افترض مثلًا عملية تصنيع الطائرات، حيث يجري اختبار أجزاء الطائرة لضمان أنها آمنة وتعمل بصورةٍ صحيحة قبل إقلاع الطائرة لأول مرة لإثبات أن جميع أنظمتها المعقدة تعمل مع بعضها البعض بصورة جيدة، إذ تُختبَر الأجنحة عن طريق ثنيها تحت حمولة شديدة، وتُختبَر أجزاء المحرك للتأكد من متانتها، ويُختبَر الزجاج الأمامي ضد تأثير محاكاة الطيور.
 +
 +
البرمجيات مشابهة للطائرة، إذ يمكنك كتابة شيفرتك ضمن وحدات صغيرة متعددة بدلًا من كتابة برنامجك بالكامل في ملف ضخم واحد يحتوي على العديد من الأسطر البرمجية، بحيث يمكنك اختبار وحدات الشيفرة اختبارًا أكثر شمولًا من اختبار جميع الشيفرة. تتشابك بهذه الطريقة كتابة الشيفرة القابلة للاختبار مع كتابة شيفرة معيارية دون اخطاء.
 +
 +
يمكنك جعل تطبيقك أكثر قابلية للاختبار من خلال فصل جزء عرض تطبيقك (أو مكونات React) عن منطق عملك وحالة التطبيق (بغض النظر عما إذا استخدمت Redux أو MobX أو حلولًا أخرى). يمكنك باستخدام هذه الطريقة الاحتفاظ باختبار منطق عملك (والذي لا ينبغي أن يعتمد على مكونات React) بصورةٍ مستقلة عن المكونات نفسها، فالهدف الأساسي هو إخراج واجهة مستخدم تطبيقك.
 +
 +
يمكنك الذهاب إلى أبعد من ذلك نظريًا من خلال نقل كل المنطق والبيانات المجلوبة من مكوناتك، وبالتالي ستُخصَّص مكوناتك فقط للإخراج، وستكون حالتك مستقلة تمامًا عن مكوناتك، إذ سيعمل منطق تطبيقك بدون أي مكونات React على الإطلاق.
 +
 +
=== اختبارات الكتابة ===
 +
يجب الآن كتابة بعض الاختبارات الفعلية بعد كتابة شيفرة قابلة للاختبار. يُحمَّل قالب React Native الافتراضي مع إطار عمل اختبار [https://jestjs.io/ Jest]، ويشتمل هذا القالب على إعداد مسبق مصمَّم خصيصًا لهذه البيئة حتى تتمكن من زيادة الإنتاجية دون تعديل الإعداد والتزييفات mocks (سنتكلم لاحقًا عن التزييف mocking). يمكنك استخدام Jest لكتابة جميع أنواع الاختبارات.<blockquote>إن أجريت تطويرًا يعتمد على الاختبار، فيجب كتابة الاختبارات أولًا، وبالتالي تصبح شيفرتك قابلة للاختبار.</blockquote>
 +
 +
==== بنية الاختبارات ====
 +
يجب أن تكون اختباراتك قصيرة وتختبر شيئًا واحدًا فقط. لنبدأ بمثال اختبار وحدة مكتوب باستخدام Jest:<syntaxhighlight lang="javascript">
 +
it('given a date in the past, colorForDueDate() returns red', () => {
 +
  expect(colorForDueDate('2000-10-20')).toBe('red');
 +
});
 +
</syntaxhighlight>يوصَف الاختبار بواسطة السلسلة المُمرَّرة إلى الدالة [https://jestjs.io/docs/api#testname-fn-timeout <code>it</code>]. احرص على كتابة الوصف مع توضيح ما تختبره، إذ يجب أن يتضمن الوصف ما يلي:
 +
 +
# '''Given''': بعض الشروط المسبقة
 +
# '''When''': بعض الإجراءات التي تنفّذها الدالة التي تختبرها
 +
# '''Then''': النتيجة المتوقعة
 +
 +
يُعرف ذلك أيضًا باسم AAA (Arrange, Act, Assert).
 +
 +
يقدّم Jest دالة <code>[https://jestjs.io/docs/api#describename-fn describe]</code> للمساعدة في تنظيم اختباراتك. استخدم دالة <code>describe</code> لتجميع جميع الاختبارات التي تنفّذ المهمة نفسها، ويمكن أن تتداخل الأوصاف، إذا كنت بحاجة إلى ذلك. الدوال الأخرى التي ستستخدمها هي <code>[https://jestjs.io/docs/api#beforeeachfn-timeout beforeEach]</code> أو <code>[https://jestjs.io/docs/api#beforeallfn-timeout beforeAll]</code> التي يمكنك استخدامها لإعداد الكائنات التي تختبرها. اقرأ المزيد في [https://jestjs.io/docs/api Jest api reference].
 +
 +
إذا كان الاختبار الخاص بك يحتوي على العديد من الخطوات أو التوقعات، فقد تقسّمه إلى عدة خطوات أصغر. تأكد أيضًا من أن اختباراتك مستقلة تمامًا عن بعضها البعض، إذ يجب أن يكون كل اختبار في مجموعتك قابلًا للتنفيذ بمفرده دون إجراء اختبار آخر أولًا. بينما إذا أجريت جميع اختباراتك معًا، فيجب ألا يؤثر الاختبار الأول على خرج الاختبار الثاني.
 +
 +
أخيرًا، يحب المطورون عندما تعمل شيفرتهم دون أخطاء، والعكس صحيح عند تطبيق الاختبارات، فالاختبار الفاشل هو شيء جيد. يخبرنا فشل الاختبار أن هناك شيئًا ما ليس صحيحًا، وهذا يمنحك فرصة لإصلاح المشكلة قبل أن تؤثر على المستخدمين.
 +
 +
=== اختبارات الوحدة Unit tests ===
 +
تغطي اختبارات الوحدة أصغر أجزاء الشيفرة، مثل الدوال أو الأصناف الفردية.
 +
 +
إذا احتوى الكائن قيد الاختبار على أي اعتماديات، فيجب تزييفه كما هو موضح في الفقرة التالية.
 +
 +
ميزة اختبارات الوحدة هي أنها سريعة في الكتابة والتشغيل، لذلك تحصل أثناء عملك على ملاحظات سريعة حول نجاح اختباراتك أو فشلها. يمتلك Jest أيضًا خيارًا لتشغيل الاختبارات ذات الصلة بالشيفرة الذي تعدلها: وضع المشاهدة باستمرار.
 +
[[ملف:p tests-unit.svg|بديل=tests unit|مركز|تصغير|491x491بك]]

مراجعة 20:12، 2 يونيو 2021

الاختبار Testing

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

سنغطّي طرقًا آلية مختلفة لضمان عمل تطبيقك كما هو متوقع بدءًا من التحليل الساكن إلى الاختبارات الشاملة.

أهمية عملية الاختبار

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

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

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

وأخيرًا، يؤدي إجراء المزيد من الاختبارات الآلية إلى قضاء وقت أقل في عملية ضمان الجودة اليدوية، مما يوفر وقتًا ثمينًا.

التحليل الساكن Static Analysis

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

  • تحلّل أدوات Linter الشيفرة للكشف عن الأخطاء الشائعة مثل الشيفرة غير المستخدمة وللمساعدة في تجنب المخاطر، ولإعلام دليلٍ من النمط المحرَّم مثل استخدام مفايتح tab بدلًا من المسافات (أو العكس اعتمادًا على الإعداد الخاص بك).
  • يضمن التحقق من النوع Type checking تطابق البنية التي تمرّرها إلى دالة ما صُمِّمت الدالة لقبوله، كمنع تمرير سلسلة إلى دالة حسابية تقبل أعدادًا.

يأتي إطار عمل React Native مع أداتين من هذا القبيل هما: ESLint للكشف عن الأخطاء و Flow للتحقق من النوع. يمكنك أيضًا استخدام لغة TypeScript، وهي لغة مكتوبة تُصرَّف إلى لغة JavaScript صِرفة.

كتابة شيفرة قابلة للاختبار

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

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

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

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

اختبارات الكتابة

يجب الآن كتابة بعض الاختبارات الفعلية بعد كتابة شيفرة قابلة للاختبار. يُحمَّل قالب React Native الافتراضي مع إطار عمل اختبار Jest، ويشتمل هذا القالب على إعداد مسبق مصمَّم خصيصًا لهذه البيئة حتى تتمكن من زيادة الإنتاجية دون تعديل الإعداد والتزييفات mocks (سنتكلم لاحقًا عن التزييف mocking). يمكنك استخدام Jest لكتابة جميع أنواع الاختبارات.

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

بنية الاختبارات

يجب أن تكون اختباراتك قصيرة وتختبر شيئًا واحدًا فقط. لنبدأ بمثال اختبار وحدة مكتوب باستخدام Jest:

it('given a date in the past, colorForDueDate() returns red', () => {
  expect(colorForDueDate('2000-10-20')).toBe('red');
});

يوصَف الاختبار بواسطة السلسلة المُمرَّرة إلى الدالة it. احرص على كتابة الوصف مع توضيح ما تختبره، إذ يجب أن يتضمن الوصف ما يلي:

  1. Given: بعض الشروط المسبقة
  2. When: بعض الإجراءات التي تنفّذها الدالة التي تختبرها
  3. Then: النتيجة المتوقعة

يُعرف ذلك أيضًا باسم AAA (Arrange, Act, Assert).

يقدّم Jest دالة describe للمساعدة في تنظيم اختباراتك. استخدم دالة describe لتجميع جميع الاختبارات التي تنفّذ المهمة نفسها، ويمكن أن تتداخل الأوصاف، إذا كنت بحاجة إلى ذلك. الدوال الأخرى التي ستستخدمها هي beforeEach أو beforeAll التي يمكنك استخدامها لإعداد الكائنات التي تختبرها. اقرأ المزيد في Jest api reference.

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

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

اختبارات الوحدة Unit tests

تغطي اختبارات الوحدة أصغر أجزاء الشيفرة، مثل الدوال أو الأصناف الفردية.

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

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

tests unit