Lộ trình Kỹ sư QA (Tester): Xử lý Xác thực (Authentication) và Ủy quyền (Authorization) trong Tự động hóa Kiểm thử

Chào mừng bạn quay trở lại với loạt bài “Lộ trình học Kỹ sư QA (Tester)“! Sau khi đã tìm hiểu về các loại hình kiểm thử, xây dựng tư duy kiểm thử, và làm quen với các công cụ tự động hóa giao diện người dùng và API, đã đến lúc chúng ta đối mặt với một khía cạnh quan trọng và thường gây khó khăn trong tự động hóa: xử lý Xác thực (Authentication) và Ủy quyền (Authorization).

Hầu hết các ứng dụng hiện đại đều yêu cầu người dùng đăng nhập (xác thực) và có các quyền truy cập khác nhau dựa trên vai trò của họ (ủy quyền). Kiểm thử tự động các luồng này là điều bắt buộc để đảm bảo an toàn và tính đúng đắn của ứng dụng. Tuy nhiên, việc quản lý trạng thái đăng nhập, các loại người dùng khác nhau và thông tin nhạy cảm như mật khẩu trong code tự động có thể khá phức tạp. Bài viết này sẽ đi sâu vào cách tiếp cận hiệu quả để xử lý Auth/Auth trong các script tự động hóa của bạn.

Xác thực (Authentication) và Ủy quyền (Authorization) là gì?

Trước khi đi vào chi tiết kỹ thuật, hãy làm rõ hai khái niệm cơ bản này. Dù thường đi đôi với nhau, chúng là hai thứ khác biệt:

  • Xác thực (Authentication): Là quá trình xác minh danh tính của người dùng hoặc hệ thống. Câu hỏi đặt ra là: “Bạn là ai?”. Các phương pháp xác thực phổ biến bao gồm nhập tên người dùng/mật khẩu, sử dụng chứng chỉ số, token, hoặc xác thực đa yếu tố (MFA).
  • Ủy quyền (Authorization): Là quá trình xác định những gì người dùng đã được xác thực được phép làm hoặc truy cập. Câu hỏi đặt ra là: “Bạn có quyền làm điều này không?”. Ủy quyền thường dựa trên vai trò (roles) hoặc quyền hạn (permissions) được gán cho người dùng. Ví dụ: admin có thể truy cập tất cả các trang, trong khi người dùng thông thường chỉ có thể xem hồ sơ của họ.

Trong kiểm thử tự động, chúng ta cần kiểm thử cả hai khía cạnh này một cách kỹ lưỡng:

  • Kiểm thử xác thực: Đảm bảo chỉ người dùng hợp lệ mới đăng nhập được, các trường hợp sai (sai mật khẩu, tài khoản bị khóa, v.v.) được xử lý đúng.
  • Kiểm thử ủy quyền: Đảm bảo người dùng chỉ truy cập và thực hiện các hành động mà họ được phép làm, và không thể truy cập hoặc thực hiện các hành động bị cấm đối với vai trò của họ.

Tại sao Xử lý Auth/Auth quan trọng trong Tự động hóa Kiểm thử?

