Đang tải...

Lửng Lọc Lõi

Đeo kính để soi Bug cho rõ, nhíu mày để nhắc Dev sửa cho kỹ. Với tôi, 'chạy được' thôi là chưa đủ! 🧐💻


0

SQL cơ bản cho tester: Những truy vấn cần biết để kiểm tra dữ liệu

Lửng Lọc Lõi
Lửng Lọc Lõi

3 tháng trước · 10 phút đọc

Tại sao tester cần biết SQL?

Mình nhớ hồi mới đi làm, có lần test tính năng "Lịch sử đơn hàng" của một app thương mại điện tử. UI hiển thị 5 đơn hàng, nhưng mình không chắc con số đó đúng hay sai. Dev bảo "đúng rồi", nhưng mình không có cách nào verify. Kết quả? Bug bị bỏ sót vì mình không có công cụ để kiểm tra phía backend.

Đó là lúc mình học SQL.

SQL (Structured Query Language) là ngôn ngữ dùng để "hỏi" database - hỏi rằng dữ liệu trong đó đang lưu gì, bao nhiêu bản ghi, có khớp với UI không. Bạn không cần biết lập trình, không cần hiểu code backend. Chỉ cần biết vài câu lệnh cơ bản là đã test được rất nhiều thứ.

344964 Tester dùng SQL để verify data backend - không chỉ tin vào những gì UI hiển thị

Cụ thể, SQL giúp tester làm được gì?

  • Đối chiếu số liệu: UI hiển thị "10 sản phẩm" - query DB xem có đúng 10 không
  • Verify trạng thái: Sau khi user đặt hàng, DB có cập nhật status = 'confirmed' chưa
  • Kiểm tra dữ liệu bị thiếu: Có bản ghi nào bị NULL hoặc thiếu field quan trọng không
  • Reproduce bug: Tìm đúng record đang bị lỗi để dev fix nhanh hơn

Một điều mình hay thấy: fresher tester thường chỉ test theo những gì mắt nhìn thấy trên UI. Nhưng bug nhiều khi nằm ở tầng data - UI hiển thị đúng nhưng DB lưu sai, hoặc ngược lại. Biết SQL là có thêm một lớp kiểm tra mà nhiều người bỏ qua.


Chuẩn bị trước khi bắt đầu

Bạn cần 2 thứ: một công cụ để chạy SQL và quyền truy cập database của dự án.

Công cụ phổ biến:

  • DBeaver - miễn phí, hỗ trợ hầu hết database (MySQL, PostgreSQL, SQL Server...). Mình dùng cái này nhiều nhất vì giao diện trực quan, không cần cài thêm gì
  • MySQL Workbench - dành riêng cho MySQL, cũng free
  • TablePlus - giao diện đẹp hơn, có bản free đủ dùng cho tester
  • pgAdmin - nếu project dùng PostgreSQL

344965 DBeaver là lựa chọn phổ biến nhất cho tester vì hỗ trợ nhiều loại database

Quyền truy cập:

Đây là bước quan trọng bạn cần xin từ team. Tester thường được cấp quyền READ ONLY (chỉ đọc) - tức là chỉ SELECT, không được INSERT, UPDATE, DELETE. Điều này đúng và bình thường, đừng lo.

Khi xin quyền, hỏi BA hoặc dev lead để lấy:

  • Host/IP của database server (thường là môi trường staging hoặc test, KHÔNG phải production)
  • Tên database
  • Username và password
  • Port (MySQL mặc định 3306, PostgreSQL mặc định 5432)

Lưu ý: Không bao giờ chạy query trực tiếp trên production trừ khi được phép rõ ràng. Môi trường test/staging là nơi bạn làm việc.

Cài xong DBeaver và kết nối được database rồi? Bắt đầu thôi.


SELECT và WHERE: Nền tảng của mọi query

SELECT là câu lệnh bạn sẽ dùng 90% thời gian. Nó có nghĩa đơn giản: "Lấy dữ liệu từ bảng này cho mình".

-- Lấy tất cả cột trong bảng users
SELECT * FROM users;

-- Lấy chỉ 2 cột cần thiết
SELECT email, full_name FROM users;

