التطوير المدفوع بالاختبارات في فلاتر
التطوير المدفوع بالاختبارات في فلاتر
التطوير المدفوع بالاختبارات (TDD) هو نهج تطوير برمجي تكتب فيه اختبارًا فاشلًا قبل كتابة أي كود إنتاجي. فقط بعد وجود الاختبار وفشله للسبب الصحيح تكتب الحد الأدنى من الكود لتجتازه — ثم تُعيد هيكلته بحرية محميًا بالاختبار. تُعرف هذه الدورة بـ أحمر ← أخضر ← أعد الهيكلة، وهي من أكثر التقنيات موثوقية لبناء ميزات Flutter صحيحة وقابلة للصيانة.
دورة أحمر-أخضر-أعد الهيكلة
تتبع كل تكرار TDD ثلاث خطوات بالضبط:
- أحمر — اكتب اختبارًا يصف السلوك المطلوب. شغّله. يجب أن يفشل (الميزة غير موجودة بعد). الاختبار الذي يجتاز فورًا بدون كود ليس اختبار TDD صحيح.
- أخضر — اكتب الحد الأدنى من كود الإنتاج المطلوب لاجتياز الاختبار الفاشل. لا تبالغ في الهندسة. الكود الرديء مقبول هنا؛ الصحة هي الهدف الوحيد.
- أعد الهيكلة — نظّف كود الإنتاج (وإذا لزم الأمر الاختبار) دون تغيير السلوك الملاحظ. مجموعة الاختبارات الخضراء تعمل كشبكة أمان: إن عادت حمراء فقد كسرت شيئًا.
بناء ميزة بـ TDD: تجوّل كامل
سنبني فئة Counter بسيطة — ليست ودجتًا — من الصفر باستخدام TDD. اختبارات الوحدة البسيطة في Dart تعمل فورًا وتوفر أسرع حلقة تغذية راجعة، مما يجعلها مثالية لتعلم الدورة.
الخطوة 1 — أحمر: أنشئ ملف الاختبار أولًا. الفئة غير موجودة بعد، لذا لن يُترجم الاختبار، وهذا يُحسب فشلًا.
test/counter_test.dart — الاختبار الفاشل الأول
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/counter.dart'; // غير موجود بعد
void main() {
group('Counter', () {
test('يبدأ من الصفر', () {
final counter = Counter();
expect(counter.value, equals(0));
});
});
}
شغّل flutter test. يفشل: "Target of URI doesn't exist: 'counter.dart'". هذه المرحلة الحمراء — الاختبار يُبلّغ بشكل صحيح عن سلوك مفقود.
الخطوة 2 — أخضر: اكتب فقط ما يكفي من كود الإنتاج لإرضاء الاختبار.
lib/counter.dart — التنفيذ الأدنى الذي يجتاز الاختبار
class Counter {
int value = 0;
}
شغّل flutter test مجددًا. يجتاز الاختبار. وصلنا إلى الأخضر.
الخطوة 3 — أعد الهيكلة: الفئة بسيطة حتى الآن، لكن مع إضافة المزيد من الاختبارات ستظهر فرص لتحسين التسمية والتغليف والهيكل. لنضف سلوكين آخرين، كل منهما مدفوع أولًا باختبار فاشل.
test/counter_test.dart — إضافة الزيادة والنقصان
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/counter.dart';
void main() {
group('Counter', () {
late Counter counter;
setUp(() {
counter = Counter(); // نسخة جديدة لكل اختبار
});
test('يبدأ من الصفر', () {
expect(counter.value, equals(0));
});
test('الزيادة ترفع القيمة بمقدار 1', () {
counter.increment();
expect(counter.value, equals(1));
});
test('النقصان يخفض القيمة بمقدار 1', () {
counter.increment();
counter.decrement();
expect(counter.value, equals(0));
});
test('القيمة لا تنخفض عن الصفر', () {
counter.decrement(); // بالفعل عند 0
expect(counter.value, equals(0)); // يجب أن تبقى 0
});
});
}
شغّل الاختبارات بعد إضافة كل اختبار واحدًا تلو الآخر. بعد إضافة اختبار increment: أحمر. نفّذ increment(): أخضر. بعد إضافة اختبار decrement: أحمر. نفّذ decrement(): أخضر. بعد إضافة اختبار الحد الأدنى: أحمر. أضف الحارس: أخضر. أخيرًا، أعد الهيكلة:
lib/counter.dart — بعد دورة TDD الكاملة وإعادة الهيكلة
class Counter {
int _value = 0; // خاص بعد إعادة الهيكلة
int get value => _value;
void increment() => _value++;
void decrement() {
if (_value > 0) _value--;
}
}
جميع الاختبارات الأربعة تبقى خضراء بعد إعادة الهيكلة. الحقل الآن مُغلَّف بشكل صحيح مع getter، وdecrement تطبّق قاعدة العمل التي تمنع انخفاض العداد دون الصفر. حققنا ذلك بأمان لأن الاختبارات اكتشفت أي تراجع فورًا.
TDD للودجات مع WidgetTester
تنطبق نفس الدورة على اختبارات ودجات Flutter. اكتب اختبارًا يضخ ودجتًا ويُؤكد على المخرجات المُقدَّمة، راقبه يفشل، نفّذ الودجت، اجتز اختبارك، ثم أعد هيكلة الودجت بدون خوف.
تنظيم اختبارات TDD في مشاريع Flutter
احرص على الاتفاقيات التالية عند ممارسة TDD في مشروع Flutter:
- عكس هيكل
lib/داخلtest/: إن كان لديكlib/models/cart.dart، يعيش الاختبار فيtest/models/cart_test.dart. - استخدم
setUp()وtearDown()للإعداد المشترك بدلًا من تكرار البناء في كل اختبار. - سمّ كل اختبار كجملة: "يُعيد قائمة فارغة عند عدم إضافة عناصر". الأسماء الجيدة توثيق.
- تأكيد واحد لكل اختبار هو افتراض جيد؛ الاختبار الذي يفحص أشياء كثيرة غير مترابطة صعب التشخيص عند الفشل.
ملخص
TDD في Flutter لا يتعلق بامتلاك اختبارات — كل مشروع احترافي يجب أن يمتلك اختبارات. بل يتعلق بترك الاختبارات تقود التصميم. بكتابة الاختبار أولًا تلتزم بواجهة برمجية عامة قبل كتابة سطر تنفيذ. تحافظ دورة أحمر-أخضر-أعد الهيكلة على التغييرات صغيرة وآمنة، ومجموعة الاختبارات المتنامية توثّق النية، ومرحلة إعادة الهيكلة تبقي قاعدة الكود نظيفة بلا مخاطرة. ابدأ صغيرًا: اختر فئة واحدة أو ودجتًا واحدًا، اكتب اختبارًا فاشلًا واحدًا، اجعله يجتاز، وكرر.