Xử lý Auth/Auth một cách hiệu quả trong tự động hóa không chỉ giới hạn ở việc kiểm thử chức năng đăng nhập/đăng xuất. Nó là nền tảng cho hầu hết các kịch bản kiểm thử tiếp theo.

  1. Nền tảng cho các Test Case Khác: Hầu hết các chức năng quan trọng của ứng dụng chỉ có thể truy cập sau khi người dùng đăng nhập. Nếu không xử lý xác thực tự động, bạn không thể kiểm thử các luồng chính của ứng dụng.
  2. Kiểm thử Ủy quyền: Để kiểm thử các quyền khác nhau, bạn cần tự động hóa việc đăng nhập bằng các tài khoản có vai trò khác nhau (admin, user, guest, v.v.) và sau đó kiểm thử các chức năng, giao diện, API endpoints có thể truy cập được bởi từng vai trò.
  3. Đảm bảo An toàn Cơ bản: Mặc dù đây không phải là kiểm thử bảo mật nâng cao (Giới thiệu Kiểm thử Bảo mật và OWASP Top 10), việc tự động hóa kiểm thử các trường hợp đăng nhập sai, truy cập trái phép giúp phát hiện các lỗ hổng ủy quyền cơ bản.
  4. Giảm Sự Phụ thuộc vào Kiểm thử Thủ công: Các kịch bản đăng nhập/đăng xuất lặp đi lặp lại rất tốn thời gian khi kiểm thử thủ công (Kiểm thử Thủ công 101). Tự động hóa giúp tiết kiệm thời gian và đảm bảo tính nhất quán.
  5. Tích hợp CI/CD: Để bộ kiểm thử tự động chạy trong quy trình CI/CD (Tự động hóa Kiểm thử trong CI/CD), nó cần có khả năng tự động xử lý xác thực mà không cần can thiệp thủ công.

Các Kịch bản (Scenarios) Auth/Auth phổ biến cần Tự động hóa Kiểm thử

Dưới đây là một số kịch bản điển hình mà bạn nên đưa vào bộ kiểm thử tự động của mình:

  • Đăng nhập thành công với thông tin hợp lệ (cho các vai trò khác nhau).
  • Đăng nhập thất bại với thông tin không hợp lệ (sai tên người dùng, sai mật khẩu).
  • Đăng nhập với tài khoản bị khóa hoặc chưa được kích hoạt.
  • Luồng đăng xuất.
  • Kiểm tra “ghi nhớ đăng nhập” (Remember Me).
  • Kiểm tra hết hạn phiên làm việc (Session Expiration).
  • Kiểm tra truy cập các trang hoặc chức năng yêu cầu đăng nhập khi chưa đăng nhập (nên chuyển hướng đến trang đăng nhập hoặc hiển thị thông báo lỗi).
  • Đối với các vai trò khác nhau (Admin, User, Editor, Guest…):
    • Kiểm tra khả năng hiển thị của các phần tử UI (menu, nút, link).
    • Kiểm tra khả năng truy cập các URL hoặc trang cụ thể.
    • Kiểm tra khả năng thực hiện các hành động (tạo, đọc, cập nhật, xóa – CRUD) trên dữ liệu hoặc tài nguyên.
    • Kiểm tra phản hồi của API khi cố gắng truy cập các endpoint yêu cầu quyền cao hơn. (Tự động hóa Kiểm thử Backend rất hữu ích ở đây).
  • Kiểm tra luồng đăng ký người dùng mới (nếu có).
  • Kiểm tra luồng quên mật khẩu/đặt lại mật khẩu (thường khó tự động hóa hoàn toàn do yêu cầu truy cập email, nhưng có thể tự động hóa một phần). (Cách Kiểm thử Email Hiệu quả có thể giúp ích).

Thách thức khi Tự động hóa Kiểm thử Auth/Auth

