मोबाइल टेस्ट ऑटोमेशन की व्याख्या

मोबाइल टेस्ट ऑटोमेशन emulator, simulator या असली डिवाइस पर ऐप चलाता है और किसी इंसान के स्क्रीन टैप किए बिना उसका व्यवहार जाँचता है। तीन टूल ज़्यादातर क्षेत्र कवर करते हैं: Android के लिए Espresso और iOS के लिए XCUITest, जो प्लेटफ़ॉर्म के अपने UI टेस्टिंग फ़्रेमवर्क हैं, और Appium, एक open-source सर्वर जो WebDriver प्रोटोकॉल से दोनों प्लेटफ़ॉर्म चलाता है। ये इस बात में अलग हैं कि टेस्ट कहाँ चलता है, ऐप का इंतज़ार कैसे करता है, आम तौर पर कौन लिखता है, और डिवाइस के कितने हिस्से तक पहुँच सकता है।

यह व्याख्या तीनों की तुलना करती है, हर एक में एक छोटा टेस्ट दिखाती है, और उन हिस्सों को कवर करती है जो तय करते हैं कि मोबाइल suite पर भरोसा होगा या उसे नज़रअंदाज़ किया जाएगा: locators, flakiness, device farm और CI। बड़ा संदर्भ — डिवाइस स्ट्रैटेजी, जोखिम क्षेत्र, सुरक्षा — मोबाइल टेस्टिंग पिलर गाइड में है।

मोबाइल पर क्या ऑटोमेट करें

Test pyramid मोबाइल पर भी किसी और प्रोडक्ट की तरह लागू होता है (manual vs automated testing गाइड कारण बताती है): ज़्यादातर checks UI के नीचे होने चाहिए, जहाँ वे तेज़ और स्थिर हैं। Android पर local unit टेस्ट development मशीन के JVM पर सेकंडों में चलते हैं, जबकि instrumented टेस्ट डिवाइस या emulator पर चलते हैं; iOS पर XCTest एक ही Xcode प्रोजेक्ट से unit और UI टेस्ट चलाता है। बिज़नेस नियम, validation और गणनाएँ unit टेस्ट और बैक एंड के API टेस्ट में होनी चाहिए। UI टेस्ट उन journeys के लिए हैं जो कभी टूटनी नहीं चाहिए — साइन-इन, onboarding, search, checkout, ऐप का मुख्य फ़ीचर — और स्क्रीन के बीच की wiring के लिए।

  • Unit टेस्ट — view models, formatters, validation, लोकल डेटाबेस queries; हर commit पर चलें।
  • Instrumented या integration टेस्ट — वह कोड जिसे प्लेटफ़ॉर्म चाहिए: storage, लोकल डेटाबेस, बैकग्राउंड काम; emulator या simulator पर चलें।
  • API टेस्ट — ऐप जिस बैक एंड को कॉल करता है, error responses और पुराने client के साथ compatibility समेत।
  • UI टेस्ट — हर प्लेटफ़ॉर्म के लिए critical journeys का छोटा सेट, CI में emulator पर और रिलीज़ से पहले असली डिवाइस पर।
  • मैन्युअल और exploratory टेस्टिंग — gestures, असली इंटरप्शन, look and feel, असली डिवाइस का व्यवहार (मैन्युअल रहने वाले हिस्से वाला सेक्शन देखें)।

Espresso, XCUITest और Appium की तुलना

