Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

Variables — types và scope cụ thể

API Testing with Postman Advanced Bài 6/60

Mở đầu — vì sao bài này quan trọng

Nếu bạn từng mở một collection Postman của người khác và thấy đầy những dòng như {{base_url}}/api/v2/{{user_id}}, rồi tự hỏi "cái này lấy giá trị từ đâu ra?" — thì bài học hôm nay chính là câu trả lời. Variables (biến) là hệ thần kinh của mọi collection Postman chuyên nghiệp. Không có chúng, bạn buộc phải hard-code (viết cứng) đường dẫn, token, ID vào từng request. Và khi công ty chuyển từ môi trường staging sang production, bạn sẽ phải sửa tay hàng trăm request — một cơn ác mộng đủ để khiến bất kỳ QA nào nghỉ việc.

Điều khiến nhiều học viên bối rối không phải là "biến là gì" (ai cũng hiểu), mà là Postman có tới 5 loại phạm vi (scope) biến khác nhau, chúng chồng lấn lên nhau theo một thứ tự ưu tiên rất cụ thể. Hiểu sai thứ tự này là nguyên nhân số một của những bug kiểu "tôi đã set biến rồi mà sao request vẫn dùng giá trị cũ?". Bài học này sẽ mổ xẻ từng loại biến, làm rõ khi nào dùng loại nào, và đặc biệt là cơ chế phân giải (resolution) khi hai biến trùng tên tồn tại ở hai scope khác nhau.

Đây là kiến thức nền mà bạn sẽ dùng lại trong mọi bài sau — từ chained requests, authorization, cho tới data-driven testing. Nắm chắc nó ngay bây giờ, bạn sẽ tiết kiệm được vô số giờ debug sau này.

Khái niệm cốt lõi

Biến trong Postman thực chất là gì

Về bản chất, một biến trong Postman là một cặp key–value (tên–giá trị) mà bạn có thể tham chiếu ở bất cứ đâu bằng cú pháp hai dấu ngoặc nhọn: {{tên_biến}}. Khi request được gửi đi, Postman sẽ thay thế {{tên_biến}} bằng giá trị thật của nó. Bạn có thể dùng biến trong URL, headers, request body, params, và cả trong các script (pre-request và test).

Điểm mấu chốt phân biệt các biến không nằm ở giá trị, mà ở phạm vi sống (scope) của chúng: biến tồn tại ở đâu, ai nhìn thấy được, và tồn tại trong bao lâu.

Năm loại scope và thứ tự ưu tiên

Postman có 5 scope, xếp từ rộng nhất (ưu tiên thấp nhất) đến hẹp nhất (ưu tiên cao nhất):

  • Global — Biến toàn cục, dùng chung cho cả workspace, bất kể bạn đang chọn environment nào. Đây là scope rộng nhất. Thích hợp cho những giá trị hiếm khi đổi và dùng ở khắp nơi.
  • Collection — Biến gắn với một collection cụ thể. Mọi request trong collection đó đều truy cập được, và nó "đi kèm" collection khi bạn export/chia sẻ. Rất phù hợp cho base_url của một dịch vụ.
  • Environment — Biến gắn với một môi trường (dev/staging/production). Bạn chọn environment nào thì bộ biến của môi trường đó được kích hoạt. Đây là công cụ chính để chuyển đổi giữa các môi trường.
  • Data — Biến đến từ file dữ liệu ngoài (CSV hoặc JSON) khi chạy collection bằng Collection Runner hoặc Newman. Mỗi vòng lặp (iteration) nạp một dòng dữ liệu. Biến data chỉ sống trong lúc chạy.
  • Local — Biến tạm, tạo bằng script trong lúc request đang chạy (ví dụ pm.variables.set()). Sống trong đúng một lần thực thi request/collection rồi biến mất. Đây là scope hẹp nhất, ưu tiên cao nhất.
Quy tắc vàng cần thuộc lòng: khi hai biến trùng tên ở nhiều scope, Postman luôn chọn giá trị ở scope hẹp hơn. Thứ tự phân giải là: Local > Data > Environment > Collection > Global. Nghĩa là nếu bạn có base_url ở cả Global và Environment, giá trị Environment sẽ thắng.

