# 📋 TEMPLATE TEST SCENARIO CHO TESTER FRESHER AGILE

> **Phiên bản:** 1.0 | **Cập nhật:** 2024 | **Dành cho:** Tester Fresher trong môi trường Agile/Scrum

---

## 📚 MỤC LỤC

1. [Hướng dẫn đọc User Story & Acceptance Criteria](#1-hướng-dẫn-đọc-user-story--acceptance-criteria)
2. [Template Given-When-Then](#2-template-given-when-then)
3. [Tính năng: Đăng nhập](#3-tính-năng-đăng-nhập)
4. [Tính năng: Thêm/Sửa/Xóa dữ liệu](#4-tính-năng-thêmsửaxóa-dữ-liệu)
5. [Tính năng: Phân quyền](#5-tính-năng-phân-quyền)
6. [Tính năng: Thanh toán](#6-tính-năng-thanh-toán)
7. [Tính năng: Tìm kiếm / Lọc](#7-tính-năng-tìm-kiếm--lọc)
8. [Checklist trước khi submit scenario](#8-checklist-trước-khi-submit-scenario)

---

## 1. HƯỚNG DẪN ĐỌC USER STORY & ACCEPTANCE CRITERIA

### 1.1 User Story là gì?

```
Cấu trúc chuẩn:
┌─────────────────────────────────────────────────────────────┐
│  As a   [AI LÀ NGƯỜI DÙNG?]                                 │
│  I want [HỌ MUỐN LÀM GÌ?]                                   │
│  So that [ĐỂ ĐẠT ĐƯỢC ĐIỀU GÌ?]                             │
└─────────────────────────────────────────────────────────────┘

Ví dụ thực tế:
  As a   → Nhân viên kế toán
  I want → Xuất báo cáo doanh thu theo tháng ra file Excel
  So that → Nộp báo cáo cho trưởng phòng đúng deadline
```

### 1.2 Cách đọc Acceptance Criteria (AC)

```
AC thường viết theo 2 dạng:

━━━ DẠNG 1: Danh sách điều kiện ━━━
  AC1: Hệ thống cho phép đăng nhập bằng email và mật khẩu
  AC2: Hiển thị thông báo lỗi khi sai mật khẩu
  AC3: Khóa tài khoản sau 5 lần nhập sai liên tiếp

━━━ DẠNG 2: Given-When-Then (BDD) ━━━
  Given: Người dùng đã có tài khoản hợp lệ
  When:  Nhập đúng email và mật khẩu
  Then:  Chuyển đến trang Dashboard
```

### 1.3 Quy trình phân tích User Story → Test Scenario

```
BƯỚC 1: ĐỌC KỸ USER STORY
  ├── Xác định: Ai dùng? (Actor)
  ├── Xác định: Làm gì? (Action)
  └── Xác định: Mục đích? (Goal)

BƯỚC 2: PHÂN TÍCH TỪNG AC
  ├── Gạch chân ĐỘNG TỪ chính → hành động cần test
  ├── Gạch chân DỮ LIỆU cụ thể → test data cần chuẩn bị
  └── Tìm ĐIỀU KIỆN biên → edge case

BƯỚC 3: ĐẶT CÂU HỎI "what if?"
  ├── What if người dùng KHÔNG nhập gì?
  ├── What if dữ liệu quá dài / quá ngắn?
  ├── What if kết nối mạng bị ngắt?
  ├── What if người dùng không có quyền?
  └── What if hệ thống đang xử lý chậm?

BƯỚC 4: PHÂN LOẠI SCENARIO
  ├── ✅ Happy Path    → Luồng đúng, dữ liệu hợp lệ
  ├── ❌ Negative      → Dữ liệu sai, thiếu, không hợp lệ
  └── ⚠️  Edge Case    → Biên giới, giới hạn, tình huống đặc biệt

BƯỚC 5: VIẾT SCENARIO THEO GIVEN-WHEN-THEN
  └── (Xem template bên dưới)
```

### 1.4 Ví dụ phân tích thực tế

```
━━━ INPUT (User Story từ PO/BA) ━━━

  User Story:
  "Là nhân viên bán hàng, tôi muốn thêm sản phẩm mới vào
  danh mục, để khách hàng có thể xem và đặt hàng online."

  AC1: Bắt buộc nhập: Tên sản phẩm, Giá bán, Danh mục
  AC2: Tên sản phẩm tối đa 200 ký tự
  AC3: Giá bán phải là số dương, tối đa 999.999.999 VNĐ
  AC4: Sau khi lưu, sản phẩm hiển thị ngay trên website

━━━ OUTPUT (Danh sách scenario cần viết) ━━━

  ✅ Happy Path:
     → Thêm sản phẩm với đầy đủ thông tin hợp lệ

  ❌ Negative:
     → Thêm sản phẩm khi để trống Tên sản phẩm
     → Thêm sản phẩm với Giá bán = -1
     → Thêm sản phẩm với Giá bán = chữ "abc"

  ⚠️  Edge Case:
     → Tên sản phẩm đúng 200 ký tự (max boundary)
     → Tên sản phẩm 201 ký tự (over boundary)
     → Giá bán = 999.999.999 (max value)
     → Giá bán = 1.000.000.000 (over max)
```

### 1.5 Mapping AC → Scenario nhanh

| Từ khóa trong AC | Loại scenario cần tạo |
|---|---|
| "Bắt buộc nhập", "Required" | Negative: để trống field |
| "Tối đa N ký tự" | Edge: nhập đúng N, nhập N+1 |
| "Chỉ nhập số" | Negative: nhập chữ, ký tự đặc biệt |
| "Sau khi lưu..." | Happy: verify kết quả sau action |
| "Hiển thị thông báo lỗi" | Negative: trigger lỗi, check message |
| "Không cho phép..." | Negative + Phân quyền |
| "Gửi email/SMS" | Happy: verify notification |

---

## 2. TEMPLATE GIVEN-WHEN-THEN

### 2.1 Cấu trúc cơ bản

```gherkin
Scenario: [TÊN MÔ TẢ NGẮN GỌN - AI LÀM GÌ VỚI KẾT QUẢ GÌ]

  Given [TRẠNG THÁI BAN ĐẦU / ĐIỀU KIỆN TIÊN QUYẾT]
    And [ĐIỀU KIỆN BỔ SUNG NẾU CÓ]
  When  [HÀNH ĐỘNG NGƯỜI DÙNG THỰC HIỆN]
    And [HÀNH ĐỘNG BỔ SUNG NẾU CÓ]
  Then  [KẾT QUẢ MONG ĐỢI]
    And [KẾT QUẢ BỔ SUNG NẾU CÓ]
```

### 2.2 Quy tắc viết Given-When-Then

```
━━━ GIVEN (Điều kiện tiên quyết) ━━━
  ✅ NÊN:   "Người dùng đã đăng nhập với tài khoản Admin"
  ✅ NÊN:   "Sản phẩm 'Áo thun trắng' đang tồn tại trong hệ thống"
  ❌ TRÁNH: "Người dùng mở trình duyệt" (quá chi tiết UI)
  ❌ TRÁNH: "Hệ thống đang chạy" (hiển nhiên)

━━━ WHEN (Hành động) ━━━
  ✅ NÊN:   "Người dùng nhấn nút 'Xóa' trên sản phẩm ID #123"
  ✅ NÊN:   "Người dùng nhập email 'test@email.com' và mật khẩu 'Pass@123'"
  ❌ TRÁNH: Nhiều hành động độc lập trong 1 When
  ❌ TRÁNH: "Người dùng làm nhiều thứ phức tạp..."

━━━ THEN (Kết quả mong đợi) ━━━
  ✅ NÊN:   Cụ thể, đo lường được, có thể verify
  ✅ NÊN:   "Thông báo 'Đăng nhập thành công' hiển thị"
  ✅ NÊN:   "Tài khoản bị trừ 250.000 VNĐ"
  ❌ TRÁNH: "Hệ thống hoạt động đúng" (mơ hồ)
  ❌ TRÁNH: "Không có lỗi xảy ra" (không đo được)
```

### 2.3 Ký hiệu phân loại

```
✅ [HAPPY]    → Luồng thành công, dữ liệu hợp lệ
❌ [NEGATIVE] → Luồng thất bại, dữ liệu không hợp lệ
⚠️ [EDGE]     → Trường hợp biên, giới hạn hệ thống
🔒 [SECURITY] → Liên quan bảo mật, phân quyền
⚡ [PERF]     → Liên quan hiệu năng
```

---

## 3. TÍNH NĂNG: ĐĂNG NHẬP

> **Bối cảnh:** Hệ thống quản lý bán hàng nội bộ cho chuỗi siêu thị MegaMart

```
User Story:
  Là nhân viên MegaMart, tôi muốn đăng nhập vào hệ thống
  bằng email công ty và mật khẩu, để quản lý đơn hàng
  và kho hàng theo ca làm việc của mình.

AC1: Đăng nhập bằng email công ty (@megamart.vn) + mật khẩu
AC2: Hiển thị lỗi cụ thể khi sai thông tin
AC3: Khóa tài khoản 30 phút sau 5 lần nhập sai liên tiếp
AC4: Nhớ đăng nhập trong 7 ngày nếu tick "Ghi nhớ"
AC5: Chuyển đến màn hình phù hợp theo role sau đăng nhập
```

---

### SCENARIO 1 — ✅ HAPPY PATH

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-LOGIN-001: Đăng nhập thành công với tài khoản hợp lệ
─────────────────────────────────────────────────────────────────
Tags: @login @happy-path @smoke-test

  Given Nhân viên "Nguyễn Văn An" có tài khoản hợp lệ
          | Field      | Value                    |
          | Email      | an.nguyen@megamart.vn    |
          | Mật khẩu  | Megamart@2024            |
          | Role       | Nhân viên bán hàng       |
          | Trạng thái | Đang hoạt động           |
    And   Tài khoản CHƯA bị khóa
    And   Người dùng đang ở trang đăng nhập "/login"

  When  Người dùng nhập Email: "an.nguyen@megamart.vn"
    And Người dùng nhập Mật khẩu: "Megamart@2024"
    And Người dùng nhấn nút "Đăng nhập"

  Then  Hệ thống chuyển hướng đến trang "/dashboard/sales"
    And Hiển thị thông báo "Chào mừng, Nguyễn Văn An!"
    And Góc trên phải hiển thị tên "Nguyễn Văn An" và avatar
    And Menu điều hướng hiển thị đúng các mục theo role "Nhân viên bán hàng"
    And Session token được tạo và lưu trong cookie

Ghi chú:
  - Verify redirect URL đúng theo từng role
  - Kiểm tra session timeout đúng cấu hình
─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 2 — ❌ NEGATIVE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-LOGIN-002: Đăng nhập thất bại khi nhập sai mật khẩu
─────────────────────────────────────────────────────────────────
Tags: @login @negative

  Given Nhân viên "Trần Thị Bình" có tài khoản hợp lệ
          | Field      | Value                    |
          | Email      | binh.tran@megamart.vn    |
          | Mật khẩu  | Megamart@2024            |
          | Trạng thái | Đang hoạt động           |
    And   Người dùng đang ở trang đăng nhập "/login"
    And   Số lần đăng nhập sai hiện tại = 0

  When  Người dùng nhập Email: "binh.tran@megamart.vn"
    And Người dùng nhập Mật khẩu: "SaiMatKhau123"  ← mật khẩu SAI
    And Người dùng nhấn nút "Đăng nhập"

  Then  Hệ thống KHÔNG chuyển hướng, giữ nguyên trang "/login"
    And Hiển thị thông báo lỗi: "Email hoặc mật khẩu không đúng. Vui lòng thử lại."
    And Thông báo lỗi hiển thị màu đỏ, vị trí dưới form
    And Trường mật khẩu bị xóa, trường email giữ nguyên
    And Số lần đăng nhập sai tăng lên = 1
    And Tài khoản KHÔNG bị khóa (vì chưa đủ 5 lần)

Ghi chú:
  - KHÔNG hiển thị riêng "sai email" hay "sai mật khẩu" (bảo mật)
  - Đảm bảo message lỗi không tiết lộ thông tin nhạy cảm
─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 3 — ⚠️ EDGE CASE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-LOGIN-003: Khóa tài khoản sau 5 lần đăng nhập sai
─────────────────────────────────────────────────────────────────
Tags: @login @edge-case @security

  Given Nhân viên "Lê Văn Cường" có tài khoản đang hoạt động
          | Email      | cuong.le@megamart.vn     |
          | Mật khẩu  | Megamart@2024            |
    And   Tài khoản đã đăng nhập sai 4 lần liên tiếp trước đó
    And   Người dùng đang ở trang đăng nhập "/login"

  When  Người dùng nhập Email: "cuong.le@megamart.vn"
    And Người dùng nhập Mật khẩu: "SaiLanThu5" ← lần sai thứ 5
    And Người dùng nhấn nút "Đăng nhập"

  Then  Hệ thống KHÓA tài khoản ngay lập tức
    And Hiển thị thông báo:
        "Tài khoản bị tạm khóa do đăng nhập sai quá nhiều lần.
         Vui lòng thử lại sau 30 phút hoặc liên hệ Admin."
    And Ghi log sự kiện khóa tài khoản vào hệ thống audit
    And Admin nhận email thông báo: "Tài khoản cuong.le@megamart.vn bị khóa"
    And Sau đúng 30 phút, tài khoản tự động MỞ KHÓA
    And Người dùng có thể đăng nhập lại với mật khẩu đúng sau 30 phút

Ghi chú:
  - Test thêm: Nếu Admin unlock trước 30 phút → có thể login ngay
  - Test thêm: Đăng nhập đúng ở lần thứ 4 → counter reset về 0
─────────────────────────────────────────────────────────────────
```

---

## 4. TÍNH NĂNG: THÊM/SỬA/XÓA DỮ LIỆU

> **Bối cảnh:** Hệ thống quản lý nhân sự HRM cho công ty phần mềm TechViet

```
User Story:
  Là HR Manager, tôi muốn quản lý hồ sơ nhân viên (thêm/sửa/xóa),
  để duy trì dữ liệu nhân sự chính xác và cập nhật.

AC1: Bắt buộc nhập: Họ tên, CCCD, Ngày sinh, Phòng ban, Chức vụ
AC2: CCCD gồm đúng 12 số, không trùng trong hệ thống
AC3: Tuổi nhân viên từ 18 đến 60
AC4: Xóa nhân viên yêu cầu xác nhận, chuyển sang trạng thái "Đã nghỉ việc"
AC5: Lưu lịch sử chỉnh sửa (ai sửa, sửa gì, lúc nào)
```

---

### SCENARIO 4 — ✅ HAPPY PATH

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-HRM-001: Thêm mới hồ sơ nhân viên thành công
─────────────────────────────────────────────────────────────────
Tags: @hrm @create @happy-path

  Given HR Manager "Phạm Thị Dung" đã đăng nhập hệ thống
    And Người dùng đang ở trang "Quản lý nhân viên"
    And Số CCCD "012345678901" CHƯA tồn tại trong hệ thống

  When  Người dùng nhấn nút "+ Thêm nhân viên"
    And Người dùng điền form với thông tin:
          | Field          | Giá trị nhập          |
          | Họ và tên      | Hoàng Minh Tuấn       |
          | CCCD           | 012345678901          |
          | Ngày sinh      | 15/03/1995            |
          | Giới tính      | Nam                   |
          | Phòng ban      | Phòng Kỹ thuật        |
          | Chức vụ        | Software Engineer     |
          | Ngày vào làm   | 01/01/2024            |
          | Lương cơ bản   | 20.000.000 VNĐ        |
    And Người dùng nhấn nút "Lưu"

  Then  Hệ thống lưu hồ sơ thành công
    And Hiển thị thông báo: "Thêm nhân viên Hoàng Minh Tuấn thành công!"
    And Hồ sơ "Hoàng Minh Tuấn" xuất hiện trong danh sách nhân viên
    And Mã nhân viên tự động được cấp (format: TV-YYYY-XXXX)
    And Email chào mừng được gửi đến HR Manager
    And Lịch sử ghi nhận: "Phạm Thị Dung tạo hồ sơ lúc [timestamp]"

─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 5 — ❌ NEGATIVE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-HRM-002: Thêm nhân viên thất bại khi CCCD đã tồn tại
─────────────────────────────────────────────────────────────────
Tags: @hrm @create @negative @validation

  Given HR Manager đã đăng nhập hệ thống
    And Trong hệ thống đã có nhân viên với CCCD "012345678901"
          | Nhân viên hiện có | Nguyễn Văn Bảo |
          | CCCD              | 012345678901   |

  When  Người dùng mở form "Thêm nhân viên mới"
    And Người dùng nhập CCCD: "012345678901"   ← CCCD đã tồn tại
    And Người dùng điền đầy đủ các thông tin bắt buộc khác
    And Người dùng nhấn nút "Lưu"

  Then  Hệ thống KHÔNG lưu hồ sơ
    And Hiển thị lỗi tại field CCCD:
        "Số CCCD này đã được đăng ký cho nhân viên khác trong hệ thống."
    And Form vẫn hiển thị với đầy đủ dữ liệu người dùng đã nhập
    And Dữ liệu các field khác KHÔNG bị mất
    And Không có bản ghi mới nào được tạo trong database

Ghi chú:
  - Test thêm: CCCD đủ 12 số nhưng chứa chữ → lỗi format
  - Test thêm: CCCD chỉ có 9 số → lỗi độ dài
─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 6 — ⚠️ EDGE CASE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-HRM-003: Xóa nhân viên đang có hợp đồng lao động hiệu lực
─────────────────────────────────────────────────────────────────
Tags: @hrm @delete @edge-case @business-rule

  Given HR Manager đã đăng nhập hệ thống
    And Nhân viên "Vũ Thị Hoa" tồn tại với:
          | Trạng thái HĐ    | Hợp đồng còn hiệu lực  |
          | Hết hạn HĐ       | 31/12/2025             |
          | Phòng ban        | Phòng Kinh doanh       |

  When  Người dùng nhấn icon "Xóa" trên hồ sơ nhân viên "Vũ Thị Hoa"
    And Hệ thống hiển thị popup xác nhận
    And Người dùng nhấn "Xác nhận xóa"

  Then  Hệ thống KHÔNG xóa vĩnh viễn hồ sơ
    And Hiển thị cảnh báo:
        "Nhân viên Vũ Thị Hoa đang có hợp đồng còn hiệu lực đến 31/12/2025.
         Không thể xóa. Vui lòng kết thúc hợp đồng trước."
    And Hồ sơ vẫn còn nguyên trong danh sách
    And Gợi ý người dùng: nút "Kết thúc hợp đồng" hoặc "Chuyển trạng thái"

Ghi chú:
  - Test thêm: Xóa nhân viên HĐ đã hết hạn → chuyển "Đã nghỉ việc", không xóa thật
  - Test thêm: Xóa nhân viên đang có phiếu lương tháng hiện tại chưa duyệt
─────────────────────────────────────────────────────────────────
```

---

## 5. TÍNH NĂNG: PHÂN QUYỀN

> **Bối cảnh:** Hệ thống quản lý bệnh viện cho Bệnh viện Đa Khoa Bình Dương

```
User Story:
  Là Quản trị hệ thống, tôi muốn phân quyền truy cập theo vai trò,
  để đảm bảo mỗi nhóm nhân viên chỉ xem được thông tin phù hợp
  với công việc của họ.

AC1: 4 role: Admin, Bác sĩ, Y tá, Lễ tân
AC2: Chỉ Bác sĩ mới xem được hồ sơ bệnh án chi tiết
AC3: Lễ tân chỉ quản lý lịch hẹn, không xem kết quả xét nghiệm
AC4: Admin cấp/thu hồi quyền, ghi log mọi thay đổi
AC5: Người dùng không có quyền nhận HTTP 403, redirect về trang thông báo
```

---

### SCENARIO 7 — ✅ HAPPY PATH

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-AUTH-001: Bác sĩ truy cập hồ sơ bệnh án thành công
─────────────────────────────────────────────────────────────────
Tags: @authorization @happy-path @role-based

  Given Người dùng "BS. Nguyễn Thanh Hải" đã đăng nhập
    And Tài khoản có role: "Bác sĩ"
    And Hồ sơ bệnh nhân "BN-2024-00123 - Trần Văn Nam" đang tồn tại
    And BS. Nguyễn Thanh Hải là bác sĩ phụ trách bệnh nhân này

  When  Bác sĩ nhấn vào "Xem hồ sơ bệnh án" của BN-2024-00123

  Then  Hệ thống cho phép truy cập
    And Hiển thị đầy đủ hồ sơ bệnh án bao gồm:
          - Thông tin cá nhân bệnh nhân
          - Lịch sử khám chữa bệnh
          - Kết quả xét nghiệm
          - Đơn thuốc đã kê
          - Ghi chú chẩn đoán
    And Response HTTP status = 200
    And Ghi log truy cập: "BS. Nguyễn Thanh Hải xem hồ sơ BN-2024-00123 lúc [timestamp]"

─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 8 — ❌ NEGATIVE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-AUTH-002: Lễ tân bị từ chối khi truy cập hồ sơ bệnh án
─────────────────────────────────────────────────────────────────
Tags: @authorization @negative @security

  Given Người dùng "Lê Thị Mai" đã đăng nhập hệ thống
    And Tài khoản có role: "Lễ tân"  ← KHÔNG có quyền xem bệnh án
    And Hồ sơ bệnh nhân BN-2024-00123 đang tồn tại trong hệ thống

  When  Lê Thị Mai cố truy cập URL trực tiếp:
        "/benh-an/BN-2024-00123/chi-tiet"

  Then  Hệ thống TỪ CHỐI truy cập
    And HTTP Response status = 403 Forbidden
    And Redirect đến trang "/khong-co-quyen"
    And Trang hiển thị thông báo:
        "Bạn không có quyền truy cập tính năng này.
         Vui lòng liên hệ Quản trị viên nếu cần hỗ trợ."
    And Ghi log cảnh báo: "Lễ tân 'Lê Thị Mai' cố truy cập bệnh án [timestamp]"
    And KHÔNG hiển thị BẤT KỲ dữ liệu bệnh nhân nào dù là một phần

Ghi chú:
  - Test thêm: Dùng Developer Tools sửa role trong cookie → vẫn bị chặn
  - Test thêm: Gọi API trực tiếp không qua UI → vẫn trả về 403
─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 9 — ⚠️ EDGE CASE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-AUTH-003: Tài khoản bị thu hồi quyền trong khi đang đăng nhập
─────────────────────────────────────────────────────────────────
Tags: @authorization @edge-case @session

  Given Bác sĩ "Phạm Quốc Hùng" đang đăng nhập và làm việc
    And Hiện đang mở trang danh sách bệnh nhân của mình
    And Admin "Quản trị Sơn" đăng nhập trên một trình duyệt khác

  When  Admin "Quản trị Sơn" thu hồi quyền "Bác sĩ" của tài khoản Phạm Quốc Hùng
    And Phạm Quốc Hùng nhấn "Xem hồ sơ" của một bệnh nhân

  Then  Hệ thống phát hiện quyền đã thay đổi
    And Tự động đăng xuất phiên làm việc của Phạm Quốc Hùng
    And Redirect về trang đăng nhập "/login"
    And Hiển thị thông báo:
        "Phiên làm việc của bạn đã hết hạn hoặc quyền truy cập thay đổi.
         Vui lòng đăng nhập lại."
    And Mọi thay đổi chưa lưu được cảnh báo trước khi logout
    And Ghi log sự kiện thu hồi quyền vào audit trail

Ghi chú:
  - Thời gian phát hiện thay đổi quyền không quá 5 phút (real-time hoặc polling)
  - Test thêm: Cấp thêm quyền mới → không cần logout, tự nhận quyền mới
─────────────────────────────────────────────────────────────────
```

---

## 6. TÍNH NĂNG: THANH TOÁN

> **Bối cảnh:** App đặt xe GrabBike/GoCar phiên bản Việt Nam (ví dụ: FastGo VN)

```
User Story:
  Là khách hàng, tôi muốn thanh toán chuyến đi bằng ví điện tử
  MoMo hoặc tiền mặt, để hoàn tất giao dịch thuận tiện.

AC1: Hỗ trợ thanh toán: Tiền mặt, Ví MoMo, VNPay, Thẻ Visa/MC
AC2: Số dư ví đủ → trừ tiền ngay sau khi tài xế xác nhận kết thúc
AC3: Thanh toán thất bại → giữ đơn hàng, cho phép thử lại hoặc đổi PP
AC4: Hiển thị hóa đơn chi tiết sau thanh toán thành công
AC5: Hoàn tiền về ví trong 3-5 ngày làm việc khi hủy đơn hợp lệ
```

---

### SCENARIO 10 — ✅ HAPPY PATH

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-PAY-001: Thanh toán chuyến đi thành công qua ví MoMo
─────────────────────────────────────────────────────────────────
Tags: @payment @happy-path @momo @critical

  Given Khách hàng "Nguyễn Bảo Trân" đã đăng nhập app FastGo
    And Chuyến đi từ "Quận 1" đến "Tân Bình" đã hoàn thành
    And Cước phí chuyến đi = 45.000 VNĐ
    And Số dư ví MoMo của khách = 200.000 VNĐ  ← đủ tiền
    And Phương thức thanh toán được chọn: "Ví MoMo"

  When  Tài xế nhấn "Kết thúc chuyến đi" trên app tài xế
    And Hệ thống gửi yêu cầu thanh toán 45.000 VNĐ đến MoMo
    And MoMo xác nhận giao dịch thành công

  Then  Ví MoMo của khách bị trừ đúng 45.000 VNĐ
    And Số dư còn lại: 200.000 - 45.000 = 155.000 VNĐ
    And App FastGo hiển thị màn hình hóa đơn:
          | Mã chuyến đi   | FG-20240315-00891    |
          | Điểm đón       | 25 Lê Lợi, Q.1      |
          | Điểm trả       | 48 CMT8, Tân Bình    |
          | Quãng đường    | 6.2 km               |
          | Thời gian      | 18 phút              |
          | Cước phí       | 45.000 VNĐ           |
          | PP thanh toán  | Ví MoMo              |
          | Trạng thái     | THÀNH CÔNG ✓         |
    And Khách nhận thông báo push: "Thanh toán 45.000đ thành công"
    And Tài xế nhận thông báo xác nhận đã thanh toán
    And Lịch sử giao dịch trong app được cập nhật

─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 11 — ❌ NEGATIVE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-PAY-002: Thanh toán thất bại do số dư ví không đủ
─────────────────────────────────────────────────────────────────
Tags: @payment @negative @momo @insufficient-balance

  Given Khách hàng "Trần Hữu Phúc" đã đăng nhập app FastGo
    And Chuyến đi đã hoàn thành với cước phí = 85.000 VNĐ
    And Số dư ví MoMo = 30.000 VNĐ  ← KHÔNG đủ tiền
    And Phương thức thanh toán được chọn: "Ví MoMo"

  When  Tài xế nhấn "Kết thúc chuyến đi"
    And Hệ thống gửi yêu cầu thanh toán 85.000 VNĐ đến MoMo
    And MoMo trả về lỗi: "Số dư không đủ"

  Then  Hệ thống KHÔNG trừ tiền từ ví MoMo
    And App FastGo hiển thị popup thông báo:
        "Thanh toán không thành công. Số dư ví MoMo không đủ.
         (Cần: 85.000đ | Có: 30.000đ)"
    And Cung cấp 2 lựa chọn:
          [1] "Đổi phương thức thanh toán"
          [2] "Nạp thêm tiền vào MoMo"
    And Chuyến đi chuyển sang trạng thái "Chờ thanh toán"
    And Tài xế thấy thông báo: "Khách đang xử lý thanh toán"
    And Sau 15 phút không thanh toán → nhắc nhở tự động

Ghi chú:
  - Test thêm: Hệ thống MoMo timeout → FastGo xử lý thế nào?
  - Test thêm: Giao dịch pending quá 30 phút → tự động chuyển tiền mặt
─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 12 — ⚠️ EDGE CASE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-PAY-003: Tránh thanh toán trùng lặp do double-click
─────────────────────────────────────────────────────────────────
Tags: @payment @edge-case @idempotency @critical

  Given Khách hàng "Lê Ngọc Ánh" hoàn thành chuyến đi
    And Cước phí = 60.000 VNĐ
    And Số dư ví VNPay = 500.000 VNĐ
    And Phương thức thanh toán: "VNPay"

  When  Khách nhấn nút "Xác nhận thanh toán"
    And Do mạng chậm, nút không phản hồi ngay
    And Khách nhấn lại nút "Xác nhận thanh toán" lần 2
    And (Hai request được gửi gần như đồng thời)

  Then  Hệ thống chỉ xử lý MỘT giao dịch duy nhất
    And Ví VNPay chỉ bị trừ đúng 60.000 VNĐ (không trừ 120.000 VNĐ)
    And Chỉ có 1 bản ghi giao dịch trong lịch sử
    And Hiển thị hóa đơn thanh toán thành công bình thường
    And Không có thông báo lỗi "giao dịch trùng lặp" nếu server xử lý đúng

Ghi chú:
  - Cơ chế: Idempotency Key hoặc vô hiệu hóa nút sau lần nhấn đầu
  - Test thêm: Double submit qua API trực tiếp (Postman) → vẫn xử lý 1 lần
  - Test thêm: Ngắt mạng giữa chừng → giao dịch ở trạng thái "đang xử lý",
               không trừ tiền → cho phép retry
─────────────────────────────────────────────────────────────────
```

---

## 7. TÍNH NĂNG: TÌM KIẾM / LỌC

> **Bối cảnh:** Sàn thương mại điện tử Sendo.vn / Tiki-clone dành cho SME Việt Nam

```
User Story:
  Là khách hàng mua sắm online, tôi muốn tìm kiếm và lọc sản phẩm
  theo nhiều tiêu chí, để nhanh chóng tìm được sản phẩm phù hợp
  với nhu cầu và ngân sách của mình.

AC1: Tìm kiếm theo tên sản phẩm, thương hiệu, mô tả
AC2: Lọc theo: Danh mục, Giá (khoảng), Thương hiệu, Đánh giá, Kho hàng
AC3: Sắp xếp: Liên quan nhất, Bán chạy, Giá tăng/giảm, Mới nhất
AC4: Kết quả tìm kiếm không phân biệt hoa thường, có dấu/không dấu
AC5: Hiển thị số lượng kết quả, phân trang 20 sản phẩm/trang
AC6: Gợi ý tự động khi gõ từ 2 ký tự trở lên
```

---

### SCENARIO 13 — ✅ HAPPY PATH

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-SEARCH-001: Tìm kiếm sản phẩm với kết quả hợp lệ và lọc theo giá
─────────────────────────────────────────────────────────────────
Tags: @search @filter @happy-path

  Given Khách hàng đang ở trang chủ sàn TMDT
    And Trong hệ thống có 150 sản phẩm danh mục "Điện thoại"
    And Có 45 sản phẩm trong khoảng giá 3.000.000 - 7.000.000 VNĐ

  When  Khách hàng nhập từ khóa "điện thoại samsung" vào ô tìm kiếm
    And Nhấn Enter hoặc icon tìm kiếm
    And Hệ thống hiển thị kết quả
    And Khách hàng áp dụng bộ lọc:
          | Bộ lọc         | Giá trị                        |
          | Giá từ         | 3.000.000 VNĐ                  |
          | Giá đến        | 7.000.000 VNĐ                  |
          | Thương hiệu    | Samsung                        |
          | Đánh giá       | Từ 4 sao trở lên               |
    And Chọn sắp xếp: "Giá: Thấp đến Cao"

  Then  Trang kết quả hiển thị:
          - Tiêu đề: "Kết quả tìm kiếm cho 'điện thoại samsung'"
          - Số kết quả: "Tìm thấy XX sản phẩm"
          - Chỉ hiển thị sản phẩm Samsung trong khoảng giá đã chọn
          - Sản phẩm được sắp xếp giá từ thấp đến cao
          - Mỗi sản phẩm hiển thị: ảnh, tên, giá, số sao đánh giá
    And Phân trang hiển thị đúng: 20 sản phẩm/trang
    And URL phản ánh các filter: "?q=dien+thoai+samsung&brand=samsung&min=3000000..."
    And Thời gian tải kết quả < 3 giây

─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 14 — ❌ NEGATIVE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-SEARCH-002: Tìm kiếm từ khóa không có kết quả phù hợp
─────────────────────────────────────────────────────────────────
Tags: @search @negative @empty-result

  Given Khách hàng đang ở trang tìm kiếm
    And Trong hệ thống KHÔNG có sản phẩm nào tên "máy pha cà phê Nespresso"
          (hoặc sản phẩm tồn tại nhưng đang hết hàng/ẩn)

  When  Khách hàng nhập từ khóa: "máy pha cà phê Nespresso"
    And Nhấn tìm kiếm

  Then  Hệ thống KHÔNG báo lỗi 404 hay lỗi hệ thống
    And Hiển thị trang "Không tìm thấy kết quả" thân thiện với:
          - Thông báo: "Không tìm thấy sản phẩm nào cho 'máy pha cà phê Nespresso'"
          - Gợi ý: "Thử lại với từ khóa khác" hoặc "Kiểm tra chính tả"
          - Hiển thị 4-6 sản phẩm "Có thể bạn quan tâm" liên quan (cà phê, pha cà phê)
          - Nút "Xem tất cả danh mục"
    And Ô tìm kiếm vẫn hiển thị từ khóa người dùng đã nhập
    And Không crash hoặc màn hình trắng

Ghi chú:
  - Test thêm: Từ khóa chứa ký tự đặc biệt: "máy <script>alert(1)</script>"
               → hệ thống escape, không execute
  - Test thêm: Từ khóa quá dài (> 500 ký tự) → hệ thống cắt bớt hoặc thông báo
─────────────────────────────────────────────────────────────────
```

---

### SCENARIO 15 — ⚠️ EDGE CASE

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-SEARCH-003: Tìm kiếm không phân biệt dấu tiếng Việt
─────────────────────────────────────────────────────────────────
Tags: @search @edge-case @vietnamese @encoding

  Given Khách hàng đang ở trang tìm kiếm
    And Hệ thống có sản phẩm: "Áo Phông Nam Trắng Uniqlo"
    And Hệ thống có sản phẩm: "Áo Khoác Nữ Mùa Đông"

  When  Khách hàng lần lượt tìm kiếm các từ khóa sau:

        ┌─────────────────────────────────────────────┐
        │  Test Case A: "ao phong nam"  (không dấu)   │
        │  Test Case B: "ÁO PHÔNG NAM" (viết HOA)     │
        │  Test Case C: "áo phong nam" (thiếu dấu)    │
        │  Test Case D: "  áo phông  " (có khoảng trống đầu/cuối) │
        └─────────────────────────────────────────────┘

  Then  Với TẤT CẢ 4 test case trên:
          - Hệ thống đều trả về sản phẩm "Áo Phông Nam Trắng Uniqlo"
          - Từ khóa tìm kiếm được tự động trim khoảng trống
          - Hiển thị đúng tên sản phẩm gốc (có dấu, đúng font)

    And Với Test Case A "ao phong nam" cụ thể:
          - Tìm thấy sản phẩm áo phông (không phân biệt dấu)
          - KHÔNG tìm ra sản phẩm "áo khoác" (sai danh mục)

    And Thời gian trả kết quả < 2 giây với mọi dạng từ khóa

Ghi chú:
  - Test thêm: Tìm "samsung galxy" (sai chính tả) → gợi ý "Ý bạn muốn nói: samsung galaxy?"
  - Test thêm: Copy-paste từ khóa từ Word có ký tự đặc biệt (" ") → xử lý đúng
  - Test thêm: Từ khóa là emoji "📱" → không crash, trả về kết quả rỗng hoặc relevant
─────────────────────────────────────────────────────────────────
```

---

## 8. CHECKLIST TRƯỚC KHI SUBMIT SCENARIO

### 8.1 Checklist tự review

```
━━━ CHECKLIST CHO MỖI SCENARIO ━━━

PHẦN GIVEN:
  □ Đã xác định rõ ROLE người dùng thực hiện?
  □ Đã nêu dữ liệu ban đầu cụ thể (không mơ hồ)?
  □ Điều kiện tiên quyết có thể setup được không?
  □ Đã liệt kê đủ data cần thiết để reproduce?

PHẦN WHEN:
  □ Chỉ có MỘT hành động chính (hoặc chuỗi hành động liên tiếp)?
  □ Hành động mô tả đủ rõ để bất kỳ tester nào cũng làm được?
  □ Đã ghi rõ data input cụ thể?

PHẦN THEN:
  □ Mỗi kết quả có thể VERIFY được bằng mắt hoặc code?
  □ Không có kết quả mơ hồ ("hệ thống hoạt động đúng")?
  □ Đã kiểm tra cả UI lẫn backend (data trong DB)?
  □ Đã kiểm tra notification/email/log nếu AC yêu cầu?

TỔNG THỂ:
  □ Tên scenario mô tả đúng nội dung?
  □ Có đủ 3 loại: Happy / Negative / Edge case?
  □ Scenario độc lập, không phụ thuộc thứ tự chạy?
  □ Tags được gán đúng?
  □ Ghi chú các scenario liên quan cần test thêm?
```

### 8.2 Bảng tổng hợp Test Coverage

```
Feature           | Happy | Negative | Edge | Total | Reviewed
──────────────────|───────|──────────|──────|───────|---------
Đăng nhập         |   ✅  |    ✅    |  ✅  |   3   |   [ ]
Thêm/Sửa/Xóa      |   ✅  |    ✅    |  ✅  |   3   |   [ ]
Phân quyền        |   ✅  |    ✅    |  ✅  |   3   |   [ ]
Thanh toán        |   ✅  |    ✅    |  ✅  |   3   |   [ ]
Tìm kiếm/Lọc      |   ✅  |    ✅    |  ✅  |   3   |   [ ]
──────────────────|───────|──────────|──────|───────|---------
TỔNG              |   5   |    5     |  5   |  15   |
```

### 8.3 Quy ước đặt tên Scenario ID

```
Format: TC-[FEATURE]-[SỐ THỨ TỰ]

TC  = Test Case
Feature codes:
  LOGIN   = Đăng nhập / Đăng xuất
  HRM     = Quản lý nhân sự / dữ liệu
  AUTH    = Phân quyền
  PAY     = Thanh toán
  SEARCH  = Tìm kiếm / Lọc
  REPORT  = Báo cáo
  NOTIFY  = Thông báo

Ví dụ:
  TC-LOGIN-001  → Test case đăng nhập số 1
  TC-PAY-003    → Test case thanh toán số 3
  TC-SEARCH-010 → Test case tìm kiếm số 10
```

### 8.4 Template trống để copy-paste

```gherkin
─────────────────────────────────────────────────────────────────
Scenario TC-[FEATURE]-[XXX]: [MÔ TẢ NGẮN GỌN]
─────────────────────────────────────────────────────────────────
Tags: @[feature] @[happy-path|negative|edge-case]

  Given [ĐIỀU KIỆN TIÊN QUYẾT 1]
    And [ĐIỀU KIỆN BỔ SUNG NẾU CÓ]
          | Field | Giá trị |
          |       |         |

  When  [HÀNH ĐỘNG CHÍNH]
    And [HÀNH ĐỘNG BỔ SUNG NẾU CÓ]

  Then  [KẾT QUẢ MONG ĐỢI 1]
    And [KẾT QUẢ MONG ĐỢI 2]
    And [KẾT QUẢ MONG ĐỢI 3]

Ghi chú:
  - [SCENARIO LIÊN QUAN CẦN TEST THÊM]
─────────────────────────────────────────────────────────────────
```

---

## 📌 TÀI LIỆU THAM KHẢO & GHI NHỚ NHANH

```
┌──────────────────────────────────────────────────────────────┐
│                    CÔNG THỨC GHI NHỚ NHANH                   │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│  GIVEN = "Bối cảnh" → Ai? Trạng thái ban đầu thế nào?       │
│  WHEN  = "Hành động" → Làm gì?                               │
│  THEN  = "Kết quả" → Mong đợi thấy gì?                      │
│                                                              │
│  ✅ Happy   = Đúng người + Đúng data + Đúng điều kiện        │
│  ❌ Negative = Sai data + Thiếu data + Sai quyền             │
│  ⚠️ Edge    = Biên giới + Giới hạn + Đồng thời + Crash      │
│                                                              │
│  3 CÂU HỎI KHI ĐỌC AC:                                      │
│    1. Điều gì phải ĐÚNG để scenario pass?                    │
│    2. Điều gì khiến scenario FAIL?                           │
│    3. Có trường hợp ĐẶC BIỆT nào chưa được nhắc đến?        │
│                                                              │
└──────────────────────────────────────────────────────────────┘
```

---

> **Lưu ý cuối:** Template này là điểm khởi đầu. Hãy luôn **trao đổi với Dev và PO** khi có thắc mắc về AC — một câu hỏi đúng lúc có thể tiết kiệm hàng giờ test sai hướng! 🚀