कोई सार्वभौमिक विजेता नहीं है। अगर टेस्ट developers के हैं और प्लेटफ़ॉर्म अलग-अलग टीमें बनाती हैं, तो नेटिव फ़्रेमवर्क सबसे उपयुक्त हैं: सबसे तेज़ feedback, सबसे कम flakiness, ऐप वाली ही भाषा। अगर एक अलग automation टीम साझा flows के साथ दोनों प्लेटफ़ॉर्म कवर करती है, या टेस्ट को source access के बिना release जैसे builds पर चलना है, तो Appium का एक codebase और भाषा की आज़ादी ज़्यादा मायने रखती है। कई टीमें दोनों मिलाती हैं: developer pipeline में स्क्रीन-स्तर के टेस्ट के लिए नेटिव फ़्रेमवर्क, और end-to-end journeys के लिए छोटा cross-platform Appium suite।

  • Espresso — सिर्फ़ Android; टेस्ट Kotlin या Java में; ऐप के process के अंदर instrumentation टेस्ट के रूप में चलता है। यह ऐप के UI thread के साथ अपने-आप sync होता है, इसलिए सिर्फ़ तब action लेता है जब UI idle हो; जो बैकग्राउंड काम इसे नहीं दिखता वह idling resources के ज़रिए रजिस्टर होता है। तेज़ और स्थिर; आम तौर पर Android developers कोड के साथ लिखते हैं। यह ऐप के बाहर के सिस्टम UI तक नहीं पहुँचता — उसके लिए UI Automator है।
  • XCUITest — सिर्फ़ iOS; टेस्ट Swift या Objective-C में, Xcode में XCTest के साथ लिखे जाते हैं (Apple अब UI testing API को XCUIAutomation नाम से document करता है)। test runner एक अलग process है जो accessibility layer के ज़रिए ऐप को वैसे चलाता है जैसे यूज़र। यह interact करने से पहले ऐप के स्थिर होने का इंतज़ार करता है और सिस्टम alerts सँभाल सकता है। आम तौर पर iOS developers या Xcode में काम करने वाले automation engineers लिखते हैं।
  • Appium — Android, iOS और दूसरे प्लेटफ़ॉर्म; किसी भी ऐसी भाषा में टेस्ट जिसका WebDriver client हो (Java, Python, JavaScript, C#, Ruby…)। client W3C WebDriver commands Appium सर्वर को भेजता है, जो डिवाइस पर action के लिए प्लेटफ़ॉर्म driver इस्तेमाल करता है — जैसे Android पर UiAutomator2 driver और iOS पर XCUITest driver। यह ऐप को black box मानता है, हाइब्रिड ऐप के WebView context में जा सकता है, और मोबाइल ब्राउज़र ऑटोमेट कर सकता है। हर step ज़्यादा परतें पार करता है, इसलिए यह नेटिव फ़्रेमवर्क से धीमा है।
टेस्ट कोड कहाँ चलता है, यही बाक़ी सब समझाता है: Espresso ऐप के process के अंदर चलता है, XCUITest उसे अलग process से चलाता है, और Appium का हर step client, सर्वर और driver पार करता है।

Espressoसिर्फ़ Android

ऐप के process के अंदर

  1. 1टेस्ट: view ढूँढे, action करे, assertion जाँचेinstrumentation टेस्टidle UI thread का इंतज़ार
  2. 2ऐप के views
टेस्ट की भाषा:
Kotlin या Java
इंतज़ार कैसे करता है:
UI thread idle होने तक अपने-आप; जो बैकग्राउंड काम इसे नहीं दिखता वह idling resources के ज़रिए रजिस्टर होता है
आम तौर पर कौन लिखता है:
Android developers, कोड के साथ
पहुँच:
सिर्फ़ ऐप के अंदर; सिस्टम UI के लिए UI Automator
गति:
तेज़ और स्थिर

XCUITestसिर्फ़ iOS

  1. 1Test runnerएक अलग processaccessibility layer के ज़रिए
  2. 2ऐपउसका element tree, type और identifier से query
टेस्ट की भाषा:
Swift या Objective-C
इंतज़ार कैसे करता है:
ऐप के स्थिर होने का इंतज़ार; बाद में दिखने वाले एलिमेंट के लिए waitForExistence(timeout:)
आम तौर पर कौन लिखता है:
iOS developers या Xcode में काम करने वाले automation engineers
पहुँच:
ऐप, और सिस्टम alerts भी
गति:
नेटिव: Appium से तेज़ feedback

AppiumAndroid, iOS और अन्य

  1. 1टेस्ट कोड + WebDriver clientW3C WebDriver commands
  2. 2Appium सर्वर
  3. 3प्लेटफ़ॉर्म driverजैसे Android पर UiAutomator2 driver, iOS पर XCUITest driver
  4. 4डिवाइस पर ऐपblack box माना जाता है
टेस्ट की भाषा:
कोई भी भाषा जिसका WebDriver client हो
इंतज़ार कैसे करता है:
किसी condition का explicit wait, जैसे एलिमेंट का मौजूद होना
आम तौर पर कौन लिखता है:
दोनों प्लेटफ़ॉर्म कवर करने वाली अलग automation टीम के लिए उपयुक्त
पहुँच:
ऐप black box के रूप में, हाइब्रिड ऐप के WebView context, मोबाइल ब्राउज़र
गति:
धीमा: हर step ज़्यादा परतें पार करता है

Espresso: process के अंदर और synchronised

Espresso टेस्ट matcher से view ढूँढता है, उस पर action करता है, और assertion जाँचता है। हर action और assertion से पहले Espresso UI thread की message queue के idle होने तक इंतज़ार करता है, जिससे वह ज़्यादातर waiting कोड हट जाता है जो दूसरे टूल्स को चाहिए। जो काम कहीं और चलता है — कस्टम thread pool, या ऐसी network library जिसे Espresso नहीं जानता — उसे idling resource के रूप में रजिस्टर करना होगा, वरना टेस्ट उससे race करेगा। Jetpack Compose से बनी स्क्रीन Compose के अपने testing APIs से टेस्ट होती हैं, जो इसी सिद्धांत पर चलते हैं।

@RunWith(AndroidJUnit4::class)
class LoginTest {
    @get:Rule
    val activityRule = ActivityScenarioRule(LoginActivity::class.java)

    @Test
    fun wrongPasswordShowsError() {
        onView(withId(R.id.email)).perform(typeText("layla.h@example.com"), closeSoftKeyboard())
        onView(withId(R.id.password)).perform(typeText("wrong-pass-1"), closeSoftKeyboard())
        onView(withId(R.id.sign_in)).perform(click())
        onView(withText(R.string.error_invalid_credentials)).check(matches(isDisplayed()))
    }
}

XCUITest: accessibility के ज़रिए black-box

XCUITest टेस्ट ऐप को अलग process के रूप में लॉन्च करता है और उसके element tree को type और identifier से query करता है: buttons, text fields, static texts। Developers हर उस एलिमेंट पर accessibilityIdentifier लगाते हैं जिसकी टेस्ट को ज़रूरत है; accessibility label के उलट, identifier VoiceOver नहीं बोलता, इसलिए यह स्थिर तकनीकी नाम हो सकता है। Launch arguments और environment variables ऐप को टेस्ट स्थिति में डालते हैं — mock server URL, reset data store, बंद animations — बिना विशेष builds के। async काम के बाद दिखने वाले एलिमेंट के लिए fixed sleep के बजाय waitForExistence(timeout:) इस्तेमाल करें।

final class LoginUITests: XCTestCase {
    func testWrongPasswordShowsError() {
        let app = XCUIApplication()
        app.launchArguments += ["-uiTesting", "-resetState"]
        app.launch()

        let email = app.textFields["login.email"]
        email.tap()
        email.typeText("layla.h@example.com")

        let password = app.secureTextFields["login.password"]
        password.tap()
        password.typeText("wrong-pass-1")

        app.buttons["login.submit"].tap()

        XCTAssertTrue(app.staticTexts["login.error"].waitForExistence(timeout: 5))
    }
}

Appium: मोबाइल के लिए WebDriver

Appium एक सर्वर है। आपका टेस्ट, जो WebDriver client library से लिखा गया है, capabilities भेजकर session खोलता है — कौन सा प्लेटफ़ॉर्म, कौन सा automation driver, कौन सा ऐप, कौन सा डिवाइस — और फिर find element, click और send keys जैसे commands भेजता है। Appium 2 से drivers सर्वर से अलग इंस्टॉल होते हैं, इसलिए प्रोजेक्ट ठीक-ठीक बताता है कि वह कौन से driver वर्ज़न इस्तेमाल करता है। जो capabilities W3C मानक का हिस्सा नहीं हैं उन पर appium: prefix लगता है। क्योंकि Appium ऐप को बाहर से चलाता है, वही टेस्ट emulator पर debug build और device farm के फ़ोन पर release candidate दोनों पर चल सकता है।

from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

caps = {
    "platformName": "Android",
    "appium:automationName": "UiAutomator2",
    "appium:deviceName": "Pixel_Test",
    "appium:app": "/builds/shop-4.0.0-debug.apk",
    "appium:autoGrantPermissions": True,
}
driver = webdriver.Remote("http://127.0.0.1:4723", options=UiAutomator2Options().load_capabilities(caps))
try:
    driver.find_element(AppiumBy.ACCESSIBILITY_ID, "login.email").send_keys("layla.h@example.com")
    driver.find_element(AppiumBy.ACCESSIBILITY_ID, "login.password").send_keys("wrong-pass-1")
    driver.find_element(AppiumBy.ACCESSIBILITY_ID, "login.submit").click()
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((AppiumBy.ACCESSIBILITY_ID, "login.error")))
finally:
    driver.quit()