Static vs Dynamic — hai họ biến khác nhau

Bên cạnh phân loại theo scope, biến còn được chia theo cách sinh ra giá trị:

  • Static (tĩnh): Là biến bạn tự đặt giá trị. Ví dụ bạn set base_url = https://api.tiki.vn. Giá trị đứng yên cho đến khi bạn (hoặc một script) thay đổi nó. Toàn bộ 5 scope ở trên đều là biến static.
  • Dynamic (động): Là biến do Postman dựng sẵn, luôn có tiền tố dấu $, và sinh ra giá trị mới mỗi lần bạn dùng. Bạn không set chúng — bạn chỉ gọi ra. Chúng cực kỳ hữu ích để tạo dữ liệu test ngẫu nhiên, tránh trùng lặp.
Một vài dynamic variable hay dùng nhất:

  • {{$guid}} — sinh một UUID v4 ngẫu nhiên, ví dụ f47ac10b-58cc-4372-a567-0e02b2c3d479.
  • {{$timestamp}} — dấu thời gian Unix hiện tại (giây), ví dụ 1719450000.
  • {{$randomInt}} — số nguyên ngẫu nhiên từ 0 đến 1000.
  • {{$randomEmail}} — một email giả hợp lệ, ví dụ Kaya.Nguyen@yahoo.com.
  • {{$randomFirstName}}, {{$randomFullName}}, {{$randomPhoneNumber}} — dữ liệu nhân thân giả.
  • {{$isoTimestamp}} — thời gian dạng ISO 8601, ví dụ 2026-06-27T03:00:00.000Z.
Postman hỗ trợ hơn 200 dynamic variable (dựa trên thư viện Faker.js). Trong test thực tế, chúng giúp bạn tạo tài khoản mới, đơn hàng mới mà không lo đụng dữ liệu cũ.

Biến trong script — ba API tương ứng ba scope

Trong pre-request và test script, bạn thao tác biến qua các đối tượng pm.* khác nhau, mỗi cái ứng với một scope:

  • pm.globals.set("key", "value") / pm.globals.get("key") — thao tác biến Global.
  • pm.collectionVariables.set(...) — thao tác biến Collection.
  • pm.environment.set(...) — thao tác biến Environment.
  • pm.variables.set(...) — tạo/đọc biến Local (tạm thời) và cũng là cách đọc gộp theo đúng thứ tự ưu tiên. Khi bạn pm.variables.get("base_url"), Postman tự tìm từ scope hẹp đến rộng và trả về giá trị thắng.
Ghi nhớ mẹo này: dùng pm.variables.get() để đọc (vì nó tôn trọng thứ tự ưu tiên), nhưng dùng pm.environment.set() hay pm.collectionVariables.set() để ghi vào đúng scope bạn muốn giá trị tồn tại lâu dài.

Tình huống thực tế

Ví dụ 1 — Tiki chuyển môi trường mà không sửa một request nào

Đội QA của một sàn thương mại điện tử giả định giống Tiki có một collection 80 request để test API giỏ hàng và thanh toán. Ban đầu, bạn thực tập viên Minh hard-code toàn bộ URL là https://staging-api.tiki.vn/.... Khi cần chạy smoke test trên production, Minh phải mở từng request sửa tay — mất 40 phút và bỏ sót 3 request vẫn trỏ về staging, suýt tạo đơn hàng thật trên hệ thống production.

Cách làm đúng: đặt một biến Environment tên base_url. Tạo hai environment — Staging với base_url = https://staging-api.tiki.vn, và Production với base_url = https://api.tiki.vn. Mọi request viết là {{base_url}}/carts/{{cart_id}}. Giờ chuyển môi trường chỉ là chọn từ dropdown góc phải màn hình. Không sửa request nào, không sót cái nào.

Bài học rút ra: base_url là ứng viên kinh điển cho biến Environment. Bất cứ giá trị nào thay đổi theo môi trường — URL, API key, database name — đều nên nằm ở scope Environment, không phải viết cứng trong request.

Ví dụ 2 — Shopee test đăng ký với email không trùng nhờ dynamic variable