Tự động hóa Auth/Auth mang lại nhiều lợi ích nhưng cũng đi kèm với các thách thức:

  • Quản lý Thông tin Đăng nhập (Credentials Management): Lưu trữ tên người dùng và mật khẩu trong code hoặc file cấu hình là không an toàn. Cần có giải pháp quản lý bí mật (Quản lý Bí mật (Secrets Management)) như sử dụng biến môi trường, HashiCorp Vault, AWS Secrets Manager, CyberArk, v.v.
  • Thay đổi Trạng thái (Statefulness): Phiên làm việc (session) hoặc token có thể hết hạn, yêu cầu phải đăng nhập lại. Script tự động cần xử lý trường hợp này một cách gracefully.
  • Xác thực Đa Yếu tố (MFA): Các phương thức xác thực bổ sung như gửi mã SMS, sử dụng ứng dụng authenticator, hoặc xác thực sinh trắc học rất khó hoặc không thể tự động hóa hoàn toàn. Cần có sự phối hợp với đội phát triển để có “cửa hậu” cho môi trường kiểm thử (ví dụ: bỏ qua MFA trong môi trường DEV/STG) hoặc sử dụng các dịch vụ giả lập MFA.
  • Captcha: Tương tự MFA, Captcha được thiết kế để ngăn chặn bot, gây khó khăn cho tự động hóa. Cần loại bỏ Captcha trong môi trường kiểm thử tự động.
  • Các Cơ chế Xác thực Phức tạp: OAuth2, OpenID Connect, SAML… có các luồng phức tạp hơn đăng nhập username/password đơn giản. Việc tự động hóa có thể yêu cầu hiểu sâu hơn về các giao thức này.
  • Quản lý Dữ liệu Kiểm thử (Test Data Management): Cần có một bộ tài khoản người dùng kiểm thử đa dạng với các vai trò và trạng thái khác nhau, và quản lý chúng hiệu quả.

Các Chiến lược Xử lý Xác thực trong Tự động hóa

Có nhiều cách tiếp cận để xử lý xác thực trong tự động hóa, mỗi cách có ưu nhược điểm riêng:

1. Đăng nhập qua UI (UI Login)

  • Cách thực hiện: Tự động hóa các bước nhập tên người dùng, mật khẩu vào form đăng nhập trên giao diện web/ứng dụng, sau đó click nút “Đăng nhập”.
  • Ưu điểm: Kiểm thử luồng đăng nhập thực tế mà người dùng cuối trải qua. Dễ hiểu và thực hiện với các công cụ tự động hóa UI (Selenium, Playwright, Puppeteer).
  • Nhược điểm: Chậm. Kịch bản đăng nhập rất dễ bị ảnh hưởng bởi những thay đổi nhỏ trên giao diện (yếu tố định vị – locators thay đổi). Nếu mọi test case đều bắt đầu bằng đăng nhập UI, bộ test suite sẽ chạy rất lâu và dễ bị lỗi. Không hiệu quả để kiểm thử ủy quyền cho nhiều vai trò trong cùng một lần chạy.
# Ví dụ Pseudocode (Playwright/Selenium style)
def login_via_ui(page, username, password):
    page.fill("#usernameInput", username)
    page.fill("#passwordInput", password)
    page.click("#loginButton")
    # Chờ trang tải xong hoặc phần tử sau đăng nhập xuất hiện
    page.wait_for_selector("#dashboardHeader") 

2. Đăng nhập qua API (API Login) – Lấy Token hoặc Session Cookie

  • Cách thực hiện: Thay vì dùng UI, thực hiện một request API (thường là POST) đến endpoint đăng nhập với payload chứa tên người dùng và mật khẩu. Server sẽ trả về một token (ví dụ: JWT) hoặc thiết lập session cookie trong response. Sau đó, sử dụng token/cookie này trong header của các request API hoặc inject cookie vào trình duyệt (đối với kiểm thử UI).
  • Ưu điểm: Nhanh hơn rất nhiều so với đăng nhập UI. Ổn định hơn vì ít bị ảnh hưởng bởi thay đổi UI. Dễ dàng sử dụng cho cả kiểm thử API và UI. Có thể dễ dàng lấy token cho nhiều người dùng/vai trò khác nhau.
  • Nhược điểm: Yêu cầu endpoint API đăng nhập phải khả dụng và ổn định. Cần hiểu cách ứng dụng xử lý token/session (đặt ở header nào? tên cookie là gì?). Không kiểm thử được giao diện đăng nhập thực tế (nhưng bạn có thể có một test case UI riêng cho luồng đăng nhập chính).
# Ví dụ Pseudocode (Sử dụng fetch API hoặc thư viện request)
async function login_via_api(username, password) {
    const response = await fetch("https://your-app.com/api/login", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ username: username, password: password })
    });
    const data = await response.json();
    // Giả sử API trả về token trong response body
    return data.token; 
}