मोबाइल पर locators

Locator वह तरीक़ा है जिससे टेस्ट एलिमेंट ढूँढता है, और मोबाइल पर इसका चुनाव स्थिरता और गति दोनों तय करता है। Developers के साथ identifier की naming convention तय करें (जैसे screen.element: login.submit), टेस्ट जिन एलिमेंट को छूते हैं उन सब पर identifiers लगाएँ, और "test identifiers मौजूद हैं" को definition of done का हिस्सा बनाएँ। सामान्य सिद्धांत locator strategies गाइड में हैं; मोबाइल की ख़ास बातें नीचे हैं।

  • Accessibility id — Appium की पसंदीदा strategy। iOS पर यह accessibilityIdentifier से मेल खाता है, जिसे VoiceOver नहीं पढ़ता, इसलिए यह तकनीकी नाम हो सकता है। Android पर यह content description से मेल खाता है, जिसे TalkBack ज़ोर से पढ़ता है — इसलिए Android पर यह असली इंसानी label होना चाहिए, वरना resource id इस्तेमाल करें।
  • Resource id (Android) — जैसे com.example.shop:id/sign_in; तब तक स्थिर जब तक developers ids न बदलें।
  • प्लेटफ़ॉर्म-नेटिव queries — UiAutomator2 के लिए UiSelector, iOS पर predicate strings और class chains — जब ऊपर वाले फ़िट न हों; XPath से तेज़।
  • दिखने वाला टेक्स्ट — ऐप localize होने पर टूट जाता है (अरबी और अंग्रेज़ी builds अलग टेक्स्ट दिखाते हैं); सिर्फ़ हर locale के resources के साथ इस्तेमाल करें।
  • XPath — आख़िरी उपाय: मोबाइल पर धीमा क्योंकि पूरी view hierarchy serialise करनी पड़ती है, और layout बदलने पर नाज़ुक।
  • Cross-platform फ़्रेमवर्क (React Native, Flutter) अपनी test-id property देते हैं; उस पर locators बनाने से पहले जाँचें कि वह हर प्लेटफ़ॉर्म पर किससे map होती है।

मोबाइल UI टेस्ट flaky क्यों होते हैं — और क्या करें

Flaky टेस्ट एक ही कोड पर कभी पास और कभी फ़ेल होता है। मोबाइल आम कारणों (asynchrony, shared state, remote services, समय) में अपने कारण जोड़ता है, और बेतरतीब फ़ेल होने वाला suite जल्दी नज़रअंदाज़ होने लगता है। flaky tests गाइड पहचान और quarantine कवर करती है; ये मोबाइल-विशेष स्रोत हैं।

  • Animations और transitions — टेस्ट डिवाइस और emulator पर इन्हें बंद करें (नीचे की तीन animation scale settings), या iOS पर launch arguments से।
  • ऐसी asynchrony जो फ़्रेमवर्क को नहीं दिखती — Espresso में idling resources रजिस्टर करें, बाक़ी हर जगह शर्तों (एलिमेंट मौजूद है, enabled है) का इंतज़ार करें; fixed sleep कभी नहीं।
  • सिस्टम डायलॉग — permission prompts, "app isn’t responding", कीबोर्ड टिप्स, OS update prompts। जहाँ टेस्ट permissions के बारे में नहीं है वहाँ पहले से permission दें, और अपेक्षित सिस्टम alerts को स्पष्ट रूप से सँभालें।
  • टेस्ट के बीच state का रिसना — साइन-इन session, लोकल डेटा, feature flags। हर टेस्ट पर reset करें: ऐप डेटा clear करें (Android Test Orchestrator टेस्ट के बीच package data clear कर सकता है) या iOS पर reset argument के साथ लॉन्च करें।
  • असली नेटवर्क और साझा बैक एंड — mock server या seeded test environment इस्तेमाल करें, और हर run के लिए unique डेटा generate करें।
  • अगले एलिमेंट को ढकने वाला soft keyboard, और ऐसे एलिमेंट जिन्हें दिखाने के लिए scroll चाहिए।
  • डिवाइस और emulator की सेहत — धीमा boot, भरा storage, कम बैटरी या गर्म farm डिवाइस। health checks जोड़ें; retry सिर्फ़ infrastructure स्तर पर, असली विफलता छिपाने के लिए कभी नहीं।
  • मैट्रिक्स के डिवाइसों के बीच locale, timezone और घड़ी का अंतर।
# Android — turn off animations on a test device or emulator
adb shell settings put global window_animation_scale 0
adb shell settings put global transition_animation_scale 0
adb shell settings put global animator_duration_scale 0

आज़माएँ: Mock API रिस्पॉन्स जनरेटर आज़माएँ: API स्टेटस कोड सिम्युलेटर आज़माएँ: Mock एरर रिस्पॉन्स जनरेटर आज़माएँ: फ़ेक यूज़र जनरेटर

Device farm और CI pipeline

