Functional Testing عملياً - كيف نختبر الـ Business Logic؟

مقال مجاني 17 دقيقة

مقدمة

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

في الدرس الماضي حكينا عن الفرق بين Functional Testing و Non-Functional Testing، وفهمنا إنه Functional Testing يختبر شو النظام يفعل.

لكن السؤال: كيف نختبر الـ Functional؟ ومن وين؟

اليوم راح نحكي عن الطرق المختلفة لاختبار الـ Business Logic والـ Requirements، وكيف نتأكد إنه النظام مش فقط "يعمل" - بل "يعمل صح حسب المتطلبات"!


الأهداف التعليمية

بنهاية هذا الدرس، راح تكون قادراً على:

  • تفهم ما المقصود بـ Business Logic وليش مهم نختبره
  • تتعرف على الطرق المختلفة لاختبار الـ Functional (UI, API, Database)
  • تعرف متى تستخدم كل طريقة وليش
  • تحدد الأشياء المهمة التي لازم تختبرها (User Roles, Error Messages, Integration)
  • تطبق أمثلة عملية على تطبيقات حقيقية

ماذا نختبر بالـ Functional Testing؟

Business Logic - المنطق التجاري

Business Logic هو القواعد التي تحكم كيف النظام يعمل.

مش فقط "Login يعمل" ← بل "Login يعمل حسب القواعد الصحيحة"

Business Logic هو "العقل" اللي ورا النظام - القوانين والقواعد التي تحدد ما يصير وما ما يصير.

أمثلة واقعية على Business Logic

مثال 1: Amazon - السلة (Cart)

  • عندما تضيف منتج، السعر الكلي يتحدث ← Business Logic
  • لو عندك Discount Code، السعر ينزل ← Business Logic
  • لو المنتج Out of Stock، لا تستطيع أن تشتريه ← Business Logic
  • لو طلبت فوق $50، Shipping مجاني ← Business Logic

مثال 2: Netflix - الاشتراكات

  • Free User يرى لكن SD ← Business Logic
  • Premium User يرى 4K ← Business Logic
  • تستطيع أن تشغل على جهازين بنفس الوقت (حسب الاشتراك) ← Business Logic
  • بعد شهر، الاشتراك بيتجدد تلقائياً ← Business Logic

مثال 3: Instagram - الخصوصية

  • Private Account ← لكن الـ Followers يشوفوا Posts ← Business Logic
  • Public Account ← الكل يرى Posts ← Business Logic
  • Blocked User لا يستطيع يشوف أي شي ← Business Logic

خلينا واضحين: نختبر القواعد التي تحكم كيف النظام يتصرف!


الطرق المختلفة لاختبار الـ Functional

في 3 طرق رئيسية نقدر نختبر فيهم الـ Business Logic:

1. من خلال الـ UI (User Interface)

الطريقة التقليدية - نفتح التطبيق ونضغط ونجرب!

كيف تشتغل؟

  • نفتح الموقع أو التطبيق
  • بنتصرف مثل المستخدم العادي
  • نضغط على الأزرار ونملي الحقول
  • نرى النتيجة على الشاشة

مثال عملي: Amazon

خطوات الاختبار:

  1. نفتح Amazon.com 🌐
  2. نبحث عن منتج (مثلاً: "iPhone 15") 🔍
  3. نختار المنتج ونضغط "Add to Cart" 🛒
  4. نروح على السلة ونتأكد إنه المنتج موجود ✅
  5. نضغط "Proceed to Checkout" 💳
  6. نملي بيانات الدفع 📝
  7. نضغط "Place Order" 📦
نصيحة
ميزة: سهلة ومباشرة - نرى بالضبط ما المستخدم راح يشوفه! عيب: بطيئة - لازم ننتظر تحميل الصفحات، الصور، الخ.

2. من خلال الـ API

الطريقة السريعة - بدلاً من أن نضغط على الـ UI، نبعث requests مباشرة للـ Backend!