Dấu * nghĩa là "lấy hết tất cả cột". Mình thường dùng * khi muốn xem toàn bộ bảng có gì, sau đó mới chỉ định cột cụ thể.

344966 Câu SELECT đơn giản nhất - xuất phát điểm của mọi tester làm quen SQL

WHERE là điều kiện lọc. Không dùng WHERE thì query trả về toàn bộ dữ liệu - đôi khi hàng nghìn bản ghi. Dùng WHERE để thu hẹp đúng cái mình cần kiểm tra.

-- Tìm user có email cụ thể
SELECT * FROM users
WHERE email = '[email protected]';

-- Tìm đơn hàng có trạng thái 'pending'
SELECT * FROM orders
WHERE status = 'pending';

-- Kết hợp nhiều điều kiện bằng AND
SELECT * FROM orders
WHERE status = 'pending'
  AND created_at >= '2024-01-01';

-- Dùng OR khi muốn một trong hai điều kiện
SELECT * FROM orders
WHERE status = 'cancelled'
   OR status = 'refunded';

Ví dụ thực tế khi test:

Bạn vừa test tính năng đặt hàng. User đặt xong, UI hiển thị "Đơn hàng đã xác nhận". Muốn verify DB có lưu đúng không?

-- Kiểm tra đơn hàng vừa tạo có đúng status không
SELECT order_id, user_id, status, created_at
FROM orders
WHERE user_id = 123
  AND status = 'confirmed'
ORDER BY created_at DESC
LIMIT 1;

Nếu query trả về đúng 1 bản ghi với status = 'confirmed' - pass. Nếu không có gì hoặc status vẫn là 'pending' - bug.

Mình hay dùng thêm LIKE khi cần tìm kiếm gần đúng:

-- Tìm tất cả user có email chứa 'gmail'
SELECT * FROM users
WHERE email LIKE '%gmail.com';

-- Tìm sản phẩm tên bắt đầu bằng 'Áo'
SELECT * FROM products
WHERE product_name LIKE 'Áo%';

Dấu % là ký tự đại diện - có thể thay thế cho bất kỳ chuỗi nào. %gmail.com nghĩa là "chuỗi bất kỳ rồi kết thúc bằng gmail.com".


ORDER BY và LIMIT: Sắp xếp và giới hạn kết quả

Hai câu lệnh này đơn giản nhưng cực kỳ hữu dụng khi test.

ORDER BY sắp xếp kết quả theo một cột nào đó:

-- Lấy đơn hàng mới nhất trước (giảm dần)
SELECT * FROM orders
ORDER BY created_at DESC;

-- Sắp xếp sản phẩm theo giá tăng dần
SELECT product_name, price FROM products
ORDER BY price ASC;

DESC = descending (giảm dần). ASC = ascending (tăng dần, mặc định nếu không ghi).

LIMIT giới hạn số bản ghi trả về:

-- Chỉ lấy 10 bản ghi đầu tiên
SELECT * FROM orders
ORDER BY created_at DESC
LIMIT 10;

344967 ORDER BY DESC + LIMIT 10 - combo mình dùng hàng ngày để kiểm tra bản ghi mới nhất

Khi nào dùng trong test?

Rất hay gặp khi test tính năng phân trang (pagination) hoặc danh sách "Mới nhất". Ví dụ: UI hiển thị trang 1 có 10 đơn hàng, sắp xếp mới nhất trước. Query để đối chiếu:

SELECT order_id, status, created_at
FROM orders
WHERE user_id = 456
ORDER BY created_at DESC
LIMIT 10;

So sánh kết quả query với những gì UI hiển thị. Nếu thứ tự khác, hoặc thiếu/thừa bản ghi - đó là bug cần báo.

Bạn thấy đây đơn giản không? Mình cũng nghĩ vậy lúc đầu. Nhưng chính 2 câu lệnh này đã giúp mình tìm ra khá nhiều bug về sorting và pagination mà test tay thông thường rất khó phát hiện.


COUNT và GROUP BY: Đếm và tổng hợp dữ liệu

Đây là phần mình thấy nhiều fresher tester hay bỏ qua, nhưng thực ra lại dùng rất nhiều.