Android emulator Linux, Windows या macOS CI मशीनों पर चलते हैं और तेज़ होने के लिए hardware acceleration चाहते हैं (Linux पर KVM); iOS simulator के लिए macOS ज़रूरी है। लंबे suites को shards में बाँटें जो कई emulator या डिवाइस पर समानांतर चलें। क्लाउड device farm आपका ऐप और test package लेकर आपके चुने असली डिवाइस पर चलाता है और वीडियो, screenshots और logs के साथ नतीजे लौटाता है; वही डिवाइस आम तौर पर मैन्युअल session के लिए भी मिलते हैं। farm डिवाइस अपने डिवाइस मैट्रिक्स से चुनें, और secondary parameters (भाषा, orientation, font size) के लिए runs गुणा करने के बजाय pairwise चयन इस्तेमाल करें।

नतीजे ऐसे फ़ॉर्मेट में publish करें जिसे CI सर्वर समझता हो (JUnit XML आम है) और हर फ़ेल टेस्ट के artefacts रखें। बिना वीडियो और डिवाइस log वाला red build ऐसा build है जिसे कोई ठीक करने के बजाय दोबारा चला देगा।

नीचे का उदाहरण (illustrative) pipeline की एक संभावित लय दिखाता है: हर pull request पर unit टेस्ट, ऐप और test package का build, हर प्लेटफ़ॉर्म के एक emulator/simulator पर 10–20 critical टेस्ट का smoke suite, और staging बैक एंड के ख़िलाफ़ API contract टेस्ट। हर रात emulators और simulators पर shards में बँटा पूरा UI suite, और device farm में Tier 1 और Tier 2 डिवाइस। रिलीज़ से पहले release candidate को Tier 1 और Tier 2 डिवाइस पर चलाया जाता है (बड़ी रिलीज़ से पहले Tier 3 पर भी), असली डिवाइस पर exploratory session होता है, और ऐप का सबसे पुराना सपोर्टेड वर्ज़न नए बैक एंड के ख़िलाफ़ चलता है। Tiers वही हैं जो मोबाइल टेस्टिंग पिलर गाइड के उदाहरण वाले डिवाइस मैट्रिक्स में हैं। हर फ़ेल टेस्ट के लिए: वीडियो, screenshots, डिवाइस log और JUnit XML।

Example mobile pipeline

on every pull request
  1. unit tests (JVM / XCTest unit)
  2. build the app and the test package (test APK / UI test bundle)
  3. UI smoke: 10–20 critical tests on one Android emulator and one iOS simulator
  4. API contract tests against the staging back end
nightly
  5. full UI suite, sharded across emulators and simulators
  6. Tier 1 and Tier 2 real devices in a device farm
before release
  7. release candidate on the Tier 1 and Tier 2 devices (Tier 3 too before a major release)
     + exploratory session on real devices
  8. oldest supported app version against the new back end (API smoke)
for every failed test: video, screenshots, device log, JUnit XML

आज़माएँ: पेयरवाइज़ टेस्टिंग जनरेटर आज़माएँ: API स्कीमा वैलिडेटर

क्या मैन्युअल रहता है

ऑटोमेशन वही जाँचता है जो पूछना आप पहले से जानते हैं। मोबाइल पर कई अहम सवालों का सबसे अच्छा जवाब अब भी असली डिवाइस वाला इंसान देता है: gestures इस्तेमाल में कैसे लगते हैं, जिस डिवाइस के लिए किसी ने script नहीं लिखी उस पर layout ठीक दिखता है या नहीं, असली नेटवर्क पर असली फ़ोन कॉल के दौरान क्या होता है, और क्या ऐप screen reader के साथ इस्तेमाल लायक है। दोनों प्लेटफ़ॉर्म पर ऑटोमेटेड एक्सेसिबिलिटी checks मौजूद हैं — Espresso टेस्ट के दौरान accessibility checks चला सकता है, और XCUITest accessibility audit चला सकता है — और वे missing labels, छोटे touch targets और कम contrast पकड़ते हैं, पर TalkBack या VoiceOver session की जगह नहीं लेते।

  • हर release candidate के लिए असली डिवाइस पर exploratory sessions।
  • असली इंटरप्शन: कॉल, Bluetooth, दूसरे ऐप के notifications।
  • डिवाइसों पर visual review, जब तक आप screenshot टेस्ट maintain नहीं करते।
  • Screen reader और बड़े टेक्स्ट वाले sessions।
  • सबसे कमज़ोर डिवाइस पर बैटरी, गर्मी और परफ़ॉर्मेंस।
  • स्टोर builds: स्टोर या beta channel से ठीक वैसे इंस्टॉल करना जैसे यूज़र करते हैं।

आज़माएँ: टेस्ट डेटा फ़ैक्टरी

अक्सर पूछे जाने वाले सवाल

Appium या Espresso — कौन सा इस्तेमाल करूँ?

Espresso, अगर Android developers टेस्ट लिखते हैं और आपको सबसे तेज़, सबसे स्थिर feedback चाहिए। Appium, अगर एक automation टीम साझा flows के साथ Android और iOS कवर करती है, एक भाषा पसंद करती है, या release जैसे builds को black box की तरह टेस्ट करना है। कई टीमें दोनों इस्तेमाल करती हैं।

क्या XCUITest और XCTest एक ही हैं?

XCTest unit, performance और UI टेस्ट के लिए Apple का testing फ़्रेमवर्क है। XCUITest उसके UI testing हिस्से का आम नाम है, जिसे Apple अब XCUIAutomation के रूप में document करता है: ऐसे टेस्ट जो ऐप लॉन्च करके accessibility के ज़रिए उससे interact करते हैं।

क्या Appium हाइब्रिड ऐप और मोबाइल वेब टेस्ट कर सकता है?

हाँ। Appium नेटिव context से हाइब्रिड ऐप के WebView context में जाकर वहाँ web locators इस्तेमाल कर सकता है, और Android पर Chrome और iOS पर Safari जैसे मोबाइल ब्राउज़र ऑटोमेट कर सकता है।

Locator के रूप में accessibility ids क्यों?

वे layout और दिखने वाले टेक्स्ट से स्वतंत्र हैं, इसलिए redesign और localization के बाद भी टिकते हैं, और उन्हें ढूँढना तेज़ है। याद रखें कि Android पर accessibility id वह content description है जिसे TalkBack पढ़ता है, इसलिए वह असली label हो या resource ids इस्तेमाल करें।

CI में मोबाइल UI टेस्ट कैसे चलाएँ?