كيف تشتغل؟

  • نبعث HTTP Requests (GET, POST, PUT, DELETE) مباشرة للسيرفر
  • بنستقبل Responses (JSON عادةً)
  • لا يوجد حاجة نستنى تحميل الصفحات أو الصور
  • أسرع بكثير من الـ UI!

مثال عملي: Instagram - عمل Like

بدلاً من أن:

  1. نفتح Instagram 📱
  2. ندور على Post معين 🔍
  3. نضغط على القلب ❤️
  4. ننتظر التطبيق يحمّل ⏳

نقدر:

  • نبعث POST Request مباشرة: POST /api/posts/12345/like
  • ونستقبل Response: { "status": "success", "likes": 101 }
  • كل هذا في أقل من ثانية! ⚡

API Testing موضوع كبير! راح يكون عنا قسم كامل عنه لاحقاً في الكورس.

هسا لكن بدنا نفهم إنه في طريقة أسرع من الـ UI!


3. من خلال الـ Database

الطريقة الأكيدة - نتحقق من البيانات مباشرة بالـ Database!

كيف تشتغل؟

  • بنتصل بالـ Database مباشرة
  • نفعل SQL Queries حتى نشوف البيانات
  • نتأكد إنه البيانات انحفظت صح مش فقط "ظاهرة صح"

ليش نحتاج Database Testing؟

أحياناً الـ UI يقول "Success!" لكن البيانات ما انحفظت فعلياً! 😱

مثال 1: تسجيل مستخدم جديد

على الـ UI:

  • بنملي الـ Form (Name, Email, Password)
  • نضغط "Register"
  • الموقع يقول: "Registration Successful!" ✅

لكن هل فعلاً انحفظ؟

على الـ Database:

SELECT * FROM users WHERE email = 'ahmad@example.com';

نتأكد إنه:

  • الـ User موجود في الـ Database ✅
  • الـ Name صحيح ✅
  • الـ Email صحيح ✅
  • الـ Password متشفر (Hashed) ✅
  • الـ Created Date صحيح ✅

مثال 2: Amazon - Order

على الـ UI:

  • بنشتري منتج
  • الموقع يقول: "Order Placed!" ✅

على الـ Database:

SELECT * FROM orders WHERE user_id = 123 ORDER BY created_at DESC LIMIT 1;

نتأكد إنه:

  • الـ Order موجود ✅
  • الـ Total Price صحيح ✅
  • الـ Items موجودة (iPhone, Quantity: 1) ✅
  • الـ Shipping Address صحيح ✅
  • الـ Status = "Pending" ✅
تحذير
مهم جداً: لا تثق بالـ UI بنفسه! أحياناً الـ UI بيكذب! 😅 دايماً تحقق من الـ Database حتى تكون 100% متأكد.

مقارنة بين الطرق الثلاثة

الطريقة السرعة الدقة متى نستخدمها؟
UI بطيئة 🐌 تختبر تجربة المستخدم عندما بدنا نتأكد من الـ User Experience
API سريعة ⚡ تختبر الـ Backend Logic عندما بدنا نختبر بسرعة ونركز على الـ Business Logic
Database سريعة ⚡ الأدق - الحقيقة المطلقة 💯 عندما بدنا نتأكد 100% إنه البيانات انحفظت صح
نصيحة
الأفضل: نستخدم الطرق الثلاثة مع بعض! - UI ← للتأكد من تجربة المستخدم - API ← للسرعة والتفاصيل التقنية - Database ← للتأكد من البيانات الفعلية كل طريقة تكشف مشاكل مختلفة!

ما الأشياء التي نختبرها؟

الآن نعرف من وين نختبر (UI, API, Database)، خلينا نحكي عن شو نختبر!

1. User Roles (صلاحيات المستخدمين)

الأنظمة عادةً فيها أنواع مختلفة من المستخدمين، وكل نوع إله صلاحيات مختلفة.

مثال 1: Instagram

Admin:

  • يستطيع يحذف أي Post (حتى لو مش تبعه) 🗑️
  • يستطيع يمنع (Ban) أي User 🚫
  • يرى Statistics لكل التطبيق 📊