Đội QA test API đăng ký tài khoản của một nền tảng giống Shopee gặp lỗi khó chịu: chạy lại test lần hai luôn báo 409 Conflict — email đã tồn tại, vì lần chạy đầu đã tạo tài khoản test@shopee.vn. Họ phải vào database xóa tay trước mỗi lần chạy.

Giải pháp: trong request body, thay email cứng bằng dynamic variable: "email": "qa_{{$timestamp}}@shopee.vn". Mỗi lần chạy, {{$timestamp}} sinh giá trị khác nhau (ví dụ qa_1719450123@shopee.vn), nên email luôn mới. Để dùng lại email vừa tạo ở request kế tiếp (bước đăng nhập), họ lưu nó vào biến trong pre-request script:

const email = qa_${Date.now()}@shopee.vn;
pm.collectionVariables.set("new_email", email);

Sau đó request đăng nhập tham chiếu {{new_email}}. Chuỗi test chạy sạch sẽ, không cần dọn database.

Bài học rút ra: dynamic variable ($) giải quyết bài toán trùng dữ liệu; còn khi cần "chuyền" giá trị giữa các request, hãy sinh giá trị một lần rồi lưu vào biến static ở scope Collection hoặc Environment.

Ví dụ 3 — VNG debug bug "biến ma" vì trùng tên hai scope

Một kỹ sư ở một công ty công nghệ lớn tại TP.HCM (kiểu VNG) dành cả buổi chiều debug: request đăng nhập luôn gọi tới https://old-gateway.internal dù anh đã sửa biến Environment base_url thành gateway mới. Hóa ra ba tháng trước, một đồng nghiệp đã lỡ tay tạo một biến Global cũng tên base_url trỏ về gateway cũ — nhưng vì Environment ưu tiên cao hơn Global, biến Global đáng lẽ bị che. Vấn đề thật là biến Environment base_url bị để trống ở cột "Current Value", nên Postman rơi xuống scope thấp hơn là Global.

Anh mở tab Global variables, xóa base_url thừa, và điền lại Current Value cho biến Environment. Bug biến mất.

Bài học rút ra: hai cạm bẫy cùng lúc — (1) trùng tên qua nhiều scope làm giá trị khó truy vết, và (2) sự khác biệt giữa cột "Initial Value" và "Current Value". Luôn tránh trùng tên biến giữa các scope, và nhớ rằng Postman dùng Current Value khi gửi request.

Hướng dẫn từng bước

Ta sẽ dựng một cấu hình biến gọn gàng cho một collection test API.

  • Tạo biến Collection cho base_url. Mở collection, vào tab Variables. Thêm dòng base_url với Current Value là URL dịch vụ. Dùng scope này khi URL cố định cho toàn collection.
  • Tạo Environment cho từng môi trường. Click biểu tượng mắt (Environments) ở sidebar, tạo DevProd. Nếu URL thay đổi theo môi trường, chuyển base_url từ Collection sang Environment (đặt ở Environment, xóa ở Collection để tránh trùng). Thêm các biến đặc thù như api_key.
  • Phân biệt Initial Value và Current Value. Initial Value được đồng bộ và chia sẻ khi bạn export/team sync — đừng bao giờ để token thật ở đây. Current Value chỉ nằm ở máy bạn. Với secret, để Initial trống, chỉ điền Current.
  • Dùng dynamic variable cho dữ liệu test. Trong body, viết "order_code": "ORD-{{$randomInt}}-{{$timestamp}}" để mỗi lần chạy có mã đơn khác nhau.
  • Lưu giá trị runtime bằng script. Trong tab Tests của request đăng nhập, trích token và lưu lại:
const token = pm.response.json().access_token;
pm.environment.set("auth_token", token);

Request sau dùng header Authorization: Bearer {{auth_token}}.

  • Kiểm tra giá trị thật khi debug. Rê chuột lên {{base_url}} trong URL — Postman hiện tooltip cho biết giá trị hiện tại và scope nào đang thắng. Đây là công cụ số một để bắt lỗi trùng tên.
  • Chọn đúng API khi đọc biến trong script. Dùng pm.variables.get("base_url") để đọc theo thứ tự ưu tiên, thay vì gọi thẳng pm.globals.get() (dễ bỏ sót giá trị ở scope cao hơn).

