كتم التعلم - أداة اختبار طفرة Python

يتيح لك اختبار الطفرة تحديد الأخطاء التي لا تغطيها الاختبارات التقليدية.



هل لديكم فحوصات لجميع المناسبات؟ أو ربما يحتوي مستودع مشروعك على مساعدة "حوالي 100٪ تغطية اختبارية"؟ ولكن هل كل شيء بهذه البساطة ويمكن تحقيقه في الحياة الواقعية؟







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



إنه اختبار الطفراتيسمح لك بالتعامل مع هذه الأخطاء الخبيثة. يقوم بتعديل الكود المصدري بطريقة محددة مسبقًا (إدخال أخطاء خاصة - ما يسمى بـ "المسوخات") ويتحقق مما إذا كانت هذه الطفرات على قيد الحياة في اختبارات أخرى. أي متحولة نجت من اختبار الوحدة تؤدي إلى استنتاج مفاده أن الاختبارات القياسية لم تعثر على الجزء المقابل المعدل من الكود الذي يحتوي على الخطأ.



في Python ، يعد mutmut هو الأداة الأساسية لاختبار الطفرات .



تخيل أننا نحتاج إلى كتابة رمز يحسب الزاوية بين عقرب الساعات وعقرب الدقائق في ساعة عادية:



def hours_hand(hour, minutes):
    base = (hour % 12 ) * (360 // 12)
    correction = int((minutes / 60) * (360 // 12))
    return base + correction

def minutes_hand(hour, minutes):
    return minutes * (360 // 60)

def between(hour, minutes):
    return abs(hours_hand(hour, minutes) - minutes_hand(hour, minutes))


لنكتب اختبار الوحدة الأساسي:



import angle

def test_twelve():
    assert angle.between(12, 00) == 0


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



$ coverage run `which pytest`
============================= test session starts ==============================
platform linux -- Python 3.8.3, pytest-5.4.3, py-1.8.2, pluggy-0.13.1
rootdir: /home/moshez/src/mut-mut-test
collected 1 item                                                              

tests/test_angle.py .                                                    [100%]

============================== 1 passed in 0.01s ===============================


ممتاز! مثل تغطية 100٪. لكن ماذا يحدث عندما نجري اختبار الطفرات؟







أوه لا! من أصل 21 ، نجا ما يصل إلى 16 متحولة. كيف ذلك؟



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



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



$ mutmut results
<snip>
Survived :( (16)

---- angle.py (16) ----

4-7, 9-14, 16-21
$ mutmut apply 4
$ git diff
diff --git a/angle.py b/angle.py
index b5dca41..3939353 100644
--- a/angle.py
+++ b/angle.py
@@ -1,6 +1,6 @@
 def hours_hand(hour, minutes):
     hour = hour % 12
-    base = hour * (360 // 12)
+    base = hour / (360 // 12)
     correction = int((minutes / 60) * (360 // 12))
     return base + correction


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



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



$ git diff
diff --git a/tests/test_angle.py b/tests/test_angle.py
index f51d43a..1a2e4df 100644
--- a/tests/test_angle.py
+++ b/tests/test_angle.py
@@ -2,3 +2,6 @@ import angle
 
 def test_twelve():
     assert angle.between(12, 00) == 0
+
+def test_three():
+    assert angle.between(3, 00) == 90


في السابق ، كنا نتحقق فقط من 12. هل تؤدي إضافة شيك للقيمة 3 إلى إنقاذ اليوم؟







نجح هذا الاختبار الجديد في قتل اثنين من المسوخين: إنه أفضل من ذي قبل ، ولكن هناك المزيد من العمل الذي يتعين القيام به. لن أكتب حلاً لكل حالة من الحالات الـ 14 المتبقية في الوقت الحالي ، لأن الفكرة واضحة بالفعل (هل يمكنك قتل جميع المسوخ بنفسك؟)



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






إعلان



يقدم VDSina خوادم افتراضية لنظامي Linux و Windows - اختر أحد أنظمة التشغيل المثبتة مسبقًا ، أو قم بالتثبيت من صورتك.






All Articles