User عادي:

  • يستطيع يحذف لكن Posts تبعه 🗑️
  • لا يستطيع يمنع حد 🚫
  • يرى لكن Statistics تبعته 📊

اختبارنا:

  • Admin يستطيع يحذف post لمستخدم ثاني؟ ✅
  • User عادي لا يستطيع يحذف post لمستخدم ثاني؟ ✅
  • User عادي لو حاول، يطلعله Error Message مناسب؟ ✅

مثال 2: Netflix

Free User:

  • يرى لكن SD (480p) 📺
  • يرى إعلانات 📢
  • يستطيع يشغل على جهاز واحد لكن 📱

Premium User:

  • يرى 4K (2160p) 🎬
  • بدون إعلانات 🚫
  • يستطيع يشغل على 4 أجهزة بنفس الوقت 📱📱📱📱

اختبارنا:

  • Premium User يرى 4K فعلاً؟ ✅
  • Free User لا يشوف 4K؟ ✅
  • Free User لو حاول يشغل على جهازين، يطلعله Error؟ ✅
تحذير
خطأ شائع: كثير Testers يختبروا لكن User عادي وينسوا الـ Roles الثانية! لازم نختبر كل User Role!

2. Error Messages (رسائل الخطأ)

مش فقط نختبر الـ Happy Path! (يعني عندما كل شي صح)

لازم أيضاً نختبر Unhappy Paths - عندما المستخدم يفعل غلط أو في مشكلة!

Error Messages الصحيحة مقابل السيئة

سيئة ❌:

  • "Error"
  • "Something went wrong"
  • "Error 500"
  • "Failed"

جيدة ✅:

  • "Password must be at least 8 characters"
  • "Email already exists. Please use a different email or login."
  • "Credit card declined. Please check your card details."
  • "Username can only contain letters and numbers"

مثال 1: Amazon - Login

السيناريو: المستخدم يدخل Password غلط

رسالة سيئة ❌:

Login failed

رسالة جيدة ✅:

Incorrect email or password. Please try again.

مثال 2: Facebook - Registration

السيناريو: المستخدم يسجل بإيميل موجود مسبقاً

رسالة سيئة ❌:

Error

رسالة جيدة ✅:

This email is already registered. Please login or use a different email.
نصيحة
رسالة الخطأ الجيدة: 1. توضح ما المشكلة بوضوح 📝 2. تساعد المستخدم يحل المشكلة 🛠️ 3. مش مخيفة أو تقنية زيادة 😊 تذكر: المستخدم مش مطور! لازم يفهم ما الغلط!

3. System Integration (التكامل مع أنظمة أخرى)

التطبيق مش بنفسه! يتكلم مع أنظمة ثانية كثيرة.

لازم نتأكد إنه التكامل شغال صح!

مثال 1: Amazon - Payment Gateway

Amazon يتكلم مع:

  • Visa / Mastercard 💳
  • PayPal 💰
  • Apple Pay 🍎
  • Google Pay 📱

اختباراتنا:

  • عندما المستخدم يدفع بـ Visa، الدفع يمشي؟ ✅
  • عندما الـ Card مرفوض، Amazon يستقبل Response صحيح؟ ✅
  • الـ Error Message واضح للمستخدم؟ ✅
  • المبلغ الذي راح لـ Visa هو نفسه اللي في Amazon؟ ✅

مثال 2: Uber - Google Maps

Uber يتكلم مع:

  • Google Maps (للموقع والخريطة) 🗺️
  • Payment Gateways (للدفع) 💳
  • SMS Gateway (لإرسال كود التحقق) 📱

اختباراتنا:

  • عندما نطلب Uber، الخريطة تظهر صح؟ ✅
  • الـ Driver Location يتحدث real-time؟ ✅
  • لو Google Maps عطلان، في Fallback plan؟ ✅

مثال 3: أي تطبيق - Email Service

التطبيقات تبعث Emails:

  • Welcome Email عند التسجيل 📧
  • Reset Password Email 🔐
  • Order Confirmation Email 📦

اختباراتنا:

  • الـ Email يوصل فعلاً؟ ✅
  • المحتوى صحيح (اسم المستخدم، Order Details)؟ ✅
  • الـ Links بالإيميل شغالة (Reset Password link)؟ ✅
  • الإيميل ما راح على Spam؟ ✅

Integration Testing يكشف مشاكل كثيرة لا تظهر عندما نختبر التطبيق بنفسه!

النظام ممكن يكون شغال 100%، لكن التكامل مع الأنظمة الثانية مش شغال!


مثال عملي شامل: Amazon Order

خلينا ناخذ مثال كامل ونطبق كل لا تعلمناه!

السيناريو: مستخدم بيشتري iPhone من Amazon

1. اختبار من خلال الـ UI

الخطوات:

  1. نفتح Amazon.com 🌐
  2. نسجل دخول (Login) 👤
  3. نبحث عن "iPhone 15 Pro" 🔍
  4. نختار المنتج ونضغط "Add to Cart" 🛒
  5. نروح على Cart ونتأكد إنه المنتج موجود ✅
  6. نضغط "Proceed to Checkout" 💳
  7. نختار Shipping Address 📍
  8. نختار Payment Method (Visa) 💳
  9. نضغط "Place Order" 📦
  10. نشوف "Order Confirmation" ✅

اختباراتنا:

  • الـ UI سهلة الاستخدام؟ ✅
  • الصور والمعلومات واضحة؟ ✅
  • الـ Total Price صحيح (المنتج + Shipping)؟ ✅
  • الـ Confirmation Message واضح؟ ✅

2. اختبار من خلال الـ API

بدل كل الخطوات التي فوق، نقدر نبعث API Requests مباشرة:

POST /api/cart/add
Body: { "product_id": "12345", "quantity": 1 }
Response: { "status": "success", "cart_total": "$999.00" }

POST /api/orders/create
Body: {
  "cart_id": "67890",
  "shipping_address": "...",
  "payment_method": "visa"
}
Response: {
  "status": "success",
  "order_id": "ORD-111222",
  "total": "$999.00"
}

اختباراتنا:

  • الـ API يُرجع Status Code صحيح (200 OK)? ✅
  • الـ Response فيها كل البيانات المطلوبة؟ ✅
  • الـ Total Price محسوب صح؟ ✅
  • لو في خطأ، الـ Error Response واضح؟ ✅

ميزة الـ API: أسرع بكثير! نقدر نختبر مئات Scenarios في دقائق! ⚡


3. اختبار من خلال الـ Database

بعد أن نعمل Order، نروح على الـ Database ونتأكد:

-- نتأكد إنه الـ Order موجود
SELECT * FROM orders WHERE order_id = 'ORD-111222';

-- نتأكد من التفاصيل
SELECT * FROM order_items WHERE order_id = 'ORD-111222';

-- نتأكد من المبلغ
SELECT total, tax, shipping_fee FROM orders WHERE order_id = 'ORD-111222';

-- نتأكد من الـ Status
SELECT status FROM orders WHERE order_id = 'ORD-111222';

اختباراتنا:

  • الـ Order موجود في الـ Database؟ ✅
  • الـ Product ID صحيح (iPhone 15 Pro)? ✅
  • الـ Quantity صحيح (1)? ✅
  • الـ Total Price صحيح ($999.00)? ✅
  • الـ Shipping Address محفوظ صح؟ ✅
  • الـ Status = "Pending"? ✅
  • الـ Created Date صحيح؟ ✅

4. اختبار User Roles

Admin User:

  • يستطيع يشوف كل Orders (لكل المستخدمين) 👀
  • يستطيع يلغي أي Order 🗑️
  • يستطيع يعدل Status (Pending → Shipped) 📦

Regular User:

  • يستطيع يشوف لكن Orders تبعه 👀
  • يستطيع يلغي لكن Orders تبعه (قبل Shipping) 🗑️
  • لا يستطيع يعدل Status ❌

اختباراتنا:

  • Admin يرى كل Orders؟ ✅
  • User عادي يرى لكن orders تبعه؟ ✅
  • User عادي لو حاول يشوف order لمستخدم ثاني، يطلعله Error؟ ✅

5. اختبار Error Messages

سيناريوهات Unhappy Path:

السيناريو 1: Credit Card مرفوض

  • الرسالة: "Payment declined. Please check your card details or use a different payment method." ✅
  • مش: "Error 500" ❌

السيناريو 2: المنتج Out of Stock

  • الرسالة: "This item is currently out of stock. Please check back later or choose a different product." ✅
  • مش: "Failed" ❌

السيناريو 3: Shipping Address غلط

  • الرسالة: "Invalid shipping address. Please provide a complete address with ZIP code." ✅
  • مش: "Error" ❌

6. اختبار System Integration

التكاملات التي لازم نختبرها:

أ. Payment Gateway (Visa)

  • Amazon يبعث Payment Request لـ Visa ✅
  • Visa يُرجع Response (Approved / Declined) ✅
  • لو Approved، الـ Order Status يحدث "Confirmed" ✅
  • لو Declined، الـ Error Message واضح للمستخدم ✅

ب. Email Service

  • بعد Order، المستخدم يستقبل Confirmation Email ✅
  • الإيميل فيه Order Details صحيحة (Order ID, Total, Items) ✅
  • فيه Link لـ Track Order ✅

ج. Shipping Company

  • Amazon يبعث Shipping Request ✅
  • Shipping Company يُرجع Tracking Number ✅
  • المستخدم يستطيع يتتبع Order ✅

ليش نستخدم طرق مختلفة؟

كل طريقة تكشف مشاكل مختلفة!

مثال واقعي: Bug في الـ Total Price

المشكلة: المستخدم يرى Total Price غلط!

اختبار UI:

  • الـ UI يعرض Total = $999.00 ✅
  • يظهر إنه كل شي صح! ✅

لكن عندما نختبر Database:

SELECT total FROM orders WHERE order_id = 'ORD-111222';
-- Result: $900.00 ❌

المشكلة: الـ UI يحسب صح، لكن الـ Backend يحفظ رقم غلط!

لو ما اختبرنا الـ Database، كان ما اكتشفنا المشكلة! 🐛

مثال ثاني: Bug في الـ Discount

السيناريو: في Discount Code "SAVE10" لازم ينزل 10%

اختبار UI:

  • الـ UI يعرض "Discount: $99.90" ✅
  • الـ Total بيقل من $999 لـ $899.10 ✅

اختبار API:

POST /api/cart/apply-discount
Body: { "code": "SAVE10" }
Response: { "discount": "$99.90", "total": "$899.10" }
  • الـ API يُرجع أرقام صحيحة! ✅

اختبار Database:

SELECT discount_code, discount_amount FROM orders WHERE order_id = 'ORD-111222';
-- discount_code: NULL
-- discount_amount: 0.00

المشكلة: الـ UI والـ API شغالين صح، لكن الـ Discount ما انحفظ بالـ Database! ❌

الـ Database لا يكذب! كل طريقة تكشف شي مختلف.


نصائح عملية

1. ابدأ بالـ UI حتى تفهم الـ Flow

قبل أن تبدأ تختبر بالـ API أو Database، افتح التطبيق واستخدمه!

نصيحة
لازم تفهم كيف المستخدم العادي راح يستخدم النظام. هذا يساعدك تعرف ما لازم تختبره وما الـ Scenarios المهمة.

مثال:

  • افتح Amazon واشتري منتج (حتى لو Test Environment)
  • شوف كل الخطوات التي تمر فيها
  • لاحظ الرسائل، الـ UI، الـ Flow
  • بعد ذلك ابدأ اكتب Test Cases

2. استخدم API عندما تريد أن تختبر بسرعة

بعد لا تفهم الـ Flow، استخدم الـ API للاختبارات السريعة!

ليش؟

  • أسرع بكثير من الـ UI ⚡
  • لا تحتاج تستنى تحميل الصفحات 🚀
  • تقدر تختبر مئات Scenarios بدقائق 💪
  • سهل تعمل Automation 🤖

