CI पाइपलाइन स्टेज के रूप में विजुअल QA
मैंने पिछले महीने एक PR मर्ज किया। कोड रिव्यू अच्छा दिख रहा था। टेस्ट पास हो गए। फिर मैंने अपने फोन पर साइट खोली और साइडबार पूरी तरह से टूटा हुआ था।
फिक्स तुच्छ था—एक मिसिंग मीडिया क्वेरी। बग तब स्पष्ट था जब आप वास्तव में मोबाइल व्यू देखते। किसी ने नहीं देखा।
इसलिए मैंने एक पाइपलाइन स्टेज जोड़ा जो देखता है।
मैं एक GitHub इशू खोलता हूं जो कहता है:
क्लाइंट्स जोड़ने के लिए मैनुअल एंट्री विकल्प लागू करें। क्लिक करने पर, एक नया क्लाइंट बनाने के लिए फॉर्म के साथ एक चौड़ा स्लाइड-ओवर ड्रॉअर खुलता है।
एक कमिट बाद, PR 30+ स्क्रीनशॉट्स के साथ आता है जो साबित करते हैं कि हर स्थिति हर व्यूपोर्ट पर काम करती है। शून्य मैनुअल टेस्टिंग। एकमात्र प्रयास फीचर विवरण लिखना था।
अवधारणा
PR में हर पुश पर, एक GitHub Actions वर्कफ्लो:
- PR ब्रांच से Docker Compose स्टैक (Django + Postgres) बूट करता है
- माइग्रेशन चलाता है और एक टेस्ट यूजर सीड करता है
- स्थानीय URL को Playwright MCP (हेडलेस Chromium) के साथ Claude Code को सौंपता है
- PR diff के आधार पर इंटरैक्टिव एलिमेंट्स का परीक्षण करता है
- तीन व्यूपोर्ट्स पर हर स्थिति का स्क्रीनशॉट लेता है
- परिणाम को PR कमेंट के रूप में पोस्ट करता है
Claude Code ब्राउज़र को नियंत्रित करता है। Docker Compose ऐप प्रदान करता है। GitHub Actions इसे एक साथ बांधता है। रिव्यूअर स्थानीय रूप से कुछ भी चलाए बिना कार्यक्षमता का प्रमाण देखते हैं।
%%{init: {"flowchart": {"subGraphTitleMargin": {"top": 3, "bottom": 10}}} }%%
graph TD
A["PR पुश"] --> B
subgraph GHA["GitHub Actions Runner"]
B["Checkout + Docker Compose"] --> C["माइग्रेशन + सीड डेटा"]
C --> Agent
subgraph Agent["Claude Code + Playwright"]
direction LR
D["PR Diff पढ़ें"] --> E["फाइलें → URLs मैप करें"]
E --> F["लॉगिन + नेविगेट"]
F --> G["स्क्रीनशॉट ×3 व्यूपोर्ट्स"]
end
end
Agent --> H["PR कमेंट"]
style GHA fill:transparent,stroke:#888
style Agent fill:transparent,stroke:#888
वर्कफ्लो स्वयं सीधा है:
name: UI Screenshots
on:
pull_request:
types: [opened, synchronize]
jobs:
screenshots:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
# ... Docker Compose सेटअप, माइग्रेशन, टेस्ट यूजर बनाना ...
- name: Start services
run: |
docker compose -f docker-compose.local.yml up -d --wait
- name: Install Playwright
run: npx playwright install --with-deps chromium
- name: Run Claude for Screenshots
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
claude_args: >-
--allowed-tools
"mcp__playwright__*,
Bash(gh pr diff:*),
Bash(gh pr comment:*),
Read,Glob,Grep"
prompt: |
You are a visual QA agent. Your job is to visually
verify a UI deployment.
PR: ${{ github.event.pull_request.number }}
The Django app is running at http://localhost:8001
1. Run `gh pr diff` to find changed templates/views
2. Map changed files to URLs — only test pages
affected by this push
3. Login, then screenshot each page at three viewports:
1440x900, 1024x768, 640x1136
4. Save screenshots with descriptive filenames
5. Post a PR comment with:
- Each test performed with pass/fail
- Any visual issues found
- Total screenshots captured
व्यूपोर्ट मैट्रिक्स
| डिवाइस | साइज़ | क्यों |
|---|---|---|
| डेस्कटॉप | 1440×900 | मानक लैपटॉप |
| टैबलेट | 1024×768 | iPad पोर्ट्रेट |
| मोबाइल | 640×1136 | iPhone SE |
हर इंटरैक्टिव स्थिति तीनों पर कैप्चर होती है। एक साइडबार कंपोनेंट 12+ स्क्रीनशॉट्स जेनरेट करता है:
- पेज लोड (बंद) — 3 व्यूपोर्ट्स
- ट्रिगर क्लिक — 3 व्यूपोर्ट्स
- पूरी तरह खुला — 3 व्यूपोर्ट्स
- बंद एनीमेशन — 3 व्यूपोर्ट्स
लाइट/डार्क थीम्स से गुणा करें और आप एक कंपोनेंट के लिए 24 स्क्रीनशॉट्स देख रहे हैं। यही मुद्दा है। CI आर्टिफैक्ट के रूप में संपूर्ण विजुअल प्रमाण।
यह वास्तव में क्या आउटपुट देता है
यहाँ एक PR से वास्तविक आउटपुट है जिसने एक मैनुअल एंट्री पेज जोड़ा। एजेंट एक संरचित सारांश, हर व्यूपोर्ट पर स्क्रीनशॉट्स और एक टेस्ट चेकलिस्ट के साथ PR कमेंट पोस्ट करता है:

