اختبارات اللقطات للتطبيقات المحمولة: كيف تعمل، الأدوات والأمثلة

المؤلف: IT Sectr نُشر: 2026-04-07 وقت القراءة: 9 دق

اختبار اللقطات هو أسلوب للتحقق الآلي من واجهة المستخدم، حيث تتم مقارنة الحالة الحالية للشاشة مع صورة مرجعية (لقطة) تم حفظها في تشغيل الاختبار السابق. يتم تسجيل أي تباين بصري كتغيير يتطلب تأكيد المطور. على عكس اختبارات واجهة المستخدم التي تتحقق من وجود العناصر، تكتشف اختبارات اللقطات التغييرات على مستوى البكسل — الإزاحات والانحرافات اللونية ومشاكل التخطيط. وفقًا لـ Android Developers, 2024، تكتشف اختبارات اللقطات ما يصل إلى 30% من الانحدارات البصرية التي تفوتها اختبارات واجهة المستخدم التقليدية، مما يجعلها أداة لا غنى عنها للحفاظ على واجهة متسقة.

الخلاصة

  • اختبار اللقطات — أسلوب لمقارنة العرض الحالي للشاشة مع صورة مرجعية لاكتشاف الانحدارات البصرية.
  • Paparazzi — مكتبة لأندرويد تقوم بعرض مكونات Compose وView في بيئة اختبار دون تشغيل محاكي.
  • Shot — إطار عمل لأندرويد يلتقط لقطات شاشة حقيقية في اختبارات Instrumentation مع دعم دقات مختلفة.
  • SnapshotTesting — مكتبة من Point-Free لنظام iOS تدعم مقارنة ليس فقط الصور ولكن أيضًا النصوص وJSON وبيانات Core Data.
  • تحديث المرجعيات — أمر لمرة واحدة بعد تغيير مقصود في الواجهة، لاستبدال اللقطات القديمة بأخرى جديدة.

ما هو اختبار اللقطات؟

اختبار اللقطات (snapshot testing) هو أسلوب يقوم فيه الاختبار بعرض مكون واجهة المستخدم، ويحفظ الصورة الناتجة كمرجع، وفي التشغيلات اللاحقة يقارن العرض الحالي بهذا المرجع. إذا تطابقت الصور — ينجح الاختبار. إذا تم العثور على اختلافات — يفشل الاختبار، ويتلقى المطور صورة الفرق مع إبراز البكسلات المتغيرة. تم اقتباس هذا الأسلوب من تطوير الويب (Jest snapshots) وتم تكييفه للمنصات المحمولة.

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

وفقًا لاستطلاع Mobile DevOps Summit 2023، فإن الفرق التي تستخدم اختبارات اللقطات بالإضافة إلى اختبارات واجهة المستخدم التقليدية تقلل عدد العيوب البصرية في الإصدارات بنسبة 40%. هذا الأسلوب فعال بشكل خاص في المشاريع التي تحتوي على أنظمة تصميم وهياكل قائمة على المكونات، حيث يمكن أن يؤثر تغيير مكون أساسي واحد على عشرات شاشات التطبيق.

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

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

سرعة التنفيذ تختلف أيضًا. اختبارات واجهة المستخدم تعمل على محاكي أو جهاز حقيقي، وتتطلب تحميل التطبيق بالكامل، وتستغرق من 10 ثوانٍ إلى دقيقة لكل سيناريو. اختبارات اللقطات باستخدام مكتبات مثل Paparazzi تعرض المكونات في بيئة افتراضية دون تشغيل محاكي، مما يقلل وقت الاختبار إلى 100–500 مللي ثانية. مجموعة كاملة من اختبارات اللقطات (50–100 شاشة) يتم تنفيذها في 2–5 دقائق بدلاً من 30–60 دقيقة لمجموعة مماثلة من اختبارات واجهة المستخدم.

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

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

في أندرويد، الأدوات الرئيسية هي Paparazzi وShot. Paparazzi من Cash App تقوم بعرض المكونات في بيئة اختبار JVM بدون محاكي، باستخدام تخطيط الجاذبية Layoutlib. Shot من Karumi تلتقط لقطات شاشة من Instrumentation على جهاز حقيقي أو محاكي وتقارنها بالمرجعيات عبر مكتبة AShot، مع مراعاة الاختلافات في الدقة وكثافة البكسلات.

Paparazzi لأندرويد