हर pull request पर Android emulator (hardware acceleration के साथ) और iOS simulator (macOS runners पर) पर छोटा smoke suite, हर रात shards में पूरा suite, और रिलीज़ से पहले device farm में असली डिवाइस — विफलताओं का वीडियो और logs रखते हुए।

मोबाइल UI टेस्ट की flakiness कैसे घटाएँ?

Animations बंद करें, sleep के बजाय फ़्रेमवर्क के synchronisation और condition waits पर भरोसा करें, हर टेस्ट पर ऐप state reset करें, permissions पहले से दें, बैक एंड को mock या seed करें, और डिवाइस स्वस्थ रखें। flaky टेस्ट को quarantine करें और कारण ठीक करें।

संदर्भ

  • Appium DocumentationAppium (OpenJS Foundation)iOS और Android पर नेटिव, हाइब्रिड और मोबाइल-वेब ऐप के ऑटोमेशन का आधिकारिक दस्तावेज़।
  • EspressoAndroid Developers (Google)Android का UI टेस्टिंग फ़्रेमवर्क, जो टेस्ट एक्शन को ऐप के UI थ्रेड के साथ अपने-आप सिंक्रोनाइज़ करता है।
  • XCUIAutomationAppleUI टेस्ट के लिए Apple का API जो ऐप लॉन्च करके उसके एलिमेंट से यूज़र की तरह इंटरैक्ट करता है (XCUITest का आधार)।
  • XCTestAppleiOS और अन्य Apple प्लेटफ़ॉर्म पर Xcode प्रोजेक्ट के unit, performance और UI टेस्ट के लिए Apple का फ़्रेमवर्क।
  • Test apps on AndroidAndroid Developers (Google)Android की आधिकारिक टेस्टिंग गाइडेंस: टेस्ट के प्रकार और दायरा, local बनाम instrumented टेस्ट, और बेहतरीन तरीके।
  • Eradicating Non-Determinism in Tests (Martin Fowler)martinfowler.com · 2011flaky टेस्ट सूट का मूल्य क्यों नष्ट करते हैं, उनके आम कारण (isolation, asynchrony, remote services, समय, resource leak) और जवाब के रूप में quarantine।
  • Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0ISTQB · 2024टेस्ट ऑटोमेशन समाधान और उनकी आर्किटेक्चर के डिज़ाइन, कार्यान्वयन और रखरखाव पर ISTQB का advanced पाठ्यक्रम।
  • Certified Tester Mobile Application Testing (CT-MAT)ISTQB · 2019मोबाइल टेस्टिंग पर ISTQB का specialist पाठ्यक्रम: ऐप के प्रकार, डिवाइस व प्लेटफ़ॉर्म की चुनौतियाँ, टेस्ट प्रकार और टूल।

अभ्यास

Promo code वाले flaky Appium टेस्ट को स्थिर करें

आपका काम

आप एक grocery delivery ऐप (काल्पनिक) टेस्ट करते हैं, जो Android और iOS पर अरबी और अंग्रेज़ी UI के साथ चलता है। Release 7.2 cart में promo codes जोड़ती है, और एक automation engineer ने नीचे वाला Appium टेस्ट nightly UI suite में जोड़ा है, जो device farm के फ़ोनों पर चार समानांतर shards में चलता है। पिछली 40 रातों में यह टेस्ट हर रात एक बार चला और अपने 40 runs में से 14 में फ़ेल हुआ, टीम nightly नतीजों को नज़रअंदाज़ करने लगी है, और release क़रीब है। Material में setup, line numbers के साथ टेस्ट, हर फ़ेल run के साथ farm के वीडियो में दिखी बात, और टीम के दो notes हैं।

गाइड के layers, locators, flakiness और device farm वाले सेक्शन के साथ काग़ज़ पर काम करें, और line numbers का हवाला दें। दो लोग आपके जवाब का इंतज़ार कर रहे हैं: product owner रीम जानना चाहती है कि SAVE20 काम करता है या नहीं, और developer उमर सुझाव देता है कि फ़ेल टेस्ट अपने-आप तीन बार तक दोबारा चलाए जाएँ। इसके लिए 45–60 मिनट रखें।

सामग्री
Grocery delivery ऐप (काल्पनिक) - Android और iOS, अरबी और अंग्रेज़ी UI
Release 7.2, Android build 7.2.0-rc1
Promo नियम PR-4: code SAVE20 cart के subtotal से 20% घटाता है।

Nightly UI suite: pytest + Appium 2, UiAutomator2 driver के साथ। Suite 4 shards में
बँटा है, जो समानांतर चलते हैं, device farm के हर फ़ोन पर एक: फ़ोन A, B, C और D।
हर रात shard plan हर टेस्ट को एक shard पर रखता है, इसलिए टेस्ट रात में एक बार चलता है।
हर shard tests/ui में से अपने हिस्से के टेस्ट सादे pytest से (बिना options) चलाता है;
run का सिर्फ़ farm वाला वीडियो रखा जाता है।
फ़ोन C low-end फ़ोन है, जिसकी स्क्रीन मैट्रिक्स में सबसे छोटी है।
Pairwise डिवाइस मैट्रिक्स हर run को एक भाषा देता है: en या ar।
सभी shards एक ही test account से साइन-इन करते हैं: qa.shopper@example.com

test_checkout.py
 1  import time
 2  from appium import webdriver
 3  from appium.options.android import UiAutomator2Options
 4  from appium.webdriver.common.appiumby import AppiumBy
 5
 6  CAPS = {
 7      "platformName": "Android",
 8      "appium:automationName": "UiAutomator2",
 9      "appium:app": "/builds/grocer-7.2.0-rc1.apk",
10      "appium:noReset": True,
11  }
12
13  def test_apply_promo_code(device_name):
14      # precondition: test_login has already signed in as qa.shopper@example.com
15      # and the cart holds one item: rice 5 kg, SAR 100.00
16      caps = {**CAPS, "appium:deviceName": device_name}
17      driver = webdriver.Remote(
18          "http://127.0.0.1:4723",
19          options=UiAutomator2Options().load_capabilities(caps))
20      driver.find_element(AppiumBy.XPATH,
21          "//android.widget.FrameLayout[2]/android.widget.LinearLayout"
22          "/android.widget.TextView[3]").click()   # Cart tab
23      time.sleep(3)
24      promo = driver.find_element(AppiumBy.ID, "com.example.grocer:id/promo_input")
25      promo.send_keys("SAVE20")
26      driver.find_element(AppiumBy.XPATH,
27          '//android.widget.Button[@text="Apply"]').click()
28      time.sleep(2)
29      total = driver.find_element(AppiumBy.ACCESSIBILITY_ID, "cart.total").text
30      assert total == "SAR 80.00"
31      driver.quit()

