Phân tích & thiết kế
Từ Use Case Thêm sản phẩm đến mã kiểm thử
Viết luồng chính, rẽ nhánh theo ngoại lệ và truy vết từng bước sang hàm nghiệp vụ cùng ca kiểm thử.
Thích và đánh giá Bình luận và hỏi đáp1. Mô tả mục tiêu, tác nhân và hậu điều kiện
Nhân viên hoặc quản lý cần đưa một mặt hàng mới vào danh mục. Trước khi thực hiện, người dùng đã đăng nhập và có quyền quản lý sản phẩm. Sau khi hoàn tất, danh mục có đúng một mặt hàng theo mã đã chuẩn hóa và màn hình hiển thị xác nhận.
Bản ví dụ quy định mã dài 3–16 ký tự, gồm chữ cái Latin, chữ số và dấu gạch ngang. Hệ thống cắt khoảng trắng ngoài và chuẩn hóa chữ hoa. Tên không để trống, dài tối đa 100 ký tự. Giá tính bằng đồng, là số nguyên không âm. Đặc tả càng rõ thì ca kiểm thử càng dễ đặt kỳ vọng cụ thể.
2. Tách luồng chính và các nhánh ngoại lệ
- Tác nhân chọn chức năng thêm sản phẩm.
- Hệ thống mở biểu mẫu mã, tên và giá bán.
- Tác nhân nhập dữ liệu và chọn Lưu.
- Hệ thống kiểm tra quyền, dữ liệu và mã trùng, sau đó lưu bản ghi.
- Hệ thống thông báo thành công và hiển thị thông tin vừa lưu.
Khi mã sai định dạng hoặc giá âm, biểu mẫu giữ lại dữ liệu và đánh dấu trường cần sửa. Khi mã trùng sau chuẩn hóa, hệ thống báo trùng mã và không ghi đè. Khi người dùng thiếu quyền, hệ thống từ chối trước khi ghi. Mỗi ngoại lệ cần xác định rõ phản hồi giao diện và trạng thái dữ liệu sau thao tác.
3. Ánh xạ kịch bản sang mã nghiệp vụ
Hàm addProduct nhận dữ liệu, vai trò và danh mục mô phỏng. Giá trị trả về gồm kết quả hoặc mã lỗi. Giao diện có thể dùng trường field để đặt thông báo gần ô nhập tương ứng.
Môi trường thực hành. Node.js 22 trở lên. Chạy node --test cùng tên tệp; các ca mẫu xử lý dữ liệu trong bộ nhớ.
import assert from "node:assert/strict";
import test from "node:test";
function addProduct(input, role, products) {
if (role !== "employee" && role !== "manager") {
return { ok: false, code: "FORBIDDEN" };
}
const code = typeof input?.code === "string" ? input.code.trim().toUpperCase() : "";
const name = typeof input?.name === "string" ? input.name.trim() : "";
const price = input?.price;
if (!/^[A-Z0-9-]{3,16}$/.test(code)) {
return { ok: false, code: "INVALID_CODE", field: "code" };
}
if (!name || name.length > 100) {
return { ok: false, code: "INVALID_NAME", field: "name" };
}
if (!Number.isSafeInteger(price) || price < 0) {
return { ok: false, code: "INVALID_PRICE", field: "price" };
}
if (products.has(code)) {
return { ok: false, code: "DUPLICATE_CODE", field: "code" };
}
const product = Object.freeze({ code, name, price });
products.set(code, product);
return { ok: true, product };
}
test("lưu và xác nhận với mã đã chuẩn hóa", () => {
const products = new Map();
const result = addProduct({ code: " sp01 ", name: " Bút bi ", price: 5000 }, "employee", products);
assert.deepEqual(result, { ok: true, product: { code: "SP01", name: "Bút bi", price: 5000 } });
assert.equal(products.size, 1);
assert.deepEqual(products.get("SP01"), result.product);
});
test("mã trùng không ghi đè sản phẩm đang có", () => {
const existing = { code: "SP01", name: "Bút bi", price: 5000 };
const products = new Map([["SP01", existing]]);
const result = addProduct({ code: "sp01", name: "Bút mới", price: 9000 }, "manager", products);
assert.deepEqual(result, { ok: false, code: "DUPLICATE_CODE", field: "code" });
assert.equal(products.size, 1);
assert.deepEqual(products.get("SP01"), existing);
});
test("giá sai và vai trò sai đều không thay đổi dữ liệu", () => {
const products = new Map();
assert.equal(addProduct({ code: "SP02", name: "Vở", price: -1 }, "employee", products).code, "INVALID_PRICE");
assert.equal(addProduct({ code: "SP02", name: "Vở", price: 8000 }, "viewer", products).code, "FORBIDDEN");
assert.equal(products.size, 0);
});Hàm gọi products.set sau các bước kiểm tra. Vì vậy ca thành công xác nhận dữ liệu được ghi, còn ca ngoại lệ xác nhận bản ghi cũ và kích thước danh mục. Mã demo dùng Map trong một tiến trình. Khi dùng cơ sở dữ liệu nhiều người dùng, đặt ràng buộc duy nhất cho mã đã chuẩn hóa và chuyển lỗi trùng của kho dữ liệu về nhánh ngoại lệ tương ứng.
4. Truy vết từ bước sử dụng đến ca kiểm thử
| Quy tắc trong Use Case | Dữ liệu thử | Điều cần xác nhận |
|---|---|---|
| Lưu thành công | Mã sp01 có khoảng trắng ngoài | Danh mục chứa đúng một mục mã SP01 |
| Mã phải duy nhất | Danh mục đã có SP01, nhập sp01 | Báo DUPLICATE_CODE, bản ghi cũ còn nguyên |
| Giá không âm | Giá -1 | Báo INVALID_PRICE, danh mục không tăng |
| Chỉ nhân viên và quản lý được ghi | Vai trò viewer | Báo FORBIDDEN |
Chạy node --test them-san-pham.test.mjs với Node.js 22 hoặc mới hơn. Ba ca phải đạt. Bổ sung hai trường hợp giá 0 và giá gửi dưới dạng chuỗi. Sau khi viết kỳ vọng cho dữ liệu, thử tiếp ca bấm nút Lưu hai lần trên giao diện để kiểm tra thông báo trùng và hành vi giữ biểu mẫu.