Paparazzi لا يتطلب تشغيل محاكي — يتم العرض على JVM عبر Layoutlib، مما يوفر سرعة مماثلة لاختبارات الوحدة. المكتبة تدعم كلاً من نظام View وJetpack Compose. لـ Compose، يُستخدم المُعدِّل paparazzi.snapshot { MyComposable() }. تُخزن المرجعيات في src/test/snapshots ويتم مقارنتها تلقائيًا في كل تشغيل. يتم تكوين أقصى نسبة اختلاف عبر maxPercentDifference.

SnapshotTesting لنظام iOS

SnapshotTesting من Point-Free تدعم مقارنة ليس فقط UIImage ولكن أيضًا السلاسل النصية وJSON وData ومخازن Core Data بالكامل. هذا يجعلها أداة متعددة الاستخدامات ليس فقط للقطات واجهة المستخدم ولكن أيضًا للتحقق من تسلسل وفك تشفير استجابات JSON. لـ SwiftUI، يُستخدم امتداد assertSnapshot مع المُعدِّل .image(on: .iPhone13). استراتيجية record: true تنشئ المرجعيات في أول تشغيل.

الأساليب عبر المنصات

لـ React Native، الحل الشائع هو react-native-testing-library مع jest-image-snapshot. يتم نقل أسلوب الويب لاختبار اللقطات إلى البيئة المحمولة عبر عرض المكونات في بيئة Node.js متبوعًا بمقارنة لقطات JSON من DOM الافتراضي. هذا الأسلوب أسرع من الأصلي لكنه أقل دقة — فهو لا يأخذ في الاعتبار خصائص عرض الخطوط والمكونات النظامية لكل منصة. لـ Flutter، يُستخدم اختبار golden عبر toolkit goldens.

أمثلة كود لاختبارات اللقطات

دعنا نلقي نظرة على اختبارات اللقطات لأندرويد (Paparazzi) ونظام iOS (SnapshotTesting). كلا المثالين يتحققان من مظهر أحد المكونات — بطاقة مستخدم مع صورة رمزية واسم وحالة. يقوم الاختبار بعرض المكون ببيانات اختبار ويقارن النتيجة بصورة مرجعية مخزنة في المستودع.

أندرويد: اختبار لقطة مع Paparazzi

يستخدم Paparazzi التعليق التوضيحي @Test وطريقة snapshot() لالتقاط العرض. المرجعيات تُحفظ في مجلد src/test/snapshots ويتم تحميلها تلقائيًا في التشغيل التالي للمقارنة.

kotlin
class UserCardSnapshotTest {

    @get:Rule
    val paparazzi = Paparazzi(
        theme = "Theme.MyApp",
        maxPercentDifference = 0.1
    )

    @Test
    fun userCard_defaultState() {
        val card = UserCard(
            name = "Alice Johnson",
            status = "Online",
            avatarUrl = "https://example.com/avatar.png"
        )
        paparazzi.snapshot(card)
    }

    @Test
    fun userCard_offlineState() {
        val card = UserCard(
            name = "Bob Smith",
            status = "Offline",
            avatarUrl = null
        )
        paparazzi.snapshot(card, name = "user_card_offline")
    }
}

iOS: اختبار لقطة مع SnapshotTesting

SnapshotTesting تستخدم المُعدِّل .snapshot() داخل assertSnapshot. المكتبة تحدد التنسيق تلقائيًا — UIImage لـ UIView، String للنص، Data للبيانات الثنائية.

swift
import SnapshotTesting
import XCTest

class UserCardSnapshotTests: XCTestCase {
    func testUserCardDefaultState() {
        let card = UserCardView(
            name: "Alice Johnson",
            status: "Online",
            avatarURL: URL(string: "https://example.com/avatar.png")
        )
        let controller = UIHostingController(rootView: card)
        assertSnapshot(matching: controller, as: .image(on: .iPhone13))
    }

    func testUserCardOfflineState() {
        let card = UserCardView(
            name: "Bob Smith",
            status: "Offline",
            avatarURL: nil
        )
        assertSnapshot(matching: card, as: .image(on: .iPhone13))
    }
}

سير عمل اختبار اللقطات

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

في التشغيلات اللاحقة، تعمل الاختبارات في وضع المقارنة: تتم مقارنة كل عرض جديد بالمرجع. إذا تم العثور على اختلافات، يتم إنشاء صورة الفرق: يتم إبراز البكسلات المطابقة للمرجع باللون الأخضر، والمختلفة باللون الأحمر. يدرس المطور صورة الفرق ويتخذ قرارًا: إذا كان التغيير متوقعًا (تغيير تصميم مقصود)، يتم تحديث المرجع بأمر record؛ إذا كان غير متوقع — يتم إصلاح الخلل. تحديث المرجعيات يتم بأمر واحد: لـ Paparazzi هو `./gradlew recordPaparazzi`، لـ SnapshotTesting — `assertSnapshot(record: true)`.