पिछली 40 रातें: test_apply_promo_code 40 बार चला, 26 बार पास और 14 बार फ़ेल हुआ।

F1-F5    भाषा ar वाले 5 runs (चारों फ़ोन)
         NoSuchElementException: //android.widget.Button[@text="Apply"]
         वीडियो: cart स्क्रीन अरबी में; बटन पर "تطبيق" (Apply), total "100.00 ر.س"
F6-F8    फ़ोन C, en (फ़ोन C पर बाक़ी en runs पास हुए)
         AssertionError: assert 'SAR 100.00' == 'SAR 80.00'
         वीडियो: field में SAVE20; keyboard खुला रहता है और "Apply" को ढक देता है
F9-F10   फ़ोन B, en
         AssertionError: assert 'SAR 100.00' == 'SAR 80.00'
         वीडियो: total पर spinner; टेस्ट ख़त्म होने के बाद वह SAR 80.00 हो जाता है
         staging log: उन दो रातों में promo request में 2.6 s और 3.1 s लगे
F11-F12  फ़ोन A, en
         AssertionError: assert 'SAR 140.00' == 'SAR 80.00'
         वीडियो: cart में 3 items, subtotal SAR 175.00; इस टेस्ट के चलते समय दूसरे shard
         के एक टेस्ट ने उनमें से 2 जोड़े
F13      फ़ोन D, en
         NoSuchElementException: (Cart tab का XPath, lines 20-22)
         वीडियो: सिस्टम डायलॉग "Allow Grocer to send you notifications?"
F14      फ़ोन B, en
         NoSuchElementException: (Cart tab का XPath, lines 20-22)
         वीडियो: sign-in स्क्रीन; उस रात shard plan ने test_login को फ़ोन D पर रखा

टीम के notes
  रीम (product owner): "7.2 ship करने से पहले: SAVE20 काम करता है या नहीं?"
  उमर (developer): "यह बस flaky है। फ़ेल टेस्ट अपने-आप 3 बार तक दोबारा चलाएँ,
  ताकि nightly हरा हो जाए।"
चरण
  1. 14 फ़ेल runs को groups में बाँटें। हर group के लिए गाइड से उसका स्रोत बताएँ (locator, asynchrony, soft keyboard, सिस्टम डायलॉग, टेस्ट के बीच state का रिसना, साझा बैक एंड), टेस्ट की ज़िम्मेदार lines, और यह कि वह किसी ज्ञात शर्त में हर बार फ़ेल होता है या सिर्फ़ कभी-कभी। फिर रीम के लिए एक-दो वाक्य लिखें।
  2. टेस्ट में वे समस्याएँ खोजें जिनसे अभी तक कोई run फ़ेल नहीं हुआ: locators, assertion, clean-up, और टेस्ट फ़ेल होने पर रखे जाने वाले सबूत।
  3. लिखें कि टेस्ट का स्थिर वर्ज़न क्या अलग करता है, numbered list में या Python में।
  4. Checks को layers में बाँटें: PR-4 के कौन-से checks unit या API टेस्ट में होने चाहिए, इस UI टेस्ट में क्या रहता है, और कम से कम एक check जो मैन्युअल रहता है।
  5. उमर को जवाब दें, और बताएँ कि ठीक होने तक टेस्ट के साथ क्या होता है और उसके बाद वह कहाँ चलता है।
मॉडल उत्तर दिखाएँ
मॉडल उत्तर

छह groups। F1–F5: टेस्ट के locator में defect, flakiness नहीं। Lines 26–27 दिखने वाला अंग्रेज़ी टेक्स्ट "Apply" ढूँढती हैं, जिसे अरबी UI "تطبيق" दिखाता है, इसलिए यह lookup हर अरबी run में फ़ेल होता है और किसी अंग्रेज़ी run में नहीं; यह सिर्फ़ इसलिए बेतरतीब लगता है क्योंकि मैट्रिक्स ने 40 में से सिर्फ़ 5 runs को अरबी दी, जो चारों फ़ोनों पर बँटे थे। F6–F8: अगले एलिमेंट को ढकने वाला soft keyboard। Line 25 के send_keys के बाद keyboard खुला रहता है और मैट्रिक्स की सबसे छोटी स्क्रीन पर "Apply" को ढक देता है, इसलिए lines 26–27 का tap उस तक नहीं पहुँचता और total SAR 100.00 ही रहता है; यह सिर्फ़ फ़ोन C पर होता है, और वहाँ भी हर run में नहीं। F9–F10: fixed sleep से सँभाली गई asynchrony। Line 28 दो सेकंड रुकती है, promo request में 2.6 और 3.1 सेकंड लगे, और line 29 ने total को बदलने से पहले ही पढ़ लिया।

F11–F12: साझा बैक एंड पर साझा state। चारों shards एक ही account से साइन-इन करते हैं, इसलिए इस टेस्ट के चलते समय दूसरे shard के एक टेस्ट ने server वाले उसी cart में दो items जोड़ दिए (SAR 175.00 के subtotal में से 20% घटाने पर SAR 140.00); lines 14–15 ऐसा cart मानती हैं जिसे टेस्ट कभी बनाता ही नहीं। F13: सिस्टम डायलॉग। Notification permission prompt ऐप को ढक देता है क्योंकि permissions पहले से नहीं दी गईं (lines 6–11); यह सिर्फ़ उस run में दिखता है जिसमें उसी फ़ोन पर किसी पहले वाले टेस्ट ने prompt का जवाब नहीं दिया। F14: टेस्ट के क्रम पर निर्भरता के रूप में state का रिसना। टेस्ट मानता है कि test_login उससे पहले उसी फ़ोन पर साइन-इन कर चुका है (line 10 और lines 14–15), और उस रात shard plan ने test_login को दूसरे फ़ोन पर रख दिया।

