الألفة مع اختبار في بيثون. الجزء 1

يوم جيد للجميع!

من طاولتنا إلى جدولك ... أي من خلال برنامجنا "Python Developer" ، على الرغم من اقتراب العام الجديد بسرعة ، قمنا بإعداد ترجمة مثيرة لك حول طرق الاختبار المختلفة في Python.

هذا الدليل مخصص لأولئك الذين كتبوا بالفعل تطبيق Python بارد لكنهم لم يكتبوا بعد
لهم الاختبارات.

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

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



اختبار الكود

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

الآلي مقابل اختبار يدوي

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

اختبار البحوث - الاختبار الذي يتم دون خطة. أثناء اختبار البحث ، يمكنك البحث في التطبيق.

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

يبدو قاتما ، أليس كذلك؟

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

وحدة الاختبارات VS. اختبارات التكامل

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

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

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

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

السيارات الحديثة نفسها سوف تعلمك بمصباح مكسور. يتم تحديد ذلك باستخدام اختبار وحدة.

اختبار الوحدة (اختبار الوحدة) هو اختبار صغير يتحقق من التشغيل الصحيح للمكون الفردي. يساعد اختبار الوحدة في عزل الانهيار وإصلاحه بشكل أسرع.

تحدثنا عن نوعين من الاختبارات:

  1. اختبار التكامل الذي يتحقق من مكونات النظام وتفاعلها مع بعضها البعض ؛
  2. اختبار وحدة يختبر مكونًا واحدًا من التطبيق.
  3. يمكنك إنشاء كلا الاختبارين في بيثون. لكتابة اختبار للدالة المدمجة () المدمجة ، تحتاج إلى مقارنة إخراج sum () بالقيم المعروفة.

على سبيل المثال ، بهذه الطريقة يمكنك التحقق من أن مجموع الأرقام (1 ، 2 ، 3) هو 6:

>>> assert sum([1, 2, 3]) == 6, "Should be 6" 

القيم صحيحة ، لذلك لن يتم إخراج أي شيء إلى REPL. إذا كانت نتيجة sum() صحيحة ، فسيتم AssertionError مع الرسالة "يجب أن تكون 6". تحقق من عبارة البيان مرة أخرى ، ولكن الآن باستخدام قيم غير صالحة للحصول على AssertionError :

 >>> assert sum([1, 1, 1]) == 6, "Should be 6" Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError: Should be 6 

في REPL ، سترى AssertionError لأن قيمة sum() ليست 6.

بدلاً من REPL ، ضع هذا في ملف Python جديد يسمى test_sum.py وقم بتشغيله مرة أخرى:

 def test_sum(): assert sum([1, 2, 3]) == 6, "Should be 6" if __name__ == "__main__": test_sum() print("Everything passed") 

الآن لديك حالة اختبار مكتوبة (حالة اختبار) وبيان ونقطة إدخال (سطر الأوامر). الآن يمكن القيام بذلك في سطر الأوامر:

 $ python test_sum.py Everything passed 

ترى النتيجة الناجحة ، "كل شيء مرت".

sum() في Python يقبل أي تكرار كحجة أولى. لقد راجعت القائمة. دعونا نحاول اختبار tuple. قم بإنشاء ملف جديد يسمى test_sum_2.py التالية:

 def test_sum(): assert sum([1, 2, 3]) == 6, "Should be 6" def test_sum_tuple(): assert sum((1, 2, 2)) == 6, "Should be 6" if __name__ == "__main__": test_sum() test_sum_tuple() print("Everything passed") 

test_sum_2.py ، سوف test_sum_2.py البرنامج النصي خطأ ، حيث يجب أن يكون s um() (1, 2, 2) 5 ، وليس 6. ونتيجة لذلك ، يعطي البرنامج النصي رسالة خطأ وسطرًا من التعليمات البرمجية وتتبع:

 $ python test_sum_2.py Traceback (most recent call last): File "test_sum_2.py", line 9, in <module> test_sum_tuple() File "test_sum_2.py", line 5, in test_sum_tuple assert sum((1, 2, 2)) == 6, "Should be 6" AssertionError: Should be 6 

يمكنك أن ترى كيف يتسبب خطأ في الكود في حدوث خطأ في وحدة التحكم بمعلومات حول مكان حدوثه والنتيجة المتوقعة.

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

اختيار اختبار الجلاد

هناك العديد من المتسابقين للاختبار المتاح لبيثون. على سبيل المثال ، يتم دمج unittest في مكتبة Python القياسية. في هذا الدليل ، سوف نستخدم حالات الاختبار وأعدم منفذي الاختبار. Uniteest مبادئ التشغيل قابلة للتكيف بسهولة مع الأطر الأخرى. ندرج أشهر منفذي الاختبار:

  • unittest
  • الأنف أو الأنف 2 ؛
  • pytest.

من المهم اختيار مقاول اختبار يلبي متطلباتك وخبراتك.

unittest

تم دمج unittest في مكتبة Python القياسية منذ الإصدار 2.1. من المحتمل أن تصادفها في تطبيقات Python التجارية والمشاريع مفتوحة المصدر.
Unittest لديه إطار اختبار واختبار عداء. عند كتابة الاختبارات وتشغيلها ، يجب عليك اتباع بعض المتطلبات المهمة.

يتطلب unittest:

  • وضع الاختبارات في الفصول كطرق ؛
  • استخدم طرق موافقة خاصة. الفئة TestCase بدلاً من تعبير التوكيد المضمّن المعتاد.


لتحويل مثال مكتوب سابقًا إلى حالة اختبار unittest ، يجب عليك:

  1. استيراد unittest من المكتبة القياسية ؛
  2. إنشاء فئة تسمى TestSum التي سوف ترث فئة TestCase ؛
  3. تحويل وظائف الاختبار إلى طرق بإضافة self كحجة أولى ؛
  4. تعديل العبارات عن طريق إضافة استخدام self.assertEqual() الأسلوب في فئة TestCase ؛
  5. تغيير نقطة الإدخال في سطر الأوامر للاتصال unittest.main() .

باتباع هذه الخطوات ، قم بإنشاء ملف test_sum_unittest.py جديد باستخدام هذا الرمز:

 import unittest class TestSum(unittest.TestCase): def test_sum(self): self.assertEqual(sum([1, 2, 3]), 6, "Should be 6") def test_sum_tuple(self): self.assertEqual(sum((1, 2, 2)), 6, "Should be 6") if __name__ == '__main__': unittest.main() 

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

 $ python test_sum_unittest.py .F ====================================================================== FAIL: test_sum_tuple (__main__.TestSum) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_sum_unittest.py", line 9, in test_sum_tuple self.assertEqual(sum((1, 2, 2)), 6, "Should be 6") AssertionError: Should be 6 ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) 

وهكذا ، قمت بإجراء اختبارين باستخدام عداء الاختبار غير المتواضع.

ملاحظة: إذا كنت تكتب حالات اختبار لبيثون 2 و 3 ، فاحذر. في إصدارات Python 2.7 والإصدارات الأحدث ، يسمى unittest unittest 2. عندما تقوم بالاستيراد من unittest ، ستحصل على إصدارات مختلفة بوظائف مختلفة في Python 2 و Python 3.

لمعرفة المزيد حول unittest ، اقرأ الوثائق unittest .

أنف

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

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

لبدء استخدام nose2 ، تحتاج إلى تثبيته من PyPl وتشغيله في سطر الأوامر. سيحاول nose2 العثور على جميع البرامج النصية للاختبار مع test*.py في الاسم وجميع حالات الاختبار الموروثة من unittest.TestCase في الدليل الحالي:

 $ pip install nose2 $ python -m nose2 .F ====================================================================== FAIL: test_sum_tuple (__main__.TestSum) ---------------------------------------------------------------------- Traceback (most recent call last): File "test_sum_unittest.py", line 9, in test_sum_tuple self.assertEqual(sum((1, 2, 2)), 6, "Should be 6") AssertionError: Should be 6 ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) 

هذه هي الطريقة التي يتم بها تنفيذ الاختبار الذي تم إنشاؤه في test_sum_unittest.py من عداء اختبار nose2. يوفر nose2 العديد من علامات سطر الأوامر لتصفية الاختبارات القابلة للتنفيذ. لمزيد من المعلومات ، راجع وثائق Nose 2 .

pytest