وفقًا لـ Spotify Engineering Blog (2022)، الفرق التي تستخدم سير العمل الموصوف تقضي في المتوسط دقيقتين لكل اختبار لتحليل صور الفرق. مع مجموعة من 50 اختبار لقطة، تستغرق دورة تحديث المرجعيات الكاملة 15–20 دقيقة، وهي أسرع بكثير من التحقق اليدوي من التغييرات البصرية عبر 50 شاشة.

قيود وأنماط مضادة لاختبارات اللقطات

اختبارات اللقطات لها قيود أساسية. الحساسية للبيئة: قد يتم عرض نفس المكون بشكل مختلف على إصدارات مختلفة من نظام التشغيل وكثافات شاشة وتكوينات خطوط. المرجعيات التي تم إنشاؤها على جهاز واحد قد تختلف عن العرض على خادم CI. الحل هو استخدام معايير بيئة ثابتة: إصدار محدد من Layoutlib لـ Paparazzi أو نموذج جهاز دقيق لـ SnapshotTesting.

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

وفقًا لـ Better Engineering Blog (2023)، تحقق اختبارات اللقطات أكبر فائدة عند تغطية مكونات نظام التصميم والشاشات الرئيسية في الحالات الأساسية — الفارغة والمملوءة والخطأ والحدودية. تغطية الرسوم المتحركة والحالات الديناميكية عبر اختبارات اللقطات غير فعالة بسبب الطبيعة غير الحتمية للطوابع الزمنية في العرض — لمثل هذه السيناريوهات، يكون تسجيل الفيديو أو فحص ضمان الجودة اليدوي أكثر ملاءمة.

الأسئلة الشائعة

هل اختبارات اللقطات تحل محل اختبارات واجهة المستخدم؟

لا، اختبارات اللقطات تتحقق من المظهر البصري، بينما اختبارات واجهة المستخدم تتحقق من سلوك الواجهة. الاستراتيجية المثلى هي الجمع بين كلا النهجين: اللقطات للانحدار البصري، واختبارات واجهة المستخدم للسيناريوهات والتنقل. اللقطات تجيب على «هل يبدو صحيحًا؟»، واختبارات واجهة المستخدم تجيب على «هل يعمل صحيحًا؟».

كم مرة يجب تحديث الصور المرجعية؟

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

ما المكونات التي يجب تغطيتها باختبارات اللقطات؟

في المقام الأول، مكونات نظام التصميم — الأزرار والبطاقات وحقول الإدخال والنوافذ المشروطة. ثم الشاشات الرئيسية في الحالات الأساسية. لا تختبر باللقطات الرسوم المتحركة وWebView والخرائط والشاشات ذات المحتوى الديناميكي — فاللقطات تعطي إخفاقات خاطئة بسبب عدم الحتمية.

كيفية التعامل مع الإخفاقات الخاطئة الناتجة عن إصدارات نظام التشغيل المختلفة؟

استخدم نفس مستوى API لكل من وضعي التسجيل والاختبار. لـ Paparazzi، حدد إصدارًا محددًا من Layoutlib في التكوين. لـ SnapshotTesting، ثبت نموذج الجهاز. المرجعيات التي تم إنشاؤها على Android 14 قد تختلف عن العرض على Android 12 بسبب التغييرات في خطوط النظام وسمة Material.

اختبارات اللقطات في CI — كيف يتم الإعداد؟

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

الملخص

  • اختبار اللقطات يقارن العرض الحالي للمكون بصورة مرجعية، ويكتشف تغييرات البكسل والانحدارات البصرية.
  • Paparazzi — أداة سريعة لأندرويد بدون محاكي؛ SnapshotTesting — مكتبة متعددة الاستخدامات لنظام iOS من Point-Free.
  • اختبارات اللقطات لا تحل محل اختبارات واجهة المستخدم — بل تكملها: اللقطات للظاهر، واختبارات واجهة المستخدم للسلوك.
  • وضع التسجيل ينشئ الصور المرجعية؛ وضع التحقق يقارن العرض الحالي بها ويولد الفروق عند الاختلافات.
  • مكونات نظام التصميم هي هدف ذو أولوية لاختبارات اللقطات، لأن تغييرها يؤثر على شاشات متعددة.
  • كل فرق يتطلب قرارًا واعيًا من المطور — الاستبدال التلقائي للمرجعيات دون تحليل يلغي قيمة الاختبارات.
  • الصور المرجعية يتم إيداعها في المستودع وتكون جزءًا من قاعدة الكود جنبًا إلى جنب مع كود مصدر الاختبارات.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا