CI पाइपलाइन स्टेज के रूप में विजुअल QA

मैंने पिछले महीने एक PR मर्ज किया। कोड रिव्यू अच्छा दिख रहा था। टेस्ट पास हो गए। फिर मैंने अपने फोन पर साइट खोली और साइडबार पूरी तरह से टूटा हुआ था।

फिक्स तुच्छ था—एक मिसिंग मीडिया क्वेरी। बग तब स्पष्ट था जब आप वास्तव में मोबाइल व्यू देखते। किसी ने नहीं देखा।

इसलिए मैंने एक पाइपलाइन स्टेज जोड़ा जो देखता है।

मैं एक GitHub इशू खोलता हूं जो कहता है:

क्लाइंट्स जोड़ने के लिए मैनुअल एंट्री विकल्प लागू करें। क्लिक करने पर, एक नया क्लाइंट बनाने के लिए फॉर्म के साथ एक चौड़ा स्लाइड-ओवर ड्रॉअर खुलता है।

एक कमिट बाद, PR 30+ स्क्रीनशॉट्स के साथ आता है जो साबित करते हैं कि हर स्थिति हर व्यूपोर्ट पर काम करती है। शून्य मैनुअल टेस्टिंग। एकमात्र प्रयास फीचर विवरण लिखना था।

अवधारणा

PR में हर पुश पर, एक GitHub Actions वर्कफ्लो:

  1. PR ब्रांच से Docker Compose स्टैक (Django + Postgres) बूट करता है
  2. माइग्रेशन चलाता है और एक टेस्ट यूजर सीड करता है
  3. स्थानीय URL को Playwright MCP (हेडलेस Chromium) के साथ Claude Code को सौंपता है
  4. PR diff के आधार पर इंटरैक्टिव एलिमेंट्स का परीक्षण करता है
  5. तीन व्यूपोर्ट्स पर हर स्थिति का स्क्रीनशॉट लेता है
  6. परिणाम को 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×768iPad पोर्ट्रेट
मोबाइल640×1136iPhone SE

हर इंटरैक्टिव स्थिति तीनों पर कैप्चर होती है। एक साइडबार कंपोनेंट 12+ स्क्रीनशॉट्स जेनरेट करता है:

लाइट/डार्क थीम्स से गुणा करें और आप एक कंपोनेंट के लिए 24 स्क्रीनशॉट्स देख रहे हैं। यही मुद्दा है। CI आर्टिफैक्ट के रूप में संपूर्ण विजुअल प्रमाण।

यह वास्तव में क्या आउटपुट देता है

यहाँ एक PR से वास्तविक आउटपुट है जिसने एक मैनुअल एंट्री पेज जोड़ा। एजेंट एक संरचित सारांश, हर व्यूपोर्ट पर स्क्रीनशॉट्स और एक टेस्ट चेकलिस्ट के साथ PR कमेंट पोस्ट करता है:

विजुअल QA एजेंट द्वारा बनाया गया GitHub इशू

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

डेस्कटॉप व्यू: 1440x900 पर क्लाइंट्स लिस्ट और Add Client ड्रॉअर

एजेंट ने परीक्षण किया:

मैंने इस PR के लिए व्यक्तिगत फील्ड फोकस स्थितियों को छोड़ दिया—एक साधारण फॉर्म पर घटता रिटर्न। एजेंट यह कर सकता है, लेकिन टेक्स्ट इनपुट्स के फोकस पाने के 50 स्क्रीनशॉट्स उपयोगी सिग्नल नहीं हैं।

PR कमेंट एक विजुअल चेंजलॉग बन जाता है। हर टेस्ट रन एक चेकलिस्ट के साथ समाप्त होता है:

सभी आइटम्स पास के साथ Testing Performed चेकलिस्ट

छह महीने बाद, मैं किसी भी 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 कमेंट में इनलाइन स्क्रीनशॉट्स के कुछ फायदे हैं:

  1. दृश्यमान — रिव्यूअर्स उन्हें आर्टिफैक्ट्स पर क्लिक किए बिना देखते हैं
  2. संदर्भात्मक — जिस diff की वे समीक्षा कर रहे हैं उसके ठीक बगल में
  3. तुलनीय — हर पुश कमेंट को अपडेट करता है, इसलिए आप पहले/बाद देखते हैं
  4. ऑडिट योग्य — कमेंट हिस्ट्री दिखाती है कि हर कमिट पर क्या टेस्ट किया गया था

यह क्या पकड़ता है

पहले सप्ताह में पकड़े गए वास्तविक बग:

इनमें से हर एक कोड रिव्यू पास कर गया। हर एक स्क्रीनशॉट्स में स्पष्ट था।

लागत

CI में Playwright MCP के साथ Claude चलाने में 2-4 मिनट लगते हैं इस पर निर्भर करते हुए कि कितनी स्थितियों को टेस्टिंग की आवश्यकता है। एक कंपोनेंट को छूने वाले एक विशिष्ट PR के लिए, यह लगभग 90 सेकंड है।

तुलना करें: प्रोडक्शन में डिप्लॉय करना और यूजर्स से पता लगाना कि मोबाइल लेआउट टूटा हुआ है। अमूल्य।

बदलाव

विजुअल QA हमेशा बाधा रहा है। आप यूनिट टेस्ट्स, इंटीग्रेशन टेस्ट्स, यहां तक कि एंड-टू-एंड फ्लो को भी ऑटोमेट कर सकते हैं — लेकिन किसी को अभी भी UI को देखना होता है। यह दशकों से सच रहा है।

यह अब सच नहीं है। ब्राउज़र के साथ एजेंट्स केवल स्क्रिप्ट नहीं चलाते। वे व्याख्या करते हैं, नेविगेट करते हैं, इंटरैक्ट करते हैं और निर्णय लेते हैं। टेस्ट सरफेस हार्डकोडेड नहीं है — यह बदलाव से अनुमानित है। हर PR को संपूर्ण विजुअल कवरेज मिलती है जिसका कोई मैनुअल प्रोसेस मिलान नहीं कर सकता।

यह QE को एक गेट से एक गारंटी में बदल देता है। “क्या किसी ने इसे चेक किया” नहीं बल्कि “पाइपलाइन ने इसे चेक किया, यहाँ प्रमाण है।” हर PR, हर पुश, हर व्यूपोर्ट। QE की भूमिका गायब नहीं होती। यह अपस्ट्रीम चली जाती है। टेस्ट प्लान निष्पादित करने के बजाय, आप परिभाषित कर रहे हैं कि एजेंट को क्या परवाह करनी चाहिए। बग पकड़ने के बजाय, आप उन्हें पकड़ने वाली प्रणाली डिज़ाइन कर रहे हैं।