// Sử dụng token trong request API tiếp theo
async function fetchData(token) {
    const response = await fetch("https://your-app.com/api/data", {
        method: "GET",
        headers: { "Authorization": `Bearer ${token}` } // Thêm token vào header
    });
    return await response.json();
}

Đối với kiểm thử UI sử dụng API Login, sau khi lấy được token hoặc session cookie qua API, bạn có thể inject chúng vào trình duyệt trước khi truy cập các trang cần xác thực. Các framework như Playwright hỗ trợ điều này rất tốt:

# Ví dụ Pseudocode (Playwright) - Inject Cookie sau API login
from playwright.sync_api import sync_playwright
import requests # Dùng thư viện requests để gọi API

def login_and_get_cookie(username, password):
    login_url = "https://your-app.com/api/login"
    payload = {"username": username, "password": password}
    response = requests.post(login_url, json=payload)
    response.raise_for_status() # Check for errors
    # Giả sử API trả về cookie "sessionid" trong response header "Set-Cookie"
    # Việc xử lý Set-Cookie header có thể phức tạp, thư viện requests tự động quản lý cookies
    # hoặc bạn cần parse header thủ công nếu dùng thư viện khác.
    # Cách đơn giản hơn là nếu API trả về token, dùng token đó.
    # Nếu API set cookies, requests sẽ lưu trữ chúng trong session object.
    return response.cookies # Trả về đối tượng cookie jar

with sync_playwright() as p:
    browser = p.chromium.launch()
    context = browser.new_context()

    # Lấy cookie qua API
    user_cookies = login_and_get_cookie("testuser", "password")

    # Thêm cookie vào context của browser
    # Chuyển đổi requests cookie jar sang format Playwright
    playwright_cookies = []
    for cookie in user_cookies:
        playwright_cookies.append({
            'name': cookie.name,
            'value': cookie.value,
            'url': cookie.url,
            'domain': cookie.domain,
            'path': cookie.path,
            'secure': cookie.secure,
            'httpOnly': cookie.has_nonstandard_attr('HttpOnly'), # requests doesn't have this attr easily
            'expires': cookie.expires if cookie.expires else -1 # expires time in seconds
        })

    context.add_cookies(playwright_cookies)

    # Bây giờ context đã có cookie xác thực, bạn có thể truy cập các trang cần login
    page = context.new_page()
    page.goto("https://your-app.com/dashboard")
    # Tiếp tục các bước kiểm thử UI khác...

    browser.close()

Phương pháp đăng nhập qua API kết hợp inject session/token vào trình duyệt là chiến lược được ưa chuộng nhất cho tự động hóa UI vì nó kết hợp tốc độ và sự ổn định của API với khả năng kiểm thử giao diện người dùng.

3. Sử dụng Trạng thái Đăng nhập Đã Lưu (State File / Storage State)

  • Cách thực hiện: Thực hiện đăng nhập UI hoặc API một lần duy nhất, sau đó lưu lại trạng thái đăng nhập (cookies, local storage, session storage, token) vào một file (thường là JSON). Các test case sau đó có thể tải trạng thái này lên browser context của chúng thay vì thực hiện lại quá trình đăng nhập.
  • Ưu điểm: Cực kỳ nhanh chóng cho các test case chạy sau lần đăng nhập đầu tiên. Giảm sự phụ thuộc vào luồng đăng nhập ở đầu mỗi test.
  • Nhược điểm: Trạng thái đăng nhập có thể hết hạn theo thời gian, cần có cơ chế làm mới hoặc tạo lại file trạng thái định kỳ. Ít phù hợp nếu bạn cần kiểm thử rất nhiều vai trò khác nhau trong cùng một lần chạy test suite.