उस सारांश के नीचे, एजेंट हर स्थिति के स्क्रीनशॉट्स जोड़ता है जिसका उसने परीक्षण किया। यहाँ डेस्कटॉप व्यू है—डेटा के साथ क्लाइंट्स लिस्ट, प्लस ओपन Add Client ड्रॉअर:

एजेंट ने परीक्षण किया:
- खाली फॉर्म स्थिति
- वैलिडेशन एरर्स के साथ फॉर्म (आवश्यक नाम फील्ड गायब)
- सफल फॉर्म सबमिशन
- डेटा के साथ क्लाइंट लिस्ट रेंडरिंग
- जब कोई इमेज न हो तो अवतार फॉलबैक्स
- मोडल ओपन/क्लोज ट्रांज़िशन
- तीनों व्यूपोर्ट्स
मैंने इस PR के लिए व्यक्तिगत फील्ड फोकस स्थितियों को छोड़ दिया—एक साधारण फॉर्म पर घटता रिटर्न। एजेंट यह कर सकता है, लेकिन टेक्स्ट इनपुट्स के फोकस पाने के 50 स्क्रीनशॉट्स उपयोगी सिग्नल नहीं हैं।
PR कमेंट एक विजुअल चेंजलॉग बन जाता है। हर टेस्ट रन एक चेकलिस्ट के साथ समाप्त होता है:

छह महीने बाद, मैं किसी भी PR को देख सकता हूं और ठीक-ठीक देख सकता हूं कि जब यह शिप हुआ तो UI कैसा दिखता था।
टेस्ट मेनिफेस्ट
ऊपर वर्कफ्लो में प्रॉम्प्ट जेनेरिक है — यह किसी भी PR के लिए काम करता है। विशिष्टता diff से ही आती है। एजेंट gh pr diff पढ़ता है, पता लगाता है कि कौन से टेम्प्लेट्स और व्यूज बदले, उन्हें URLs पर मैप करता है, और तय करता है कि क्या टेस्ट करना है।
एक फॉर्म कंपोनेंट के लिए, इसका मतलब है कि यह परीक्षण करेगा:
component: ClientForm
states:
- empty form
- filled form (valid data)
- validation error (submit without name)
- submitting (loading state)
- success (confirmation)
interactions:
- submit empty form (trigger validation)
- fill all fields, submit
- verify client appears in list after submit
कोई मैनुअल टेस्ट प्लान की आवश्यकता नहीं। एजेंट कोड परिवर्तनों से टेस्ट सरफेस का अनुमान लगाता है।
PR कमेंट्स में स्क्रीनशॉट्स क्यों
PR कमेंट में इनलाइन स्क्रीनशॉट्स के कुछ फायदे हैं:
- दृश्यमान — रिव्यूअर्स उन्हें आर्टिफैक्ट्स पर क्लिक किए बिना देखते हैं
- संदर्भात्मक — जिस diff की वे समीक्षा कर रहे हैं उसके ठीक बगल में
- तुलनीय — हर पुश कमेंट को अपडेट करता है, इसलिए आप पहले/बाद देखते हैं
- ऑडिट योग्य — कमेंट हिस्ट्री दिखाती है कि हर कमिट पर क्या टेस्ट किया गया था
यह क्या पकड़ता है
पहले सप्ताह में पकड़े गए वास्तविक बग:
overflow: hiddenपेरेंट द्वारा क्लिप किया गया ड्रॉपडाउन (केवल टैबलेट पर दृश्यमान)- डार्क मोड में अदृश्य बटन टेक्स्ट (गलत CSS वेरिएबल)
- iPhone पर मिसअलाइन किए गए फॉर्म लेबल (flexbox gap इशू)
- टच के बाद अटका हुआ होवर स्टेट (
@media (hover: hover)की आवश्यकता थी) - लैंडस्केप टैबलेट पर पूर्ण व्यूपोर्ट को कवर नहीं करने वाला मोडल बैकड्रॉप
इनमें से हर एक कोड रिव्यू पास कर गया। हर एक स्क्रीनशॉट्स में स्पष्ट था।
लागत
CI में Playwright MCP के साथ Claude चलाने में 2-4 मिनट लगते हैं इस पर निर्भर करते हुए कि कितनी स्थितियों को टेस्टिंग की आवश्यकता है। एक कंपोनेंट को छूने वाले एक विशिष्ट PR के लिए, यह लगभग 90 सेकंड है।
तुलना करें: प्रोडक्शन में डिप्लॉय करना और यूजर्स से पता लगाना कि मोबाइल लेआउट टूटा हुआ है। अमूल्य।
बदलाव
विजुअल QA हमेशा बाधा रहा है। आप यूनिट टेस्ट्स, इंटीग्रेशन टेस्ट्स, यहां तक कि एंड-टू-एंड फ्लो को भी ऑटोमेट कर सकते हैं — लेकिन किसी को अभी भी UI को देखना होता है। यह दशकों से सच रहा है।
यह अब सच नहीं है। ब्राउज़र के साथ एजेंट्स केवल स्क्रिप्ट नहीं चलाते। वे व्याख्या करते हैं, नेविगेट करते हैं, इंटरैक्ट करते हैं और निर्णय लेते हैं। टेस्ट सरफेस हार्डकोडेड नहीं है — यह बदलाव से अनुमानित है। हर PR को संपूर्ण विजुअल कवरेज मिलती है जिसका कोई मैनुअल प्रोसेस मिलान नहीं कर सकता।
यह QE को एक गेट से एक गारंटी में बदल देता है। “क्या किसी ने इसे चेक किया” नहीं बल्कि “पाइपलाइन ने इसे चेक किया, यहाँ प्रमाण है।” हर PR, हर पुश, हर व्यूपोर्ट। QE की भूमिका गायब नहीं होती। यह अपस्ट्रीम चली जाती है। टेस्ट प्लान निष्पादित करने के बजाय, आप परिभाषित कर रहे हैं कि एजेंट को क्या परवाह करनी चाहिए। बग पकड़ने के बजाय, आप उन्हें पकड़ने वाली प्रणाली डिज़ाइन कर रहे हैं।