مثال:

  • بدل لا تضيف 100 منتج من الـ UI (راح ياخذ ساعة!)
  • ابعث 100 API Request (راح ياخذ دقيقة!) ⚡

3. تحقق من Database عندما تريد تتأكد 100%

دايماً تحقق من الـ Database للـ Critical Operations!

Critical Operations:

  • User Registration 👤
  • Payments 💰
  • Orders 📦
  • Password Changes 🔐
  • Delete Account 🗑️
تحذير
لا تثق بالـ UI أو API لحالهم! أحياناً بيقولوا "Success" لكن البيانات ما انحفظت!

مثال:

UI: "Registration Successful!" ✅
API: { "status": "success" } ✅
Database: SELECT * FROM users WHERE email = 'ahmad@example.com'; → Empty! ❌

4. لا تنسى تختبر كل User Role

خطأ شائع: Testers يختبروا لكن User Role واحد!

لازم تختبر:

  • Admin ✅
  • Regular User ✅
  • Premium User ✅
  • Guest User (لو موجود) ✅

وأيضاً:

  • User عادي لا لازم يقدر يعمل Admin actions! 🚫
  • Guest User لا لازم يقدر يوصل لـ Premium features! 🚫

5. اختبر Error Messages - المستخدم لازم يفهم ما الغلط!

لا تختبر لكن Happy Path!

اختبر:

  • Wrong Password ✅
  • Email Already Exists ✅
  • Invalid Input ✅
  • Out of Stock ✅
  • Payment Declined ✅
  • Network Error ✅

وتأكد إنه Error Messages:

  • واضحة ومفهومة 📝
  • تساعد المستخدم يحل المشكلة 🛠️
  • مش مخيفة أو تقنية زيادة 😊

تمرين عملي

خلينا نطبق! اختار تطبيق من اللي تستخدمه (مثلاً: Talabat, Careem, Noon) وحاول:

1. حدد User Flow معين

مثال: طلب أكل من Talabat

2. اكتب خطوات الاختبار من خلال الـ UI

1. فتح التطبيق
2. اختيار مطعم
3. إضافة items
4. Checkout
5. ...

3. فكر: كيف راح تختبر نفس الـ Flow من خلال API؟

ما الـ Requests اللي راح تبعثها؟

4. فكر: ما البيانات التي لازم تتحقق منها بالـ Database؟

-- Order موجود?
-- Items صحيحة?
-- Total Price صحيح?
-- ...

5. حدد User Roles المختلفة

  • Regular User
  • Restaurant Owner
  • Admin
  • Delivery Driver

6. اكتب Error Scenarios

  • لو المطعم مسكّر؟
  • لو Payment فشل؟
  • لو Address غلط؟
نصيحة
لا تكتب كل شي! لكن فكر وخطط. الهدف إنك تتعود تفكر بالطرق المختلفة للاختبار!

خلاصة الدرس

Functional Testing يختبر الـ Business Logic والـ Requirements

في 3 طرق رئيسية: UI, API, Database

UI ← سهلة ومباشرة، لكن بطيئة. نستخدمها للتأكد من User Experience

API ← سريعة وفعالة. نستخدمها للاختبارات السريعة والـ Automation

Database ← الأدق والأكيد. نستخدمها للتأكد 100% من البيانات

كل طريقة تكشف مشاكل مختلفة ← لازم نستخدم الثلاثة!

لازم نختبر:

  • كل User Roles (Admin, User, Premium, Guest)
  • Error Messages (مش فقط Happy Path!)
  • System Integration (Payment, Email, Maps, الخ)

ابدأ بالـ UI حتى تفهم الـ Flow، بعد ذلك استخدم API للسرعة، وتحقق من Database حتى تتأكد


تذكّر: النظام ممكن يكون "شغال" على الـ UI لكن "غلط" بالـ Database!

دايماً تحقق من الطرق الثلاثة حتى تتأكد إنه كل شي صح! ✨


يعطيكم العافية! 💙