API रिस्पॉन्स वैलिडेशन
API response validation API test का वह हिस्सा है जो तय करता है कि response सही है या नहीं। आप actual response की तुलना expected result से layer by layer करते हैं: status code, headers, body में कौन-से fields मौजूद हैं, उनके types, उनकी values, उन्हें जोड़ने वाले business rules, और response में कितना समय लगा। हर तुलना एक assertion है: एक सटीक check जो या तो pass होता है या fail।
POST /api/v1/orders को लें, जो एक order बनाता है। "कुछ तो लौटा" कोई test नहीं है। "Status 201 है, Content-Type application/json है, $.status "pending" है और $.total quantity गुणा unit price के जोड़ के बराबर है" — यह test है। $.total वाला notation JSONPath है, JSON document के अंदर values तक पहुँचने की एक छोटी query language।
यह क्यों ज़रूरी है
APIs ऐसे तरीक़ों से fail होती हैं जो सरसरी नज़र में नहीं दिखते। 200 OK की body में error message हो सकता है, कोई number चुपचाप string बन सकता है, total से कोई item छूट सकता है, और profile response में password hash आ सकता है। API का हर client — web app, mobile app या partner integration — ये defects विरासत में पाता है, और अक्सर तब तक पता नहीं चलता जब तक कुछ टूट न जाए।
Validation यह भी तय करता है कि आपका test कितना काम का है। जो test सिर्फ़ status code जाँचता है, वह server के जवाब देते ही pass हो जाता है और झूठा भरोसा देता है। सटीक assertions हर run को evidence बनाते हैं: fail हुआ assertion field, expected value और actual value बताता है, और अच्छी bug report का ज़्यादातर हिस्सा यही है।
Response check की सात layers
Response को बाहर से अंदर की ओर पढ़ें। Status line बताती है कि क्या हुआ, headers message का वर्णन करते हैं और body data लाती है। Body के अंदर पहले structure जाँचें (fields मौजूद हैं?), फिर types, फिर values, और आख़िर में वे rules जो कई values को जोड़ते हैं। Timing response में लिखी नहीं होती; उसे आपका client मापता है, लेकिन वह इसी check का हिस्सा है।
हर assertion को एक test oracle चाहिए, यानी expected result का स्रोत: API documentation, acceptance criteria या कोई business rule — response ख़ुद कभी नहीं। इस lesson का उदाहरण उस request का response है जिसने customer 7 के लिए दो items वाला order बनाया।
- Status code: ठीक वही code जो documented है। बना हुआ resource
201लौटाता है, "कोई भी 2xx" नहीं। Number assert करें; reason phrase ("Created") सिर्फ़ जानकारी के लिए है, और HTTP/2 उसे भेजता ही नहीं। - Headers:
Content-Typebody का media type बताता है, यहाँapplication/json;201के बादLocationheader नए resource की पहचान देता है। RFC 9110 के अनुसार header names case-insensitive हैं, इसलिए उनकी तुलना उसी तरह करें। - Fields मौजूद: हर required field मौजूद है, और जो fields कभी नहीं भेजने चाहिए, जैसे
password, वे गायब हैं। - Types:
idऔरcustomerIdintegers हैं,totalnumber है औरitemsarray। Quotes में"7"string होता — value सही दिखने पर भी यह type defect है। - Values: जो आपने भेजा वह बिना बदले लौटता है (
customerId7 है), enumerations allowed set में हैं (statuspendingहै), और formats सही हैं (createdAtRFC 3339 timestamp है जोZया offset पर ख़त्म होता है)। - Business rules: values आपस में मेल खाती हैं।
total= 2 × 99.95 + 1 × 50.00 = 249.90, औरLocationके अंत वाला numberidके बराबर है। - Timing: response उस budget के भीतर आता है जो team ने इस endpoint के लिए तय किया। यहाँ client ने test environment में 1,000 ms के budget के मुक़ाबले 184 ms मापा।
201 response और checks की सात layers: status code, headers, required और forbidden fields, types, values, total को items से जोड़ने वाला business rule, और client का मापा हुआ समय।रिस्पॉन्स
HTTP/1.1 भाग 1:201 Created भाग 2:Content-Type: application/json Location: /api/v1/orders/9021 { भाग 3:"id": 9021, भाग 4:"customerId": 7, भाग 5:"status": "pending", "items": [ { "sku": "A-100", "qty": 2, "unitPrice": 99.95 }, { "sku": "B-200", "qty": 1, "unitPrice": 50.00 } ], भाग 6:"total": 249.90, "createdAt": "2026-10-01T09:30:12Z" }
Client मापता है, यह message का हिस्सा नहीं
response time: भाग 7:184 ms
- 1स्टेटस कोडठीक
201: order बन गया। Reason phrase assert नहीं होता।status == 201पास - 2हेडर्सMedia type
application/json;Locationनए order केidपर ख़त्म होता है।Location == /api/v1/orders/9021पास - 3Fields मौजूदRequired fields मौजूद हैं, और जो field कभी नहीं भेजना चाहिए वह गायब है:
$.password → (no match)पास - 4टाइप्सInteger 7, string
"7"नहीं;totalnumber है औरitemsarray।$.customerId type integerपास - 5वैल्यूज़नया order
pendingहोता है, औरcustomerIdवही 7 है जो आपने भेजा।$.status == "pending"पास - 6बिज़नेस रूल
totalसभी items केqty × unitPriceका जोड़ है।2 × 99.95 + 1 × 50.00 = 249.90पास - 7टाइमिंगTeam के इस endpoint के लिए तय budget के भीतर: 1,000 ms।
184 ms <= 1000 msपास
पाठ संस्करण
HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/orders/9021
{
"id": 9021,
"customerId": 7,
"status": "pending",
"items": [
{ "sku": "A-100", "qty": 2, "unitPrice": 99.95 },
{ "sku": "B-200", "qty": 1, "unitPrice": 50.00 }
],
"total": 249.90,
"createdAt": "2026-10-01T09:30:12Z"
}JSONPath से fields तक पहुँचना
हर assertion को उस value का address चाहिए जिसे वह जाँचता है। IETF ने RFC 9535 में JSONPath को standard बनाया। यह address को एक expression के रूप में लिखता है जो $ यानी document के root से शुरू होकर एक-एक segment नीचे जाता है: object member के लिए .name, array index के लिए [0], हर element के लिए [*], किसी भी depth के लिए .. और filter के लिए [?(…)], जिसमें @ उस element को दर्शाता है जिसे जाँचा जा रहा है। RFC 9535 parentheses के बिना filter ([?@.qty>1]) भी स्वीकार करता है, लेकिन standard से पहले बने कई tools में parentheses ज़रूरी हैं, इसलिए यह lesson उन्हें लिखता है। ऐसे tools दूसरी details में भी अलग हैं, इसलिए expression पहले अपने tool में आज़माएँ।
Result एक nodelist होता है: शून्य, एक या कई values। खाली result error नहीं है; इसका मतलब है कि कुछ match नहीं हुआ। इससे absence assert करना आसान होता है और typos ख़तरनाक: $.totl कुछ match नहीं करता, इसलिए उस पर assertion को fail होना चाहिए, चुपचाप pass नहीं। Results parsed values होते हैं, इसलिए text में 50.00 number 50 है।
- एक value:
$.statusको"pending"के बराबर होना चाहिए। - Absence:
$.passwordको कुछ नहीं लौटाना चाहिए। Sensitive या internal fields सिर्फ़ उनकी absence assert करके पकड़े जाते हैं। - हर element: rule तोड़ने वाले elements चुनें और खाली result की उम्मीद करें। अगर
$.items[?(@.qty<1)]कुछ न लौटाए, तो किसी भी item की numeric quantity 1 से कम नहीं है। Comparison उस item को छोड़ देता है जिसमेंqtyगायब हो या string हो, इसलिए इस rule के साथ presence और type checks भी लगाएँ। यह हर tool में काम करता है, उन tools में भी जो value rule को सिर्फ़ पहले match से मिलाते हैं। - Count: दो items की उम्मीद हो तो सिर्फ़ पहला element जाँचने की बजाय
$.itemsकी length assert करें।
Expression Result on the example body
$.status "pending"
$.items[0].sku "A-100"
$.items[-1].unitPrice 50 last element
$.items[*].qty 2, 1 every element
$..sku "A-100", "B-200" any depth
$.items[?(@.qty>1)].sku "A-100" filter
$.password (no match) absent, as requiredWorked example: नए order की checklist
Documentation कहता है: "POST /api/v1/orders एक order बनाता है और 201 Created, order के URL वाला Location header और JSON में order लौटाता है। नए order का status pending होता है। total सभी items के qty × unitPrice का जोड़ है।"
Request ने customerId 7 और दो items भेजे: A-100 × 2 और B-200 × 1। हर line में एक assertion, उसकी layer और उसके oracle के साथ लिखने से ऐसी checklist बनती है जिसे आप हाथ से चला सकते हैं, किसी validator में paste कर सकते हैं या बाद में automate कर सकते हैं।
- हर run में बदलने वाली values,
idऔरcreatedAt, type, format और relationship से जाँची जाती हैं (Locationका numberidके बराबर;createdAtrequest भेजने के समय के क़रीब), exact value से कभी नहीं। - जिन values पर आपका नियंत्रण है वे exact जाँची जाती हैं: आपने customer 7 और दो items भेजे, तो वही वापस आने चाहिए।
- Expected total, documented rule से response के items पर calculate होता है: oracle rule है, response नहीं। Numbers की तुलना numbers की तरह करें:
249.90और249.9text के रूप में अलग हैं, पर JSON number एक ही है। - एक check इस response से आगे जाता है:
LocationURL परGETवही order लौटाए, जिससे साबित हो कि order store हुआ, सिर्फ़ echo नहीं।
# Layer Assertion Oracle
1 status status == 201 documentation
2 headers Content-Type contains application/json documentation
3 headers Location == /api/v1/orders/{id} documentation
4 fields $.id, $.status, $.items, $.total exist documentation
5 fields $.password does not exist security rule
6 types $.id integer, $.total number, $.items array documentation
7 values $.customerId == 7, $.items length == 2 the request
8 values $.status == "pending" business rule
9 values $.createdAt is RFC 3339 with Z or an offset documentation
10 rule $.total == sum of qty * unitPrice (249.90) business rule
11 timing response time <= 1000 ms (measured: 184 ms) team budgetहर response में क्या assert करें, और क्या नहीं
हर endpoint को ग्यारह checks नहीं चाहिए, लेकिन हर response को एक न्यूनतम जाँच चाहिए, error responses को भी: error response को ठीक वही documented 4xx code, JSON content type और documented shape वाली error body मिलनी चाहिए।
- हमेशा: exact status code,
Content-Typeका media type, JSON के रूप में parse होने वाली body, required fields और forbidden fields की absence।204 No Contentresponse में body नहीं होती, इसलिए उसमें सिर्फ़ status और headers assert करें। - जो data आपने भेजा या जिसका अनुमान लगा सकते हैं: exact values। IDs, timestamps और tokens जैसे generated data: type, format, range और relationships।
- Business rules: endpoint जो भी rule implement करता है, उसके लिए कम से कम एक assertion।
- Timing: हर call पर budget check। एक धीमा sample दोबारा मापने की वजह है, अभी performance defect नहीं।
- जिसका कोई अर्थ नहीं, उसे assert न करें: JSON object में members का क्रम (RFC 8259 object को unordered बताता है), अलग-अलग names वाले headers का क्रम, header names का letter case और body में whitespace।
- Array order: तभी assert करें जब API कोई sort order document करे, और तब उसे साफ़ तौर पर assert करें।
आम गलतियाँ
- सिर्फ़ status code assert करना। Body में
{"error": "out of stock"}वाला200 OKऐसे test में pass हो जाता है। - मौजूदा response को copy करके expected result बना देना। अगर response पहले से गलत है, तो test अब defect की रक्षा करता है; expected values oracle से लें।
- IDs और timestamps जैसे generated data की exact values assert करना: तब test अगले run में fail होता है, जबकि कुछ गलत नहीं है।
- खाली JSONPath result को pass मान लेना।
$.totlजैसा typo कुछ match नहीं करता, और उस पर assertion को fail होना चाहिए। - Numbers की तुलना text की तरह करना, जिससे
249.9249.90के सामने fail हो, या ढीली तुलना करना, जिससे number की जगह string"249.90"pass हो जाए। - Array का एक element जाँचकर बाक़ी को वैसा ही मान लेना: पहला item सही है, तीसरे का total string है।
QA का नज़रिया
Team में response validation API बनने से पहले शुरू हो जाता है। API documentation या OpenAPI description review करते समय हर response के लिए पूछें: exact status क्या है, कौन-से fields required हैं, कौन-से null हो सकते हैं, कौन-सी values और formats allowed हैं, और कौन-सा rule उन्हें जोड़ता है? अधूरा जवाब documentation defect है, और उसे इसी समय ठीक करना सबसे सस्ता है।
Execution के समय checklist को test case के साथ रखें ताकि दूसरा tester उसे दोहरा सके, और हर fail हुए assertion की actual value record करें। अच्छी API bug report में request, fail हुए check की expected और actual value, और oracle होता है: "$.items[2].total string "75.50" है; documentation total को number बताता है।" Developers के साथ तय करें कि कौन-से checks automate होंगे, ताकि manual मेहनत उन rules और सवालों पर लगे जो कोई script नहीं पूछ सकती।
अभ्यास
Filtered order list को validate करें
Documentation कहता है: "GET /api/v1/orders?status=paid 200 और application/json लौटाता है। Body में page, pageSize और items हैं; items में अधिकतम pageSize orders होते हैं, हर एक का status paid, createdAt के अनुसार sorted, सबसे नया पहले। total एक number है। Target response time: 1,000 ms।" आपके client को नीचे वाला response 2,340 ms में मिला।
इस response की checklist लिखें, फिर तय करें कि कौन-से checks pass और कौन-से fail होते हैं। Pen और paper इस्तेमाल करें, या response को API रिस्पॉन्स वैलिडेटर और JSON Path टेस्टर में paste करें।
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
{
"page": 1,
"pageSize": 20,
"items": [
{ "id": 9021, "status": "paid", "total": 249.90,
"createdAt": "2026-10-01T09:30:12Z" },
{ "id": 9017, "status": "pending", "total": 120.00,
"createdAt": "2026-09-30T18:05:44Z" },
{ "id": 9010, "status": "paid", "total": "75.50",
"createdAt": "2026-09-29T11:20:03Z" }
]
}- Checks layer by layer लिखें: status, headers, fields, types, values, business rules, timing।
- Body के हर check को उसके expected result के साथ JSONPath expression के रूप में लिखें; "हर item" वाले rules के लिए rule तोड़ने वाले items चुनें।
- Checks चलाएँ और actual value के साथ pass या fail record करें।
- हर failure के लिए एक line का bug title लिखें।
मॉडल उत्तर दिखाएँ
Pass: status 200; $.page 1 है; $.items 3 elements वाला array है, यानी pageSize (20) से ज़्यादा नहीं; createdAt values 1 अक्टूबर, 30 सितंबर और 29 सितंबर हैं, इसलिए सबसे नया पहले वाला क्रम सही है; हर timestamp Z पर ख़त्म होता है।
Fail, headers: Content-Type text/html; charset=utf-8 है जबकि body JSON है। Bug title: "GET /api/v1/orders JSON को text/html label के साथ लौटाता है"।
Fail, business rule: $.items[?(@.status!='paid')].id 9017 लौटाता है, जबकि result खाली होना चाहिए। Bug title: "status=paid filter pending order 9017 लौटाता है"।
Fail, types: $.items[2].total string "75.50" है, number नहीं। हर element का type हाथ से जाँचना धीमा है; schema validation सभी elements एक साथ जाँचता है। Bug title: "Order 9010 total को string के रूप में लौटाता है"।
Warning, timing: 2,340 ms, 1,000 ms के target से ऊपर है। एक sample काफ़ी नहीं; request कुछ बार दोहराएँ और समय target से ऊपर ही रहे तो report करें।
अक्सर पूछे जाने वाले सवाल
JSONPath और JSON Pointer में क्या अंतर है?
JSON Pointer (RFC 6901) अपने path से ठीक एक value पहचानता है, जैसे /items/0/sku। JSONPath (RFC 9535) एक query है: wildcards, filters और descendants शून्य, एक या कई values चुन सकते हैं, जैसे $.items[*].sku। इस lesson के tools जैसे response validators JSONPath इसलिए इस्तेमाल करते हैं क्योंकि assertions अक्सर कई values या उनकी absence के बारे में होते हैं।
क्या smoke test के लिए status code जाँचना काफ़ी नहीं?
"क्या service चल रही है" जैसे quick check के लिए status code और content type काफ़ी हो सकते हैं। लेकिन जो test दावा करता है कि feature काम करता है, उसके लिए नहीं: status code body के बारे में कुछ नहीं बताता, और 200 में गलत total या error message हो सकता है। कम से कम required fields और एक business rule जोड़ें।
Responses को manually validate करूँ या automation से?
दोनों, अलग-अलग समय पर। Design और पहला run manual होते हैं: आप documentation पढ़ते हैं, हर check का oracle चुनते हैं और असली response देखते हैं। Checklist stable होने पर वही assertions automated checks बन जाते हैं जो हर build पर चलते हैं, और आपका manual समय नए endpoints और exploratory सवालों पर जाता है।
यह schema validation से कैसे अलग है?
Schema वह structure बताता है जो हर valid response में एक जैसा होता है: required fields, types, formats और allowed values। वह calculation नहीं करता, इसलिए यह नहीं जाँच सकता कि total items के जोड़ के बराबर है; और वह आपकी request नहीं जानता, इसलिए यह भी नहीं जाँच सकता कि आपका माँगा filter लागू हुआ या value वही है जो आपने भेजी। Shape के लिए schema और meaning के लिए assertions इस्तेमाल करें।
संदर्भ
- RFC 9110: HTTP SemanticsHTTP मेथड, हेडर फ़ील्ड, स्टेटस कोड और कंटेंट निगोशिएशन के अर्थ, वायर वर्ज़न से स्वतंत्र।
- RFC 9535: JSONPath: Query Expressions for JSONमानक JSONPath सिंटैक्स — रूट, चाइल्ड, डिसेंडेंट, वाइल्डकार्ड और फ़िल्टर सिलेक्टर — और क्वेरी का मूल्यांकन।
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange FormatJSON का व्याकरण: ऑब्जेक्ट, ऐरे, स्ट्रिंग, नंबर, तीन लिटरल और इंटरचेंज एन्कोडिंग के रूप में UTF-8।
- ISTQB Glossaryटेस्टिंग शब्दों की मानक परिभाषाएँ — टेस्ट केस, रिग्रेशन टेस्टिंग, सेवेरिटी, प्रायोरिटी, बाउंड्री वैल्यू एनालिसिस आदि।
Mutqan tools से अभ्यास करें
API रिस्पॉन्स को अपेक्षाओं के आधार पर जाँचें: स्टेटस, ज़रूरी हेडर, JSON स्कीमा और फ़ील्ड नियम।
JSON पर JSONPath एक्सप्रेशन ($.store.book[*].author) चलाएँ और मैच लाइव देखें।
method, हेडर और JSON बॉडी पर पूरे नियंत्रण के साथ REST endpoint टेस्ट करें, फिर स्टेटस, हेडर और JSON path पर assertion लगाएँ।
JSON को कोलैप्सिबल ट्री के रूप में देखें — पाथ, टाइप और वैल्यू की संख्या के साथ।
किसी API रिस्पॉन्स का विश्लेषण करें: संरचना, फ़ील्ड टाइप, null, डुप्लिकेट, साइज़ और संभावित डेटा-क्वालिटी समस्याएँ।
और गहराई से
इस topic में आपकी प्रगति
प्रगति ट्रैक करने के लिए साइन इन करें
Topics पूर्ण चिह्नित करें, जहाँ छोड़ा था वहीं से जारी रखें और specialisation परीक्षाएँ खोलें।