الاختبار القائم على الخصائص في Go: كسر الكود أسرع مما تكتبه

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

عندما تكذب اختبارات الوحدة وتبقى الأخطاء



لقد كتبت 20 اختبار وحدة. كلها خضراء. CI يمر. أنت راضٍ. ثم بعد ذلك - خطأ في الإنتاج. مألوف؟ سيناريو كلاسيكي: لقد اختبرت فقط الحالات التي فكرت بها بنفسك. والواقع، للأسف، يقدم مجموعات لم تفكر بها حتى.



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



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



ما هو الاختبار القائم على الخصائص ولماذا هو مطلوب؟



تخيل أنك تختبر دالة فرز. اختبار وحدة عادي:



func TestSort(t *testing.T) {    input := []int{3, 1, 2}    result := sort(input)    expected := []int{1, 2, 3}    if !reflect.DeepEqual(result, expected) {        t.Errorf("got %v, want %v", result, expected)    }}


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



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



  • طول المصفوفة التي تم فرزها يساوي طول المصفوفة الأصلية.
  • كل عنصر من المصفوفة الأصلية موجود في المصفوفة التي تم فرزها (والعكس صحيح).
  • المصفوفة مرتبة تصاعديًا.


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



مكتبات Go للاختبار القائم على الخصائص



في نظام Go البيئي، هناك عدة أدوات:



  • testing/quick - حزمة مدمجة، بسيطة ولكن بإمكانيات محدودة.
  • gopter - مكتبة قوية مع مولدات، وتقليص (تصغير بيانات الإدخال) وإعدادات مرنة. نوصي بها تحديدًا.
  • rapid - بديل حديث، أكثر أداءً.


سنستخدم gopter لأنها تحتوي على أفضل توثيق ومجتمع. التثبيت:



go get github.com/leanovate/gopter


كتابة أول اختبار قائم على الخصائص في Go



لنفترض أن لدينا دالة Reverse تعكس سلسلة نصية:



func Reverse(s string) string {    runes := []rune(s)    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {        runes[i], runes[j] = runes[j], runes[i]    }    return string(runes)}


ما الخاصية التي يمكن التحقق منها؟ إذا قمت بعكس السلسلة مرتين، يجب أن نحصل على السلسلة الأصلية:



import (    "testing"    "github.com/leanovate/gopter"    "github.com/leanovate/gopter/gen")

func TestReverseTwice(t *testing.T) { properties := gopter.NewProperties(nil)

properties.Property("reverse(reverse(s)) == s", prop.ForAll( func(s string) bool { return Reverse(Reverse(s)) == s }, gen.AnyString(), ))

properties.TestingRun(t)}


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



Bo

المدونات

توصيات الكتب