pytest يدعم unittest حالات الاختبار. ولكن الميزة الحقيقية لل pytest هي حالات الاختبار. حالات اختبار pytest هي سلسلة من الوظائف في ملف Python مع test_ في بداية الاسم.

هناك ميزات أخرى مفيدة في ذلك:

  • دعم تعبيرات التأكيد المضمنة بدلاً من استخدام أساليب self.assert * () خاصة ؛
  • دعم لتصفية حالات الاختبار.
  • القدرة على إعادة التشغيل من آخر اختبار فاشل ؛
  • نظام بيئي لمئات المكونات الإضافية التي تعمل على توسيع الوظائف.

مثال حالة اختبار TestSum لـ pytest سيبدو كما يلي:

 def test_sum(): assert sum([1, 2, 3]) == 6, "Should be 6" def test_sum_tuple(): assert sum((1, 2, 2)) == 6, "Should be 6" 

لقد تخلصت من TestCase ، وذلك باستخدام الفئات ونقاط إدخال سطر الأوامر.
يمكن الاطلاع على مزيد من المعلومات على موقع وثائق Pytest .

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

الجمع بين كل ما تعلمناه بالفعل ، وبدلاً من وظيفة sum() المدمجة ، نقوم باختبار تطبيق بسيط بنفس المتطلبات.

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

ستبدو بنية المجلد كما يلي:

project/

└── my_sum/
└── __init__.py


افتح my_sum/__init__.py وقم بإنشاء دالة جديدة تسمى sum() ، والتي تأخذ مدخلات my_sum/__init__.py (قائمة ، tuple ، set) وتضيف القيم.

 def sum(arg): total = 0 for val in arg: total += val return total 

يقوم هذا المثال بإنشاء متغير يسمى total ، يتكرر على كل القيم في arg ويضيف إلى total . ثم ، عند الانتهاء من التكرار ، يتم إرجاع النتيجة.

أين تكتب الاختبار

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

project/

├── my_sum/
│ └── __init__.py
|
└── test.py


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

ملاحظة: وما هو التطبيق الخاص بك هو سيناريو واحد؟
يمكنك استيراد أي سمات للبرنامج النصي: الفئات أو الوظائف أو المتغيرات ، باستخدام __import__() المضمنة. بدلاً from my_sum import sum اكتب ما يلي:

 target = __import__("my_sum.py") sum = target.sum 

عند استخدام __import__() لا يلزم تحويل مجلد المشروع إلى حزمة ، ويمكنك تحديد اسم الملف. يعد هذا مفيدًا إذا تعارض اسم الملف مع أسماء مكتبات الحزمة القياسية. على سبيل المثال ، إذا كان math.py يتعارض مع وحدة الرياضيات.

كيفية هيكلة اختبار بسيط

قبل كتابة الاختبارات ، تحتاج إلى حل بعض الأسئلة:

  1. ماذا تريد أن اختبار؟
  2. هل تكتب اختبار وحدة أم اختبار دمج؟

أنت تختبر حاليًا sum() . يمكنك اختبار سلوكيات مختلفة لذلك ، على سبيل المثال:

  • هل من الممكن تلخيص قائمة الأعداد الصحيحة؟
  • هل من الممكن تلخيص tuple أو مجموعة؟
  • هل يمكنني تلخيص قائمة بأرقام الفاصلة العائمة؟
  • ماذا يحدث إذا أعطيت قيمة سيئة للمدخلات: عدد صحيح واحد أو سلسلة؟
  • ماذا يحدث إذا كانت إحدى القيم سالبة؟

أسهل طريقة للاختبار هي قائمة الأعداد الصحيحة. قم test.py ملف test.py التالية:

 import unittest from my_sum import sum class TestSum(unittest.TestCase): def test_list_int(self): """ Test that it can sum a list of integers """ data = [1, 2, 3] result = sum(data) self.assertEqual(result, 6) if __name__ == '__main__': unittest.main() 

الكود في هذا المثال:

  • يستورد sum() من الحزمة my_sum() التي أنشأتها ؛
  • يعرّف فئة حالة اختبار جديدة تسمى TestSum يرث unittest.TestCase ؛
  • يحدد طريقة اختبار .test_list_int() لاختبار قائمة عدد صحيح. الطريقة .test_list_int() ستقوم بما يلي