Flaky है या नहीं: F1–F5 हर बार फ़ेल होते हैं जब भाषा अरबी हो, इसलिए यह टेस्ट का reproducible defect है। F6–F14 उसी कोड पर कभी पास और कभी फ़ेल होते हैं, उन हालात के हिसाब से जिन पर टेस्ट का नियंत्रण नहीं — सबसे छोटी स्क्रीन पर keyboard, response time, दूसरे shards क्या कर रहे हैं, डिवाइस की state और shard plan — इसलिए वे गाइड के अर्थ में flaky हैं (फ़ोन C पर भी बाक़ी अंग्रेज़ी runs पास हुए)। रीम के लिए: सभी 14 false-positive results हैं — failure टेस्ट और उसके setup से आता है, SAVE20 के किसी defect से नहीं। सबूत उलटी दिशा में इशारा करते हैं: 26 पास हुए अंग्रेज़ी runs ने SAR 80.00 पढ़ा, और F9–F12 के वीडियो में discount लगा हुआ दिखता है (spinner के बाद SAR 80.00, और SAR 175.00 के cart पर SAR 140.00)। Nightly ने जो बिल्कुल नहीं जाँचा, वह अरबी UI है, क्योंकि कोई भी अरबी run "Apply" से आगे नहीं पहुँचा। तो SAVE20 अंग्रेज़ी UI में काम करता है, एक item वाले cart पर भी और F11–F12 के तीन items वाले cart पर भी; अरबी UI और PR-4 के बाक़ी हिस्से को भरोसेमंद checks चाहिए (step 4), और टेस्ट ठीक होने तक अरबी में SAVE20 की पुष्टि किसी और तरीक़े से करनी होगी, जैसे release candidate पर मैन्युअल check।

वे समस्याएँ जिनसे अभी कोई run फ़ेल नहीं हुआ। Lines 20–22: views की position से बना XPath — मोबाइल पर धीमा, क्योंकि पूरी view hierarchy serialise करनी पड़ती है, और tab bar बदलते ही टूट जाता है; Cart tab को identifier चाहिए। Line 23: दूसरा fixed sleep, जो हर run में 3 सेकंड बर्बाद करता है और जिस रात cart धीरे लोड हो, उस रात line 24 को फ़ेल कर देगा। Line 29: Android पर accessibility id content description होता है, जिसे TalkBack ज़ोर से पढ़ता है, इसलिए TalkBack यूज़र रक़म की जगह तकनीकी नाम cart.total सुनता है; इसे ऐप के accessibility defect के रूप में रिपोर्ट करें, और टेस्ट में resource id इस्तेमाल करें। Line 30: expected value अंग्रेज़ी string SAR 80.00 है, जबकि अरबी UI "ر.س" दिखाता है (F1–F5 देखें), इसलिए locator ठीक होते ही अरबी runs यहाँ फ़ेल होंगे। Line 31: जब भी उससे पहले की कोई line exception फेंकती है — फ़ेल lookup या फ़ेल assertion — driver.quit() छूट जाता है, इसलिए session farm फ़ोन पर तब तक खुला रहता है जब तक Appium का command timeout उसे बंद न कर दे। डेटा भी कोई साफ़ नहीं करता: टेस्ट साझा account के server वाले cart से न SAVE20 हटाता है न item, इसलिए उस account से साइन-इन करने वाला अगला टेस्ट वही सब विरासत में पाता है जो यह टेस्ट छोड़ गया। और फ़ेल होने पर टेस्ट अपना कुछ नहीं रखता: न फ़ेल step का screenshot, न page source, न डिवाइस log, न CI के लिए JUnit XML — सिर्फ़ farm का वीडियो।

टेस्ट का स्थिर वर्ज़न। (1) जो चाहिए वह ख़ुद बनाता है: हर run के लिए unique test user, test environment के ज़रिए seed किया गया cart (100.00 SAR का एक item), और टेस्ट के अपने setup में साइन-इन। "appium:noReset": True हटाया जाता है, ताकि कोई session किसी दूसरे टेस्ट का ऐप डेटा न ले, और टेस्ट न test_login पर निर्भर रहे न shard plan पर। (2) "appium:autoGrantPermissions": True गाइड के उदाहरण की तरह permissions पहले से देता है (जब तक noReset true है, UiAutomator2 driver इसे अनदेखा करता है — line 10 हटाने का एक और कारण); notification prompt का अपना अलग टेस्ट होता है। (3) Developers के साथ तय resource ids, जैसे com.example.grocer:id/tab_cart, com.example.grocer:id/promo_apply और com.example.grocer:id/cart_total, जिन्हें AppiumBy.ID से ढूँढा जाता है; iOS पर इन्हीं elements को cart.total जैसे accessibilityIdentifier मिलते हैं, जिन्हें VoiceOver नहीं पढ़ता। Android ऐप से content description cart.total हटाया जाता है, ताकि TalkBack रक़म पढ़े, और "test identifiers मौजूद हैं" definition of done में जाता है। (4) कोई time.sleep नहीं: WebDriverWait शर्तों का इंतज़ार करता है — promo field दिखे, "Apply" clickable हो, total expected value दिखाए (EC.text_to_be_present_in_element, लगभग 10–15 सेकंड के timeout के साथ)। (5) "Apply" पर tap से पहले driver.hide_keyboard() से keyboard बंद किया जाता है। (6) Assertion रक़म को संख्या के रूप में मिलाता है, या run की भाषा के expected टेक्स्ट से। (7) driver.quit() गाइड की तरह finally block में जाता है; फ़ेल होने पर टेस्ट screenshot, page source और डिवाइस log सहेजता है, और CI को JUnit XML मिलता है (pytest --junitxml=results.xml)। (8) Farm फ़ोन तीनों animation scale settings 0 पर रखकर चलते हैं।