# Ví dụ Pseudocode (Playwright) - Lưu và tải trạng thái
# Lần chạy đầu tiên (hoặc khi trạng thái hết hạn):
with sync_playwright() as p:
    browser = p.chromium.launch()
    page = browser.new_page()
    # Thực hiện đăng nhập (qua UI hoặc API rồi inject)
    page.goto("https://your-app.com/login")
    page.fill("#usernameInput", "testuser")
    page.fill("#passwordInput", "password")
    page.click("#loginButton")
    page.wait_for_url("https://your-app.com/dashboard")
    # Lưu trạng thái
    page.context.storage_state(path="state.json")
    browser.close()

# Các lần chạy test sau:
with sync_playwright() as p:
    # Tải trạng thái từ file
    context = p.chromium.launch().new_context(storage_state="state.json")
    page = context.new_page()
    # Truy cập trang cần login mà không cần đăng nhập lại
    page.goto("https://your-app.com/dashboard")
    # ... tiếp tục test ...
    browser.close()

Các Chiến lược Xử lý Ủy quyền trong Tự động hóa

Kiểm thử ủy quyền tập trung vào việc xác minh quyền truy cập và khả năng thực hiện hành động của các vai trò người dùng khác nhau.

1. Sử dụng Nhiều Tài khoản Kiểm thử với Các Vai trò Khác nhau

  • Cách thực hiện: Tạo một bộ tài khoản kiểm thử chuyên dụng, mỗi tài khoản được gán một vai trò cụ thể (ví dụ: user_admin, user_editor, user_viewer).
  • Trong tự động hóa: Sử dụng các tài khoản này để đăng nhập (thường là qua API login cho nhanh), sau đó thực hiện các kiểm thử chức năng và giao diện người dùng với quyền của tài khoản đó.

2. Kiểm thử Truy cập Tài nguyên và Hành động

  • Kiểm thử Giao diện người dùng (UI):
    • Xác minh các phần tử UI (menu items, buttons, links) chỉ hiển thị hoặc được kích hoạt cho các vai trò có quyền tương ứng.
    • Thử truy cập trực tiếp các URL/trang chỉ dành cho vai trò khác và xác minh rằng ứng dụng hiển thị thông báo lỗi hoặc chuyển hướng đến trang cấm/trang đăng nhập.
  • Kiểm thử API:
    • Sau khi đăng nhập bằng một vai trò nhất định (qua API), gửi request đến các API endpoint khác nhau (GET, POST, PUT, DELETE).
    • Xác minh mã trạng thái HTTP trả về (ví dụ: 200 OK cho phép truy cập, 401 Unauthorized nếu chưa xác thực, 403 Forbidden nếu đã xác thực nhưng không đủ quyền).
    • Xác minh nội dung phản hồi (response body) có chứa dữ liệu đúng với quyền hạn hay không (ví dụ: người dùng thông thường không nhận được danh sách tất cả người dùng). (Tự động hóa Kiểm thử Backend là công cụ lý tưởng cho việc này).
# Ví dụ Pseudocode (Kiểm thử ủy quyền API với thư viện requests)
import requests

BASE_URL = "https://your-app.com/api"

def login_and_get_token(username, password):
    response = requests.post(f"{BASE_URL}/login", json={"username": username, "password": password})
    response.raise_for_status()
    return response.json().get("token")

def test_admin_can_access_users_api():
    admin_token = login_and_get_token("admin_user", "admin_password")
    headers = {"Authorization": f"Bearer {admin_token}"}
    response = requests.get(f"{BASE_URL}/users", headers=headers)
    assert response.status_code == 200
    # Thêm kiểm tra nội dung response nếu cần

def test_normal_user_cannot_access_users_api():
    normal_token = login_and_get_token("normal_user", "normal_password")
    headers = {"Authorization": f"Bearer {normal_token}"}
    response = requests.get(f"{BASE_URL}/users", headers=headers)
    assert response.status_code == 403 # Expected Forbidden status