Lỗi thường gặp & mẹo

  • Nhầm Initial Value và Current Value: đây là lỗi phổ biến nhất. Bạn sửa Current Value nhưng đồng nghiệp pull về chỉ thấy Initial Value cũ. Với dữ liệu dùng chung, cập nhật cả hai; với secret, chỉ Current.
  • Để lộ token trong Initial Value: vì Initial Value được sync lên cloud và đi theo export, để API key/token ở đó là rò rỉ bảo mật. Luôn để trống Initial, chỉ dùng Current (hoặc dùng Postman Vault ở bài sau).
  • Trùng tên biến qua nhiều scope: gây "biến ma" khó debug. Đặt tên có tiền tố phân biệt scope nếu cần, ví dụ global_flag vs env_base_url.
  • Quên dấu ngoặc nhọn kép hoặc gõ sai tên: viết {base_url} (một ngoặc) hay {{baseurl}} (sai chính tả) khiến Postman gửi nguyên chuỗi văn bản đó đi. Biến chưa được phân giải thường hiện màu đỏ/cam — để ý màu sắc.
  • Nhầm pm.variables.set() là ghi vĩnh viễn: nó chỉ tạo biến Local, sống trong đúng lần chạy đó rồi mất. Muốn giá trị tồn tại, dùng pm.environment.set() hoặc pm.collectionVariables.set().
  • Mẹo dọn biến rác: cuối chuỗi test, xóa biến tạm bằng pm.environment.unset("auth_token") để môi trường sạch, tránh giá trị cũ lẫn vào lần chạy sau.
  • Mẹo chọn scope: giá trị đổi theo môi trường → Environment; giá trị cố định của một dịch vụ → Collection; giá trị dùng khắp workspace và hiếm đổi → Global; giá trị chỉ sống trong runtime → Local/Data.

Bài tập thực hành

  • Dựng cấu hình đa môi trường: Tạo một collection với 3 request gọi {{base_url}}/products, {{base_url}}/users, {{base_url}}/orders. Tạo hai environment Dev (base_url = https://dev.example.com) và Prod (base_url = https://api.example.com). Chuyển qua lại và xác nhận cả 3 request đổi URL mà không cần sửa.
  • Sinh dữ liệu động: Viết một request POST tạo tài khoản, dùng {{$randomFullName}}, {{$randomEmail}}, và "ref": "{{$guid}}" trong body. Chạy 3 lần và kiểm tra mỗi lần dữ liệu đều khác nhau.
  • Chuyền biến giữa request: Ở request đăng nhập, viết test script lưu access_token vào biến Environment. Ở request tiếp theo, dùng token đó trong header Authorization. Xác nhận request thứ hai chạy thành công (200).
  • Thử nghiệm thứ tự ưu tiên: Cố tình tạo biến test_var ở cả Global ("toi_la_global") và Environment ("toi_la_env"). Tạo request in {{test_var}} (dùng httpbin.org/get với query param). Quan sát giá trị nào thắng. Sau đó xóa biến Environment và chạy lại để thấy Global "trồi lên".

Tóm tắt

Variables là xương sống giúp collection Postman của bạn linh hoạt, tái sử dụng được, và an toàn. Có hai trục phân loại cần nắm: theo cách sinh giá trị (static bạn tự đặt vs dynamic có tiền tố $ do Postman sinh ngẫu nhiên), và theo phạm vi sống với 5 scope xếp theo ưu tiên từ hẹp đến rộng: Local > Data > Environment > Collection > Global. Khi trùng tên, scope hẹp hơn luôn thắng.

Quy tắc hành động: đặt base_url và các giá trị đổi theo môi trường vào Environment; giá trị cố định của dịch vụ vào Collection; dùng dynamic variable để tránh trùng dữ liệu test; và luôn phân biệt Initial Value (chia sẻ, không để secret) với Current Value (cục bộ). Khi debug, hãy rê chuột lên biến để xem giá trị và scope đang thắng — đó là cách nhanh nhất bắt lỗi "biến ma". Nắm chắc những nguyên tắc này, bạn đã sẵn sàng cho các bài nâng cao về pre-request script, chained request và authorization phía trước.