:
  1. يعلن متغير data مع قائمة القيم (1, 2, 3) ؛
  2. my_sum.sum(data) القيمة my_sum.sum(data) result المتغيرة ؛
  3. يحدد أن قيمة النتيجة هي 6 باستخدام الأسلوب .assertEqual() في فئة unittest.TestCase .

  • يعرّف نقطة إدخال سطر الأوامر التي تطلق عداء اختبار .main() .

إذا كنت لا تعرف ما هي الذات ، أو كيف يتم تعريف .assertEqual() ، فيمكنك تحديث معرفتك بالبرمجة الموجهة للكائنات باستخدام البرمجة الموجهة للكائنات Python 3 .

كيفية كتابة البيانات

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

  • تحقق من أن الاختبارات قابلة للتكرار وتشغيلها عدة مرات للتأكد من أنها تعطي نفس النتائج في كل مرة ؛
  • تحقق من النتائج التي تنطبق على مدخلاتك وقم بتأكيدها - تحقق من أن النتيجة هي مجموع القيم في المثال sum() .

لدى Unittest العديد من الطرق لتأكيد قيم المتغيرات وأنواعها ووجودها. فيما يلي بعض الطرق الأكثر شيوعًا:

الطريقةأي ما يعادل
.assertEqual (a، b)== ب
.assertTrue (x)منطقي (x) صحيح
.assertFalse (x)منطقي (x) خطأ
. asertIs (أ ، ب)أ ب
.assertIsNone (x)س لا شيء
.اسيرتين (أ ، ب)في ب
.assertIsInstance (a، b)isinstance (أ ، ب)


.assertIs() و .assertIsNone() و .assertIn() و .assertIsInstance() لديهم طرق معاكسة تسمى .assertIsNot() وهكذا.

آثار جانبية

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

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

إطلاق الاختبار الأول

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

تشغيل اختبار التنفيذيين

Test Executor - تطبيق Python يقوم بتشغيل رمز الاختبار ، والتحقق من صحة التأكيدات ، ويعرض نتائج الاختبار في وحدة التحكم. في نهاية test.py أضف قطعة صغيرة من التعليمات البرمجية:

 if __name__ == '__main__': unittest.main() 

هذه هي نقطة دخول سطر الأوامر. إذا قمت بتشغيل هذا البرنامج النصي عن طريق تشغيل python test.py في سطر الأوامر ، فسيتم استدعاء unittest.main() . يؤدي هذا إلى بدء تشغيل اختبار التشغيل عن unittest.TestCase الكشف عن جميع الفئات الموجودة في هذا الملف والتي ترث من unittest.TestCase .

هذه هي واحدة من العديد من الطرق لتشغيل عداء اختبار unittest. إذا كان لديك ملف اختبار واحد يسمى test.py ، فإن استدعاء python test.py هو وسيلة رائعة للبدء.

هناك طريقة أخرى هي استخدام سطر الأوامر unittest. لنجرب:

 $ python -m unittest test 

سيؤدي ذلك إلى تنفيذ نفس وحدة الاختبار (تسمى test ) من خلال سطر الأوامر. يمكنك إضافة معلمات إضافية لتغيير الإخراج. واحد منهم هو -v ل verbose. لنجرب ما يلي:

 $ python -m unittest -v test test_list_int (test.TestSum) ... ok ---------------------------------------------------------------------- Ran 1 tests in 0.000s 

أجرينا اختبارًا واحدًا من test.py وقمنا بإخراج النتائج إلى وحدة التحكم. وضع مطول سرد أسماء الاختبارات التي أجريت ونتائج كل منها.

بدلاً من تقديم اسم الوحدة النمطية التي تحتوي على الاختبارات ، يمكنك طلب الاكتشاف التلقائي باستخدام ما يلي:

 $ python -m unittest discover 

سيبحث هذا الأمر في الدليل الحالي للملفات ذات test*.py في الاسم لاختبارها.

إذا كان لديك العديد من ملفات الاختبار وتتبع نمط تسمية test*.py ، فيمكنك تمرير اسم الدليل باستخدام علامة -s واسم المجلد.

 $ python -m unittest discover -s tests 

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

 $ python -m unittest discover -s tests -t src 