Thực hiện trong Framework Tự động hóa

Để xử lý Auth/Auth một cách có tổ chức và dễ bảo trì trong framework tự động hóa, bạn nên áp dụng các pattern sau:

  1. Module/Class Xử lý Xác thực: Tạo một module hoặc class riêng chuyên xử lý các hoạt động liên quan đến đăng nhập và đăng xuất. Module này có thể chứa các hàm như `login_as(user_role)`, `logout()`, `get_token(username, password)`, `inject_cookie(cookie_data)`. Điều này giúp tập trung logic xác thực vào một nơi, tránh lặp code và dễ dàng cập nhật khi luồng đăng nhập thay đổi.
  2. Sử dụng Hooks hoặc Fixtures: Hầu hết các test framework (như Pytest, JUnit, TestNG, Cypress) đều hỗ trợ khái niệm hooks (beforeEach, afterEach) hoặc fixtures. Sử dụng chúng để tự động đăng nhập trước mỗi test case hoặc nhóm test case, và đăng xuất hoặc dọn dẹp sau đó.
    • `beforeEachTest/Method`: Đăng nhập trước mỗi test case.
    • `beforeAll/Class`: Đăng nhập một lần cho tất cả test case trong một class/file (phù hợp nếu test case không làm thay đổi trạng thái đăng nhập).
    • `afterEachTest/Method`: Đăng xuất hoặc làm sạch trạng thái sau mỗi test case.
    • `afterAll/Class`: Đăng xuất hoặc làm sạch trạng thái sau tất cả test case.

    Việc sử dụng hooks/fixtures giúp giữ cho từng test case tập trung vào logic kiểm thử chính mà không phải bận tâm về việc đăng nhập lại mỗi lần.

  3. Quản lý Dữ liệu Kiểm thử Người dùng: Không nhúng thông tin đăng nhập trực tiếp vào test case. Sử dụng một nguồn dữ liệu riêng biệt (file JSON, YAML, cơ sở dữ liệu kiểm thử) để lưu trữ tên người dùng và vai trò. Mật khẩu nên được lưu trữ an toàn bằng các giải pháp Secrets Management (Quản lý Bí mật (Secrets Management)) và truy cập động trong quá trình chạy test.
# Ví dụ Pseudocode (Pytest Fixtures)
import pytest
import requests # Hoặc Playwright/Selenium Page Object

# Giả sử có một dictionary lưu trữ vai trò và thông tin đăng nhập (ngoài đời nên dùng Secrets Management)
USERS_DATA = {
    "admin": {"username": "admin_user", "password": "admin_password"},
    "normal": {"username": "normal_user", "password": "normal_password"},
}

@pytest.fixture(scope="function")
def login_as_admin(request):
    user_info = USERS_DATA["admin"]
    # Logic đăng nhập (qua API hoặc UI, trả về đối tượng đã đăng nhập/token/session)
    print(f"Đăng nhập với vai trò: {user_info['username']}")
    # Ví dụ đơn giản trả về token (dùng thư viện request)
    response = requests.post("https://your-app.com/api/login", json=user_info)
    response.raise_for_status()
    token = response.json().get("token")

    yield token # Cung cấp token cho test case sử dụng fixture

    # Logic đăng xuất hoặc dọn dẹp sau test case
    print(f"Đăng xuất hoặc dọn dẹp cho: {user_info['username']}")

@pytest.fixture(scope="function")
def login_as_normal_user(request):
    user_info = USERS_DATA["normal"]
    print(f"Đăng nhập với vai trò: {user_info['username']}")
    response = requests.post("https://your-app.com/api/login", json=user_info)
    response.raise_for_status()
    token = response.json().get("token")
    yield token
    print(f"Đăng xuất hoặc dọn dẹp cho: {user_info['username']}")