COUNT đếm số bản ghi:

-- Đếm tổng số user
SELECT COUNT(*) FROM users;

-- Đếm số đơn hàng đang 'pending'
SELECT COUNT(*) FROM orders
WHERE status = 'pending';

-- Đặt tên cho kết quả cho dễ đọc
SELECT COUNT(*) AS tong_don_hang
FROM orders
WHERE status = 'confirmed';

AS là alias - đặt tên hiển thị cho cột kết quả. Không ảnh hưởng gì đến data, chỉ giúp dễ đọc hơn.

GROUP BY nhóm dữ liệu lại theo một cột và thường đi kèm với COUNT hoặc SUM:

-- Đếm số đơn hàng theo từng trạng thái
SELECT status, COUNT(*) AS so_luong
FROM orders
GROUP BY status;

Kết quả sẽ trông như thế này:

status so_luong
pending 45
confirmed 230
cancelled 18
refunded 7

344968 GROUP BY hiển thị toàn cảnh phân bố dữ liệu - thứ mà UI riêng lẻ không cho bạn thấy

Ví dụ thực chiến:

UI hiển thị dashboard admin có ô "Tổng đơn hàng hôm nay: 52". Verify bằng query:

SELECT COUNT(*) AS don_hang_hom_nay
FROM orders
WHERE DATE(created_at) = CURDATE();

Nếu query trả về 52 - match. Nếu trả về 51 hay 53 - có vấn đề ở logic tính toán hoặc timezone.

Một case khác mình hay dùng: test tính năng thống kê doanh thu theo danh mục:

-- Doanh thu theo từng danh mục sản phẩm
SELECT 
    c.category_name,
    COUNT(o.order_id) AS so_don,
    SUM(o.total_amount) AS tong_doanh_thu
FROM orders o
JOIN products p ON o.product_id = p.product_id
JOIN categories c ON p.category_id = c.category_id
WHERE o.status = 'completed'
GROUP BY c.category_name
ORDER BY tong_doanh_thu DESC;

Query này hơi phức tạp hơn - có dùng JOIN mà mình sẽ giải thích ngay phần sau. Nhưng đây là dạng query rất thực tế khi test tính năng báo cáo/dashboard.


JOIN: Kết hợp dữ liệu từ nhiều bảng

Database thực tế không chỉ có 1 bảng. Thông tin user nằm bảng users, đơn hàng nằm bảng orders, sản phẩm nằm bảng products. JOIN là cách "ghép" các bảng này lại với nhau.

Loại JOIN bạn sẽ dùng nhiều nhất: INNER JOIN (hoặc chỉ cần viết JOIN).

-- Lấy thông tin đơn hàng kèm tên user
SELECT 
    o.order_id,
    u.full_name,
    u.email,
    o.status,
    o.total_amount
FROM orders o
JOIN users u ON o.user_id = u.user_id
WHERE o.status = 'pending';

Đọc query này ra tiếng Việt: "Lấy order_id, tên, email từ bảng orders ghép với bảng users (theo điều kiện user_id khớp nhau), lọc những đơn đang pending."

344969 JOIN như việc tra cứu chéo giữa 2 danh sách - ghép bằng ID chung

LEFT JOIN - dùng khi muốn lấy tất cả bản ghi từ bảng bên trái, kể cả không có dữ liệu khớp bên phải:

-- Lấy tất cả user, kể cả user chưa có đơn hàng nào
SELECT 
    u.full_name,
    u.email,
    COUNT(o.order_id) AS so_don_hang
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
GROUP BY u.user_id, u.full_name, u.email
ORDER BY so_don_hang DESC;

Case thực tế: Bạn test tính năng "Danh sách user" của admin. UI hiển thị cột "Số đơn hàng" kế bên mỗi user. Query trên giúp verify con số đó chính xác không - đặc biệt các user có 0 đơn hàng.

Thấy khó ở phần JOIN bình thường. Mình cũng mất 3-4 ngày mới quen cách đọc JOIN. Bí quyết là đọc to ra: "Bảng nào JOIN với bảng nào, dựa vào cột nào khớp". Làm vài lần là thành thói quen.