Layers। 20% की गणना बिज़नेस नियम है, इसलिए उसके cases UI के नीचे होने चाहिए: discount गणना के unit टेस्ट (subtotal का 20%, और 0.01 तक rounding — PR-4 नहीं बताता कि rounding कैसे हो, इसलिए रीम से पूछें) और promo endpoint के API टेस्ट (valid code, unknown code और खाली code, हर एक के expected response के साथ)। ये हर pull request पर सेकंडों में चलते हैं और इन्हें डिवाइस नहीं चाहिए। UI टेस्ट wiring रखता है: cart स्क्रीन पर valid code दिखाए गए total को अपडेट करता है; दूसरा UI टेस्ट यह जाँच सकता है कि unknown code अपना error message दिखाता है। दोनों भाषाएँ मैट्रिक्स में रहती हैं, क्योंकि locator और assertion की समस्याएँ अरबी runs ने ही पकड़ीं। मैन्युअल रहता है: content description ठीक होने के बाद cart स्क्रीन पर TalkBack session, और फ़ोन C पर बड़े font size के साथ यह जाँच कि keyboard खुला रहते यूज़र "Apply" तक पहुँच सकता है या नहीं।

उमर को जवाब। अपने-आप दोबारा चलाने से nightly बिना कुछ ठीक किए हरा हो जाएगा: F1–F5 हर अरबी run में फिर भी फ़ेल होंगे, और बाक़ी failures में re-run कारण छिपा देगा — और promo service के किसी असली intermittent defect को भी उतनी ही आसानी से छिपा देगा। Retry सिर्फ़ infrastructure स्तर पर करें (health check में फ़ेल farm फ़ोन, session जो शुरू न हो), failure छिपाने के लिए कभी नहीं। Fix होने तक टेस्ट को quarantine करें: वह उस नतीजे से बाहर हो जाता है जो तय करता है कि nightly हरा है या नहीं, चलता रहता है, और owner व तारीख़ के साथ track होता है। Fix के बाद उसे पूरे मैट्रिक्स पर बार-बार चलाएँ, दोनों भाषाओं और फ़ोन C समेत, और तभी वह quality gate में लौटे। उसके बाद उसकी जगह farm का nightly run और Tier 1 व Tier 2 फ़ोनों पर release candidate run है, और checkout journey का हिस्सा होने के कारण वह उस UI smoke suite में भी जा सकता है जो हर pull request पर एक Android emulator पर चलता है।

अगर आपका जवाब अलग है, तो हर बिंदु को उन दो सवालों से जाँचें जिनमें गाइड की सलाह का सार है: क्या टेस्ट वह सब ख़ुद बनाता है जिस पर वह निर्भर है (account, cart, permissions, डिवाइस settings)? और क्या वह समय के बजाय किसी शर्त का इंतज़ार करता है? अलग fix ठीक है अगर वह वही कारण हटाता है — जैसे UI टेस्ट में promo response लौटाने वाला mock server, जबकि असली endpoint को API टेस्ट कवर करते हैं।

इस topic में आपकी प्रगति

QA रोडमैप का हिस्सा

इस गाइड में बताए गए टूल्स

ऐसा सार्वजनिक endpoint पाएँ जो कोई भी HTTP स्टेटस कोड लौटाए, वैकल्पिक देरी और कस्टम JSON बॉडी के साथ, ताकि क्लाइंट की error हैंडलिंग टेस्ट हो सके।

API टेस्टिंग

टेस्ट अकाउंट के लिए फ़ेक यूज़र रिकॉर्ड (नाम, username, ईमेल, पासवर्ड, avatar seed, role) जनरेट करें।

टेस्ट डेटा

सिंथेटिक टेस्ट डेटा की एक ही जगह पर फ़ैक्टरी: users, customers, companies, पते, संख्याएँ, तारीख़ें और स्ट्रिंग — JSON, CSV, SQL या XML में।

टेस्ट डेटा

API रिस्पॉन्स को JSON Schema या OpenAPI रिस्पॉन्स स्कीमा के आधार पर जाँचें।

API टेस्टिंग

Mutqan Soft कैसे मदद कर सकता है

और गाइड

और गाइड
ऑटोमेशन

UI टेस्ट ऑटोमेशन

UI टेस्ट ऑटोमेशन व्यवहार में: फ़्रेमवर्क की परतें, Selenium, Playwright और Cypress, locators, waits, assertions, page objects, टेस्ट डेटा और CI।

16 मिनट पढ़ने का समय
ऑटोमेशन

Flaky टेस्ट

ऑटोमेटेड UI टेस्ट flaky क्यों होते हैं — timing, shared state, डेटा, environment, third parties — उनकी जाँच कैसे करें, और सही retry व quarantine नीति।

12 मिनट पढ़ने का समय
ऑटोमेशन

UI टेस्ट के लिए Locator रणनीतियाँ

UI टेस्ट के locators कैसे चुनें: पहले role और label, फिर test ids, CSS और XPath; dynamic ids, iframes, shadow DOM, anti-patterns और checklist।

12 मिनट पढ़ने का समय
ऑटोमेशन

CI/CD पाइपलाइन में टेस्टिंग

CI/CD पाइपलाइन में टेस्टिंग कैसे होती है: टेस्ट स्टेज, तेज़ फ़ीडबैक का क्रम, क्वालिटी गेट, JUnit रिपोर्ट, शार्डिंग, flaky टेस्ट और फ़ेलियर ट्राइएज।

16 मिनट पढ़ने का समय
टेस्ट डिज़ाइन

मैनुअल बनाम ऑटोमेटेड टेस्टिंग

मैनुअल और ऑटोमेटेड टेस्टिंग की लागत, गति, हर एक क्या पकड़ता और छोड़ता है, और रखरखाव पर तुलना — साथ में यह तय करने का व्यावहारिक नियम कि क्या ऑटोमेट करें।

7 मिनट पढ़ने का समय
टेस्ट डिज़ाइन

मोबाइल टेस्टिंग: एक व्यावहारिक गाइड

मोबाइल ऐप कैसे टेस्ट करें: ऐप के प्रकार, डिवाइस fragmentation, डिवाइस मैट्रिक्स, इंटरप्शन, नेटवर्क, permissions, सुरक्षा, एक्सेसिबिलिटी और ऑटोमेशन।

17 मिनट पढ़ने का समय