# Sử dụng fixture trong test case
def test_admin_dashboard_access(login_as_admin):
    admin_token = login_as_admin
    headers = {"Authorization": f"Bearer {admin_token}"}
    response = requests.get("https://your-app.com/api/admin/dashboard", headers=headers)
    assert response.status_code == 200

def test_normal_user_dashboard_access(login_as_normal_user):
    normal_token = login_as_normal_user
    headers = {"Authorization": f"Bearer {normal_token}"}
    response = requests.get("https://your-app.com/api/admin/dashboard", headers=headers)
    assert response.status_code == 403 # Expect Forbidden

Trong ví dụ trên, các fixture `login_as_admin` và `login_as_normal_user` xử lý logic đăng nhập và cung cấp token cho test case sử dụng chúng. Pytest sẽ tự động chạy fixture trước khi chạy test case và thực thi phần code sau `yield` (cleanup) sau khi test case hoàn thành.

Bảng Tóm tắt Các Phương pháp Xử lý Xác thực trong Tự động hóa

Phương pháp Cách hoạt động Ưu điểm cho Tự động hóa Nhược điểm cho Tự động hóa Trường hợp sử dụng phù hợp
Đăng nhập UI (UI Login) Tự động hóa các thao tác trên giao diện người dùng để đăng nhập. Kiểm thử luồng người dùng cuối thực tế; Dễ cài đặt ban đầu với các công cụ UI. Rất chậm; Dễ bị ảnh hưởng bởi thay đổi UI; Tốn tài nguyên. Kiểm thử chính luồng đăng nhập/đăng xuất UI; Khi không có API login.
Đăng nhập API (Lấy Token/Cookie) + Sử dụng trong API Test Gọi API đăng nhập để nhận token hoặc session cookie, sử dụng trong các request API sau. Rất nhanh và ổn định; Lý tưởng cho kiểm thử API. Không kiểm thử giao diện người dùng; Yêu cầu endpoint API login. Kiểm thử API; Thiết lập trạng thái cho kiểm thử API.
Đăng nhập API (Lấy Token/Cookie) + Inject vào Trình duyệt (cho UI Test) Gọi API đăng nhập, lấy token/cookie, sau đó inject vào browser context/session trước khi chạy test UI. Nhanh hơn đáng kể so với UI login; Ổn định hơn; Vẫn kiểm thử được giao diện người dùng. Yêu cầu endpoint API login; Cần kỹ thuật inject trạng thái vào browser. Thiết lập trạng thái đăng nhập cho hầu hết các test case UI; Tối ưu hóa tốc độ chạy test suite.
Sử dụng Trạng thái Đã Lưu (Storage State File) Đăng nhập 1 lần (UI/API), lưu trạng thái (cookies, local storage, etc.) vào file, tải lại cho các test case sau. Cực nhanh sau lần lưu trạng thái đầu tiên; Giảm thiểu logic đăng nhập trong test case. Trạng thái có thể hết hạn; Không phù hợp khi cần nhiều vai trò khác nhau trong cùng một lần chạy suite. Khi các test case cần đăng nhập với cùng một tài khoản; Khi tốc độ là ưu tiên hàng đầu và trạng thái đăng nhập tương đối ổn định.

Các Công cụ Hỗ trợ

Việc xử lý Auth/Auth sẽ dễ dàng hơn với sự hỗ trợ của các công cụ phù hợp:

  • Công cụ Tự động hóa UI: Selenium, Playwright, Cypress (Cypress cho Kiểm thử API và UI): Giúp tự động hóa các thao tác UI (nếu chọn UI login) hoặc inject cookies/storage state (nếu chọn API login).
  • Công cụ Kiểm thử API: Postman/Newman (Tự động hóa Kiểm thử Backend với Postman, Newman và REST Assured), Rest-Assured, Cypress: Dùng để gọi API đăng nhập và lấy token/session.
  • Công cụ Quản lý Bí mật (Secrets Management): HashiCorp Vault, AWS Secrets Manager, CyberArk, biến môi trường của CI/CD tools (Jenkins, GitLab CI, CircleCI): Bắt buộc để lưu trữ mật khẩu và thông tin nhạy cảm khác một cách an toàn.
  • Framework Kiểm thử: Pytest (Python), JUnit/TestNG (Java), Mocha/Jest (JavaScript): Cung cấp cơ chế fixtures/hooks để quản lý trạng thái đăng nhập trước và sau test case.

Các Thực hành Tốt Nhất (Best Practices)

  • Không Hardcode Credentials: Tuyệt đối không ghi trực tiếp tên người dùng và mật khẩu vào code hoặc file cấu hình không được mã hóa. Sử dụng các giải pháp Secrets Management. (Quản lý Bí mật (Secrets Management) và QA: Ngăn chặn Rò rỉ Dữ liệu trong Kiểm thử).
  • Sử dụng Tài khoản Kiểm thử Chuyên dụng: Không sử dụng tài khoản thật (production) để kiểm thử tự động. Tạo các tài khoản kiểm thử trên môi trường non-production (DEV, STG).
  • Tối ưu hóa Đăng nhập cho Tự động hóa: Ưu tiên sử dụng API login kết hợp inject trạng thái vào trình duyệt cho các test case UI để tăng tốc độ và độ ổn định. Chỉ sử dụng UI login khi cần kiểm thử chính luồng đăng nhập.
  • Quản lý Dữ liệu Kiểm thử: Có chiến lược rõ ràng cho việc tạo, sử dụng và dọn dẹp dữ liệu kiểm thử người dùng và các tài nguyên liên quan đến ủy quyền.
  • Thiết kế Test Case Độc lập: Mỗi test case nên độc lập với các test case khác. Sử dụng hooks/fixtures để thiết lập trạng thái (đăng nhập) và dọn dẹp sau mỗi test.
  • Xử lý Hết hạn Phiên làm việc: Code tự động cần có khả năng phát hiện khi phiên làm việc hết hạn và thực hiện đăng nhập lại hoặc bỏ qua test case đó nếu không thể phục hồi.
  • Phối hợp với Dev: Trao đổi với đội phát triển về các yêu cầu cho môi trường kiểm thử (ví dụ: tắt MFA, Captcha, cung cấp API login chuyên dụng) để hỗ trợ tự động hóa.
  • Kiểm thử cả 2 khía cạnh Auth & Auth: Đừng chỉ kiểm thử đăng nhập. Quan trọng không kém là kiểm thử xem người dùng đã đăng nhập có đúng quyền hạn hay không.
  • Ưu tiên dựa trên Rủi ro: Tập trung tự động hóa các kịch bản Auth/Auth có rủi ro cao nhất trước, ví dụ: đăng nhập/đăng xuất chính, kiểm thử vai trò Admin, kiểm thử truy cập dữ liệu nhạy cảm. (Ưu tiên Kiểm thử của Bạn).
  • Kết luận

    Xử lý Xác thực và Ủy quyền là một bước quan trọng và không thể thiếu trong hành trình xây dựng bộ kiểm thử tự động mạnh mẽ và đáng tin cậy, đặc biệt là với các hệ thống phức tạp. Bằng việc hiểu rõ sự khác biệt giữa Authentication và Authorization, lựa chọn chiến lược phù hợp (ưu tiên API login + inject trạng thái), áp dụng các pattern thiết kế tốt (modules, fixtures/hooks) và tuân thủ các thực hành bảo mật (secrets management), bạn sẽ có thể xây dựng các script tự động hóa hiệu quả, giúp kiểm thử toàn diện các luồng chức năng và đảm bảo an toàn cho ứng dụng.

    Hãy dành thời gian tìm hiểu sâu hơn về các phương pháp này và áp dụng chúng vào framework tự động hóa của bạn. Điều này sẽ là nền tảng vững chắc cho những bước tiếp theo trong Lộ trình Kỹ sư QA (Tester).

Chỉ mục