navigationnavigation

اختبار التنقل في Flutter: تأكد من أن المستخدم لا يضيع في الطريق

تخيل أنك فتحت تطبيقًا أنيقًا لتتبع اللياقة. تضغط على زر “ابدأ التمرين”، فتظهر شاشة التحميل… ثم فجأة تبقى هناك، بلا رجعة!
لا زر رجوع، لا انتقال، لا شيء يحدث. 😅

هذه المواقف المربكة تحدث عندما لا يتم اختبار التنقل (Navigation) جيدًا.
فالتنقل هو “الخريطة الداخلية” لتطبيقك — وإذا لم تختبرها، قد يجد المستخدم نفسه تائهًا بين الصفحات.

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


🧩 ما هو اختبار التنقل في Flutter؟

اختبار التنقل هو نوع من اختبارات واجهة المستخدم (Widget Tests) يركّز على التأكد من أن:

  • الشاشات تُعرض في الوقت المناسب.
  • الأزرار والروابط تؤدي إلى الوجهة الصحيحة.
  • أزرار الرجوع والتنقل تعمل كما هو متوقع.

بكلمات بسيطة:

اختبار التنقل هو التحقق من أن المستخدم يمكنه “المشي” داخل التطبيق دون أن يضيع.


لماذا نحتاج لاختباره؟

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

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


نظرة سريعة على نظام التنقل في Flutter

Flutter يستخدم Navigator للتحكم في الانتقال بين الصفحات.
فيمكنك:

  • فتح صفحة جديدة باستخدام:
Navigator.push(context, MaterialPageRoute(builder: (_) => PageB()));
  • العودة إلى الصفحة السابقة بـ:
Navigator.pop(context);
  • أو استخدام نظام المسارات المسماة
(Named Routes): Navigator.pushNamed(context, '/settings');

اختبار هذه العمليات يضمن أن هذه “الرحلات” بين الصفحات تسير بسلاسة.


إعداد اختبار تنقل بسيط

لنبدأ بتطبيق صغير يحتوي على صفحتين:

// page_a.dart
import 'package:flutter/material.dart';
import 'page_b.dart';

class PageA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('الصفحة A')),
      body: Center(
        child: ElevatedButton(
          key: ValueKey('toPageB'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => PageB()),
            );
          },
          child: Text('اذهب إلى B'),
        ),
      ),
    );
  }
}

// page_b.dart
import 'package:flutter/material.dart';

class PageB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('الصفحة B')),
      body: Center(child: Text('مرحباً بك في الصفحة B')),
    );
  }
}

الآن نريد التأكد أن الضغط على الزر في الصفحة A ينقلك فعلًا إلى الصفحة B.


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

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'page_a.dart';

void main() {
  testWidgets('يجب الانتقال من الصفحة A إلى الصفحة B عند الضغط على الزر', (tester) async {
    await tester.pumpWidget(MaterialApp(home: PageA()));

    // التحقق من الصفحة الحالية
    expect(find.text('الصفحة A'), findsOneWidget);
    expect(find.text('الصفحة B'), findsNothing);

    // الضغط على الزر
    await tester.tap(find.byKey(ValueKey('toPageB')));
    await tester.pumpAndSettle();

    // التحقق من الانتقال
    expect(find.text('الصفحة B'), findsOneWidget);
  });
}

في هذا الاختبار:

  • بدأنا بالصفحة A.
  • نفذنا حدث الضغط على الزر.
  • استخدمنا pumpAndSettle() لانتظار اكتمال الحركة.
  • ثم تحققنا من وجود النص الخاص بالصفحة B.

وبهذا نكون تأكدنا أن التنقل يعمل كما يجب!


اختبار العودة (Back Navigation)

يمكننا أيضًا التأكد من أن زر الرجوع يعيدنا للشاشة السابقة:

await tester.pageBack();
await tester.pumpAndSettle();

expect(find.text('الصفحة A'), findsOneWidget);

pageBack() يحاكي الضغط على زر الرجوع المدمج في النظام.
بهذا نضمن أن المستخدم يمكنه العودة بسلاسة دون أي كسر في تدفق التطبيق.


اختبار المسارات المسماة (Named Routes)

إذا كنت تستخدم نظام المسارات، فيمكنك اختبارها بالطريقة نفسها:

MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => HomePage(),
    '/settings': (context) => SettingsPage(),
  },
);

والاختبار:

testWidgets('يجب الانتقال إلى صفحة الإعدادات', (tester) async {
  await tester.pumpWidget(MaterialApp(
    initialRoute: '/',
    routes: {
      '/': (_) => HomePage(),
      '/settings': (_) => SettingsPage(),
    },
  ));

  await tester.tap(find.text('إعدادات'));
  await tester.pumpAndSettle();

  expect(find.text('صفحة الإعدادات'), findsOneWidget);
});

نصائح احترافية لاختبار التنقل

  1. استخدم مفاتيح ثابتة (Keys) لجميع أزرار التنقل — لتسهيل العثور عليها في الاختبار.
  2. اختبر التدفق الكامل للمستخدم (من البداية حتى الصفحة النهائية).
  3. استخدم pumpAndSettle() دائمًا بعد أي عملية تنقل.
  4. اختبر الحالات السلبية: مثل الضغط على زر أثناء التحميل أو غياب المسار المطلوب.
  5. ادمج اختبارات التنقل مع اختبارات الأداء لمعرفة سرعة الانتقال بين الشاشات.

اختبار التنقل في بيئة التكامل (Integration Tests)

عند اختبار التطبيق كاملًا، يمكنك كتابة سيناريوهات تنقل طويلة:

await tester.tap(find.text('ابدأ'));
await tester.pumpAndSettle();

await tester.tap(find.text('التالي'));
await tester.pumpAndSettle();

await tester.tap(find.text('إنهاء'));
await tester.pumpAndSettle();

expect(find.text('تم بنجاح!'), findsOneWidget);

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


الخلاصة

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

✨ تذكّر: الواجهة قد تبهج المستخدم، لكن التنقل السليم هو ما يجعله يبقى.


By احمد علي

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

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *