1 Principle

✅ What Each Testing Layer Should Do

Testing Layer What to Test Example
🟩 Unit Test Test core logic of individual functions or classes, without external dependencies Validate password strength: PasswordValidator::isStrong()
🟨 Integration Test Test how modules/services interact, often with real DB or services Check if user registration inserts into DB and sends email
🟥 End-to-End (E2E) Test Simulate real user behavior across the full stack Fill out registration form in browser → submit → redirect to dashboard

❌ What Each Testing Layer Should NOT Do

Testing Layer Don’t Do This Reason
🟩 Unit Test Don’t access DB, network, or real APIs Unit tests should be fast, isolated, and logic-only
🟨 Integration Test Don’t test UI rendering or button positions Integration tests focus on backend/data flow, not UI components
🟥 End-to-End (E2E) Test Don’t test detailed field validations (e.g., regex) E2E tests should verify core flows, not internal validation rules

🧠 Test Layer Summary

Layer DO DON’T
Unit Test logic in isolation No DB, no API calls
Integration Test module cooperation No UI component tests
E2E Test full user flow No detailed field logic or validation

2 Minimum Viable Test Plan

based on the Test Pyramid model.

Login

example AuthService::login() Unit Test Cases :

Test ID Scenario Description Input Conditions Mocked Behavior Expected Behavior Key Assertions
1 Login succeeds with valid credentials Valid email and password; email is verified; status is Active; company type is allowed Auth::attempt returns token; Auth::user returns user Returns success: true with token and user info expect($response->success)->toBeTrue()expect($response->data['user']->email)->toBe(TEST_ACCOUNT_EMAIL)
2 Login fails due to incorrect password Valid email but wrong password Auth::attempt returns false Returns success: false with login failure message expect($response->success)->toBeFalse()expect($response->message)->toBe(AuthStatus::FAILED->message())
3 Login denied due to disallowed company User’s company type is not in allowed list Auth::user returns user with disallowed company; logout called Returns success: false with “Access forbidden” message expect($response->success)->toBeFalse()expect($response->message)->toContain('Access forbidden')
4 Email not verified, triggers callback email_verified_at is null Callback is invoked; logout is called Returns success: false; includes email_verification_required = true expect($response->success)->toBeFalse()expect($called)->toBeTrue()expect($response->data['email_verification_required'])->toBeTrue()
5 Login blocked due to Pending status User status is Pending logout is called Returns success: false with pending status message expect($response->success)->toBeFalse()expect($response->message)->toBe(AuthStatus::PENDING->message())
6 Login blocked due to Suspended status User status is Suspended logout is called Returns success: false with suspended status message expect($response->success)->toBeFalse()expect($response->message)->toBe(AuthStatus::SUSPENDED->message())

example result :

   PASS  Tests\Unit\Services\Auth\AdminLoginTest
  ✓ AuthService::login() → it logs in successfully with correct credentials                                                                                                                           0.13s  
  ✓ AuthService::login() → it fails with incorrect password                                                                                                                                           0.01s  
  ✓ AuthService::login() → it blocks users with disallowed company type                                                                                                                               0.01s  
  ✓ AuthService::login() → it requires email verification if email is not verified                                                                                                                    0.03s  
  ✓ AuthService::login() → it rejects users with Pending status                                                                                                                                       0.01s  
  ✓ AuthService::login() → it rejects users with Suspended status   

Login & Registration Feature Test Cases

Feature Name Description Test Level Sample Test Data Expected Result
Sign Up Register a new user with email and password End-to-End Email: test@abc.comPassword: Test@1234Confirm: Test@1234 Registration successful; system sends email verification
Email Format Check Validate email input format Unit Email: test@abc / test@.com Error: “Invalid email format”
Password Strength Enforce strong password policy Unit Password: 12345 / abcde Error: “Password too weak”
Password Match Ensure password and confirmation match Unit Password: Test@1234Confirm: Test@4321 Error: “Passwords do not match”
Email Verification Handle email token verification Integration Link: /verify?token=abc123 Success: “Email verified”, user is activated
Token Expiry Handle expired or invalid email verification link Integration Link: /verify?token=expired Error: “Verification link is invalid or expired”
Login Login with email and password End-to-End Email: test@abc.comPassword: Test@1234 Login successful, redirect to dashboard
Login Rate Limit Limit login attempts to prevent brute-force attacks Integration 5 failed login attempts Error: “Too many login attempts” or account temporarily locked
Forgot Password Request a password reset link via email Integration Email: test@abc.com Message: “Password reset link sent to your email”
Reset Password Set a new password using the reset link End-to-End Link: /reset?token=abc123New password: Test@5678 Message: “Password successfully reset”, user can login again
Logout Log the user out and destroy session/token Integration Click “Logout” JWT/session/cookie is cleared, user is redirected to login page

User Management Feature Test Cases

Feature Name Description Test Level Sample Test Data Expected Result
Personal Info Update Update user details: last name, mobile number, landline number (required), extension, address End-to-End Last Name: SmithMobile: 0210000000Landline: 0320000000Ext: 123Address: 123 Main St Success: “Profile updated”
Landline Required Check Ensure landline number is mandatory when updating profile info Unit Landline: (empty) Error: “Landline number is required”
Password Change Change password by providing current password and confirming new one twice End-to-End Current: OldPass@123New: NewPass@456Confirm: NewPass@456 Success: “Password updated”, user may need to log in again
Password Mismatch Check Ensure new password and confirmation match Unit New Password: NewPass@456Confirm: NewPass@654 Error: “Passwords do not match”
Current Password Check Require correct current password to authorize password change Integration Current Password: (incorrect) Error: “Current password is incorrect”
Email Verification Check Ensure email is verified before allowing access to core features End-to-End User has not verified email, tries to create a project/order Error: “Please verify your email first”, action is blocked

Glossary : The Testing Pyramid is a software testing strategy that emphasizes having more low-level tests (fast and cheap) and fewer high-level tests (slower and costlier). This ensures test coverage is broad, efficient, and maintainable.

Three Layers of the Testing Pyramid :

Layer Definition Characteristics
1. Unit Test Tests individual functions, methods, or components in isolation. - Fast and lightweight- No external dependencies (e.g., database, API)- Ideal for logic validation
2. Integration Test Tests how different components or systems work together (e.g., database + backend API). - Slower than unit tests- Checks service or module interaction- Often test APIs, auth, DB logic
3. End-to-End Test (E2E) Simulates real user scenarios across the whole system (frontend + backend + DB). - Slowest and most resource-intensive- High confidence- Useful for testing critical user workflows

Key Idea :

  • The base of the pyramid is unit tests—you should have the most of these.
  • The middle layer has integration tests—fewer, but still essential.
  • The top is E2E tests—only a small number to cover critical user journeys.