سيجد unittest جميع ملفات test*.py في src/ directory داخل tests ، ثم يقوم بتنفيذها.

فهم نتائج الاختبار

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

يجب أن يقبل sum() قوائم أخرى من النوع الرقمي ، على سبيل المثال الكسور.

إلى بداية التعليمة البرمجية في test.py أضف تعبيرًا لاستيراد نوع Fraction من وحدة fractions في المكتبة القياسية.

 from fractions import Fraction 

أضف الآن اختبارًا مع بيانًا ، متوقعًا قيمة غير صحيحة. في حالتنا ، نتوقع أن يكون مجموع ¼ و ¼ و equal يساوي 1:

 import unittest from my_sum import sum class TestSum(unittest.TestCase): def test_list_int(self): """ Test that it can sum a list of integers """ data = [1, 2, 3] result = sum(data) self.assertEqual(result, 6) def test_list_fraction(self): """ Test that it can sum a list of fractions """ data = [Fraction(1, 4), Fraction(1, 4), Fraction(2, 5)] result = sum(data) self.assertEqual(result, 1) if __name__ == '__main__': unittest.main() 

إذا قمت بإجراء الاختبارات مرة أخرى باستخدام اختبار python -m unittest ، فحصل على ما يلي:

 $ python -m unittest test F. ====================================================================== FAIL: test_list_fraction (test.TestSum) ---------------------------------------------------------------------- Traceback (most recent call last): File "test.py", line 21, in test_list_fraction self.assertEqual(result, 1) AssertionError: Fraction(9, 10) != 1 ---------------------------------------------------------------------- Ran 2 tests in 0.001s FAILED (failures=1) 

في هذا الإخراج ، ترى ما يلي:

  • يعرض السطر الأول نتائج جميع الاختبارات: فشل واحد (F) ، واحد نجح (.) ؛
  • يعرض FAIL بعض تفاصيل الاختبار الفاشل:

  1. اسم طريقة الاختبار ( test_list_fraction ) ؛
  2. وحدة test ( test ) وحالة الاختبار ( TestSum ) ؛
  3. سلاسل تتبع مع وجود خطأ ؛
  4. تفاصيل البيان بالنتيجة المتوقعة (1) والنتيجة الفعلية (الكسر (9 ، 10))

تذكر أنه يمكنك إضافة معلومات إضافية إلى اختبار الإخراج باستخدام علامة -v إلى الأمر python -m unittest .

تشغيل الاختبارات من PyCharm

إذا كنت تستخدم PyCharm IDE ، فيمكنك تشغيل unittest أو pytest باتباع الخطوات التالية:

  1. في نافذة أداة المشروع ، حدد دليل الاختبارات.
  2. في قائمة السياق ، حدد الأمر unittest run. على سبيل المثال ، "Unittests في اختباراتي ...".

سيؤدي هذا إلى تنفيذ إجراء الاختبار في نافذة الاختبار وإرجاع النتائج في PyCharm:



مزيد من المعلومات متاح على موقع PyCharm .

تشغيل الاختبارات من Visual Studio Code

إذا كنت تستخدم Microsoft Visual Studio Code IDE ، فإن دعم unittest والأنف و pytest مدمج بالفعل في البرنامج المساعد Python.

إذا كنت قد قمت بتثبيته ، يمكنك تكوين تكوين الاختبار عن طريق فتح لوحة القيادة مع Ctrl + Shift + P وكتابة "اختبار Python". سترى قائمة من الخيارات:



حدد Debug All Unit Tests ، وبعد ذلك سيرسل VSCode طلبًا لتكوين إطار الاختبار. انقر على الترس لاختيار عداء الاختبار (unittest) والدليل الرئيسي (.).

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



نرى أن الاختبارات تجرى ، لكن بعضها فشل.

النهاية

في الجزء التالي من المقال ، سوف ندرس اختبارات الأطر مثل Django و Flask.

نحن في انتظار الأسئلة والتعليقات هنا ، وكما هو الحال دائمًا ، يمكنك الذهاب إلى ستانيسلاف في يوم مفتوح .

الجزء الثاني

Source: https://habr.com/ru/post/ar433358/


All Articles