ETL और डेटा पाइपलाइन टेस्टिंग
ETL का मतलब है extract, transform, load: एक job source systems से data पढ़ता है, उसे business rules के हिसाब से बदलता है और किसी target में लिखता है, जैसे data warehouse। ETL testing जाँचती है कि जो भी row पहुँचनी चाहिए वह पहुँची, ठीक एक बार, और हर value rules के मुताबिक transform हुई। उदाहरण: हर रात एक job किसी दुकान के order database से कल के orders sales warehouse में copy करता है, amounts को SAR में बदलता है, status codes को नामों से map करता है और test stores छोड़ देता है; finance dashboard सिर्फ़ warehouse से पढ़ता है।
SQL for testers guide की count, sum, orphan और duplicate queries job की checks बन जाती हैं, और migrations के लिए इस्तेमाल हुई before-and-after तुलना अब हर load पर चलती है। जो teams पहले load करके target के अंदर transform करती हैं (ELT), वे भी यही checks इस्तेमाल करती हैं।
यह क्यों ज़रूरी है
Pipeline के defects चुपचाप होते हैं। जो job कुछ rows गिरा दे, किसी batch को दो बार load कर दे या amounts को नीचे round कर दे, वह फिर भी status "success" के साथ खत्म होता है, और किसी user को error नहीं दिखता। नुकसान बाद में reports और invoices में गलत numbers के रूप में सामने आता है, जब उन पर फ़ैसले हो चुके होते हैं।
अक्सर कोई user interface नहीं होता: output हज़ारों rows होता है, और expected result mapping document और हिसाब से आता है। यह automatically साबित करना कि दो data sets मेल खाते हैं, ऐसा skill है जो integrations, migrations और analytics में बार-बार काम आएगा।
Extract, transform, load: हर stage पर क्या जाँचें
हर stage को उसकी boundary पर जाँचें। Test basis आम तौर पर source-to-target mapping document होता है: target के हर column के लिए यह source columns, transformation rule और invalid values के साथ क्या होगा, बताता है। अगर ऐसा document नहीं है, तो developer के साथ उसे लिखना अक्सर सबसे उपयोगी test activity होती है।
- Extract: तय window की सारी rows आती हैं (जैसे कल रियाद समय 00:00 से आज 00:00 तक, आज का 00:00 शामिल नहीं; जो filter 23:59:59 पर खत्म होता है वह 23:59:59.5 के timestamp वाली row छोड़ देता है), count उतना ही है जितना source बताता है, और Arabic या Hindi text अपनी encoding रखता है। CSV files के लिए RFC 4180 कहता है कि जिस field में comma, double quote या line break हो उसे double quotes में रखा जाना चाहिए, और उसके अंदर का हर quote दोहरा लिखा जाए; जो reader बस commas पर तोड़ता है वह बाद के columns खिसका देता है।
- Transform: हर mapping rule expected value देता है, NULLs, unknown codes और boundary values के लिए भी; rule तोड़ने वाली rows reason के साथ reject table में जाती हैं, और rule से filter हुई rows गिनी जाती हैं।
- Load: rows सही table में पहुँचती हैं, business keys (source से आई natural key, जैसे
order_id) unique रहती हैं, और उसी batch को दो बार load करने पर target नहीं बदलता: यानी load idempotent है।
Reconciliation: हर row का हिसाब
Reconciliation source और target की तुलना करता है और हर अंतर की वजह बताता है। Pipeline जितनी rows पढ़ता है उससे कम load कर सकता है, क्योंकि rules कुछ rows filter करते हैं और validation कुछ reject करता है, लेकिन हर row को ठीक एक जगह पहुँचना चाहिए: source rows = loaded + rejected + filtered। अगर यह balance नहीं होता, तो rows खो गईं या duplicate हुईं।
- 1Extractतय window की सारी rows; count, columns और encoding वैसे ही जैसे source बताता है
शाखा: Schema या file check fail → run रोकेंफ़ेल
- 2Rows validate करनाRequired fields, types, allowed values
शाखा: खराब rows → reject table, reason code के साथफ़ेल
- 3TransformMapping rules: lookups, conversions, time zones, defaults, duplicates
शाखा: Rule से filter हुई rows गिनी जाती हैं, खोती नहीं
- 4LoadBusiness keys unique रहती हैं; उसी batch को दोबारा load करने से कुछ नहीं बदलता
- 5Reconciliation और quality checksCounts, control totals और keys मेल खाते हैं; quality checks pass होती हैं
source = loaded + rejected + filteredGate
चरण 1–5 के दौरान Audit table: हर run में हर stage के counts
इसके बाद:Run balance हो, तभी reports के लिए publish
उदाहरण के तौर पर क्रम: कुछ pipelines transform step के अंदर validate करते हैं, या पहले load करके target में transform करते हैं (ELT)।
तीन levels पर जाँचें। हर run, दिन और status के counts दिखाते हैं कि totals मेल खाते हैं। Control totals, जैसे amounts का sum, दिखाते हैं कि values कटी नहीं या rounding में गायब नहीं हुईं। Key-level तुलना, यानी SQL for testers की LEFT JOIN … IS NULL query जो दोनों दिशाओं में चले, missing या extra ids सटीक बताती है, और developer को यही चाहिए। दो अलग systems के बीच, दोनों तरफ़ से keys export करें और एक जगह तुलना करें।
-- Balance one run (src_orders = the extracted rows, as staged)
SELECT
(SELECT COUNT(*) FROM src_orders
WHERE order_date = '2026-09-30') AS source_rows,
(SELECT COUNT(*) FROM fact_sales
WHERE order_date = '2026-09-30') AS loaded,
(SELECT COUNT(*) FROM reject_orders
WHERE order_date = '2026-09-30') AS rejected,
(SELECT COUNT(*) FROM src_orders
WHERE order_date = '2026-09-30'
AND store_type = 'TEST') AS filtered;
-- Source orders that reached neither the target nor the reject table
SELECT s.order_id
FROM src_orders s
LEFT JOIN fact_sales f ON f.order_id = s.order_id
LEFT JOIN reject_orders r ON r.order_id = s.order_id
WHERE s.order_date = '2026-09-30'
AND COALESCE(s.store_type, '') <> 'TEST' -- NULL store_type must not hide a row
AND f.order_id IS NULL
AND r.order_id IS NULL;
-- The other direction: target rows with no source order
SELECT f.order_id
FROM fact_sales f
LEFT JOIN src_orders s ON s.order_id = f.order_id
WHERE f.order_date = '2026-09-30'
AND s.order_id IS NULL;आज़माएँ: CSV से SQL आज़माएँ: SQL क्वेरी वैलिडेटर आज़माएँ: टेक्स्ट डिफ़
Transformation rules की testing
Mapping की हर row एक test condition है। Input rows partitions, boundary values और decision tables से design करें, उन्हें एक छोटे source data set में रखें जिसकी हर expected value आपको पता हो, job चलाएँ और target की row-by-row तुलना करें। Production जैसा बड़ा run volume और अनपेक्षित values जोड़ता है; आपको दोनों चाहिए।
- Lookups: status
P→Paid; एक unknown code और lowercasepभी टेस्ट करें। - Conversions: amount × order की तारीख़ का exchange rate, 2 decimals तक round। ठीक बीच वाला result टेस्ट करें, जैसे 10.125: half-up rounding 10.13 देती है, half-to-even 10.12। Missing rate भी टेस्ट करें।
- Time zones: UTC से रियाद समय (UTC+3) में बदलने पर 21:00 UTC या उसके बाद के orders अगले दिन में चले जाते हैं; 20:59:59 और 21:00:00 UTC टेस्ट करें।
- Duplicates और NULLs: जब source एक order दो बार भेजे, तो rule तय करता है कि कौन-सी copy मानी जाएगी, जैसे सबसे नए
updated_atवाली; NULL discount 0 बन सकता है।
आज़माएँ: डेसिमल डेटासेट जनरेटर आज़माएँ: तारीख़ टेस्ट डेटा जनरेटर
Data quality checks और backend validation
Reconciliation साबित करता है कि कुछ खोया नहीं; data quality checks साबित करते हैं कि जो पहुँचा वह इस्तेमाल लायक है। Teams dimensions के नाम अलग रखती हैं, लेकिन ज़्यादातर नीचे वाले dimensions जाँचती हैं, हर एक ऐसी query से जिसका खाली result pass है।
Backend data validation का मतलब है कि pipeline खुद हर run में ये checks चलाता है: data आने पर schema check, row rules जो खराब rows को reason code के साथ reject table में भेजते हैं, data owner के साथ तय thresholds जो publish से पहले run रोक देते हैं, और हर run के counts वाली audit table। इस व्यवस्था को भी टेस्ट करें: हर rule तोड़ने वाली एक row डालें, और reject rate को threshold से ऊपर ले जाकर पुष्टि करें कि run रुकता है और किसी को alert जाता है।
- Completeness: हर sale का store और amount है।
- Uniqueness: हर business key की एक row, जैसे
order_id। - Validity: known status codes, amount > 0, भविष्य की कोई तारीख़ नहीं।
- Consistency: हर sale किसी मौजूद store से जुड़ी है, और lines का जोड़ order total के बराबर है।
- Timeliness: load समय पर पूरा हुआ, और सबसे नई row अपेक्षित दिन की है।
- Accuracy: target rows का एक sample source या किसी भरोसेमंद report से field-by-field मेल खाता है।
Worked example: दो बार चला nightly load
30 सितंबर का run 10,000 orders पढ़ता है। Mapping test stores के 120 orders filter करता है और validation store id के बिना 15 orders reject करता है, इसलिए target में 9,865 rows जुड़नी चाहिए। Audit table दिखाती है कि 02:10 पर network timeout हुआ, job अपने-आप restart हुआ और 02:40 पर status "success" के साथ खत्म हुआ।
Balance query 10,365 loaded rows गिनती है, यानी source के भेजे से भी ज़्यादा: 10,000 ≠ 10,365 + 15 + 120। Missing orders वाली query कुछ नहीं लौटाती। Duplicate query 500 order ids लौटाती है, हर एक दो बार load हुआ, जो 500 rows की पूरी बढ़त को समझा देता है, और SAR control total ठीक उनके amounts जितना ज़्यादा है। Job 500 rows के chunks load करता है और हर पूरा chunk एक progress table में दर्ज करता है। एक chunk commit हो गया पर उसका progress record नहीं, क्योंकि दोनों writes एक transaction में नहीं थे, इसलिए restart ने उसे दोबारा insert कर दिया।
- Bug report: run date, balance के numbers, 500 order ids, audit log में restart, और expected behaviour: किसी batch को दोबारा चलाने से target नहीं बदलता।
- नई checks: testing में हर batch दो बार चलाएँ, job को किसी write और उसके progress record के बीच रोकें, और
order_idकी uniqueness check से publish रुकवाएँ।
आम गलतियाँ
- Job status पर भरोसा करना: "success" का मतलब है job खत्म हुआ, यह नहीं कि data पूरा या सही है।
- सिर्फ़ कुल row counts की तुलना करना: एक खोई row और एक duplicate row एक-दूसरे को बराबर कर देती हैं; control totals और key-level तुलना जोड़ें।
- Rejected और filtered rows न गिनना, जिससे कोई run balance नहीं हो पाता और खोया हुआ data filtering जैसा दिखता है।
- Rules को सिर्फ़ बड़ी production copy पर टेस्ट करना, जहाँ किसी को नहीं पता कि हर value क्या होनी चाहिए।
- हर batch एक ही बार चलाना: reruns, restarts और देर से आने वाले records वहीं हैं जहाँ loads data duplicate करते हैं या छोड़ देते हैं।
- Production का personal data बिना approved anonymisation के test environment में copy करना; सऊदी अरब का PDPL वहाँ भी लागू होता है।
QA का नज़रिया
शुरुआत mapping document से करें: उसे requirement की तरह review करें, और कुछ बनने से पहले पूछें कि NULLs, unknown codes, duplicates, देर से आए data और reruns के साथ क्या होगा। Data owner के साथ तय करें कि कौन-सी checks publish रोकती हैं, कौन-सी सिर्फ़ warning देती हैं, और कितना reject rate स्वीकार्य है।
जिस भी run को आप टेस्ट करें, उसका run id, date window, balance के numbers, control totals और queries दर्ज करें, ताकि कोई भी check दोहरा सके। जिन checks ने defects पकड़े उन्हें automate करें, और failures को keys और business impact के साथ report करें, जैसे "30 सितंबर की sales report में 500 orders दो बार गिने गए", न कि "data mismatch"।
अभ्यास
Customer load को balance करें और defects खोजें
एक job CRM extract से customers load करता है। Mapping: country lookup होता है (SA → Saudi Arabia, IN → India, कोई भी दूसरा code BAD_COUNTRY के साथ reject); email trim और lowercase होता है; बिना customer_id वाली row NO_ID के साथ reject होती है; is_test = Y वाली rows filter होती हैं।
नीचे दिए run को balance करें, फिर हर defect को उसकी key, expected result और actual result के साथ लिखें।
Extract (6 rows)
customer_id email country is_test
101 "Sara@Example.com" SA N
102 " ravi@example.com" IN N
103 "test@example.com" SA Y
(none) "noid@example.com" SA N
105 "omar@example.com" XX N
106 "lina@example.com" sa N
Target dim_customer (3 rows)
customer_id email country
101 "sara@example.com" Saudi Arabia
102 " ravi@example.com" India
106 "lina@example.com" Unknown
Reject table (1 row)
customer_id reason
(none) NO_ID- निकालें कि कौन-सी rows load, reject और filter होनी चाहिए।
- जाँचें कि source = loaded + rejected + filtered सही बैठता है या नहीं।
- हर loaded row की rules से field-by-field तुलना करें।
- हर defect उसकी key, expected value और actual value के साथ लिखें।
मॉडल उत्तर दिखाएँ
Expected: 103 filter; बिना id वाली row NO_ID के साथ reject; 105 BAD_COUNTRY के साथ reject; 101 और 102 load। 106 में sa है: जैसा लिखा है, उसके हिसाब से यह दूसरा code है और reject होना चाहिए, जब तक lookup case को ignore न करे।
Balance: source में 6 rows, लेकिन 3 loaded + 1 rejected + 1 filtered = 5। Customer 105 न target में है न reject table में: data loss, सबसे गंभीर defect, क्योंकि run सफल दिखता है।
Defect: 102 के email में आगे का space रह गया; expected "ravi@example.com"। Lowercasing काम करती है (101), इसलिए trimming गायब है।
Defect: 106 का country Unknown है, जो mapping कभी नहीं बनाता; expected BAD_COUNTRY के साथ reject, या lookup case ignore करे तो Saudi Arabia। Mapping owner से पूछें, और यह भी पूछें कि filtered rows कहाँ गिनी जाती हैं: उस number के बिना कोई run balance नहीं हो सकता।
अक्सर पूछे जाने वाले सवाल
ETL और ELT testing में क्या फ़र्क है?
ETL में data load होने से पहले transform होता है; ELT में वह raw रूप में load होता है और फिर target के अंदर transform होता है, आम तौर पर SQL से। Checks वही हैं (reconciliation, transformation rules, data quality), लेकिन ELT में ज़्यादातर checks एक ही system के अंदर SQL के रूप में चलती हैं, और आप raw layer भी जाँचते हैं।
क्या हर row की तुलना ज़रूरी है, या sample काफ़ी है?
Counts, control totals और key-level तुलना हर row को cover करनी चाहिए: ये सस्ती queries हैं, और ये वे खोई या duplicate rows पकड़ती हैं जो sample से छूट जाती हैं। Values की field-by-field तुलना एक sample और आपके छोटे known data set से हो सकती है, जिन्हें ऐसे चुना जाए कि हर rule और हर जोखिम वाली value cover हो।
क्या ETL testing और database testing एक ही हैं?
इनमें skills वही लगती हैं (SQL, constraints, reconciliation), पर object अलग है। Database testing जाँचती है कि एक application अपना data कैसे store करता और बदलता है; ETL testing systems के बीच batches में चलते data को जाँचती है, जहाँ मुख्य जोखिम runs के दौरान rows का खोना, duplicate होना या गलत transform होना है।
संदर्भ
- ISTQB Certified Tester Foundation Level (CTFL) v4.0सॉफ़्टवेयर टेस्टिंग का फ़ाउंडेशन पाठ्यक्रम: टेस्ट स्तर और प्रकार, टेस्ट डिज़ाइन तकनीकें, टेस्ट प्रबंधन और टूल।
- ISTQB Glossaryटेस्टिंग शब्दों की मानक परिभाषाएँ — टेस्ट केस, रिग्रेशन टेस्टिंग, सेवेरिटी, प्रायोरिटी, बाउंड्री वैल्यू एनालिसिस आदि।
- RFC 4180: Common Format and MIME Type for Comma-Separated Values (CSV) FilesCSV के आम नियम: कॉमा सेपरेटर, CRLF लाइन एंड, और कॉमा, कोट या लाइन ब्रेक वाले फ़ील्ड की क्वोटिंग।
- Personal Data Protection Law (English translation)व्यक्तिगत डेटा पर सऊदी कानून — टेस्ट वातावरण में असली ग्राहक रिकॉर्ड की प्रतियों के बजाय सिंथेटिक डेटा क्यों इस्तेमाल करना चाहिए।
Mutqan tools से अभ्यास करें
कस्टम कॉलम, डेटा टाइप, पंक्ति संख्या और डिलिमिटर के साथ CSV फ़ाइलें जनरेट करें।
CSV डेटा को अनुमानित कॉलम टाइप के साथ CREATE TABLE और INSERT स्टेटमेंट में बदलें।
SQL स्टेटमेंट में सिंटैक्स की समस्याएँ, असंतुलित कोष्ठक, बिना बंद की स्ट्रिंग और जोखिम भरे पैटर्न जाँचें।
दो टेक्स्ट की लाइन-दर-लाइन या शब्द-दर-शब्द तुलना करें और अंतर हाइलाइट करें।
तय परिशुद्धता, करेंसी जैसी राशियों और राउंडिंग edge cases के साथ decimal / floating-point डेटासेट जनरेट करें।
तारीख़ों के डेटासेट जनरेट करें: किसी रेंज में रैंडम तारीख़ें, leap day, महीने के अंत, DST किनारे और कई फ़ॉर्मेट।
और गहराई से
इस topic में आपकी प्रगति
प्रगति ट्रैक करने के लिए साइन इन करें
Topics पूर्ण चिह्नित करें, जहाँ छोड़ा था वहीं से जारी रखें और specialisation परीक्षाएँ खोलें।