<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jay Saadana</title>
    <description>The latest articles on DEV Community by Jay Saadana (@jaysaadana).</description>
    <link>https://dev.to/jaysaadana</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2093572%2Fa52d91c1-919e-4ee2-95fa-cf548f56b949.jpeg</url>
      <title>DEV Community: Jay Saadana</title>
      <link>https://dev.to/jaysaadana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jaysaadana"/>
    <language>en</language>
    <item>
      <title>What Makes Healthcare App Testing Different from Every Other App Category</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Wed, 15 Jul 2026 08:19:36 +0000</pubDate>
      <link>https://dev.to/drizzdev/what-makes-healthcare-app-testing-different-from-every-other-app-category-4ibn</link>
      <guid>https://dev.to/drizzdev/what-makes-healthcare-app-testing-different-from-every-other-app-category-4ibn</guid>
      <description>&lt;p&gt;A patient opens their prescription and sees 500mg instead of 50mg. A lab report displays "Normal" when the value is critically high. A teleconsult disconnects the misdiagnosis, and the prescription is never generated. The doctor's registration number is missing from the prescription, making it legally invalid at the pharmacy.&lt;/p&gt;

&lt;p&gt;In most app categories, bugs cost time or money. In healthcare, bugs cost patient safety, clinical accuracy, and legal compliance. A food delivery app with a broken checkout means someone waits an extra 15 minutes for dinner. A health app with a broken prescription means a patient takes the wrong medication.&lt;/p&gt;

&lt;p&gt;The stakes are different. The complexity is different. And the testing approach needs to be different.&lt;/p&gt;

&lt;p&gt;Healthcare apps sit at the intersection of real-time clinical workflows, strict regulatory compliance, extreme data sensitivity, and emotional user experiences that no other app category shares. A banking app handles sensitive financial data but doesn't need to display it with clinical context. A video calling app handles real-time connections but doesn't generate legally binding prescriptions afterward. A marketplace app coordinates multiple stakeholders, but none of them are making medical decisions.&lt;/p&gt;

&lt;p&gt;Consumer health apps, telemedicine platforms, pharmacy ordering, lab test booking, and health records management combine all of these challenges in a single product. And most QA teams approach them with the same tools and strategies they use for e-commerce or social media apps.&lt;/p&gt;

&lt;p&gt;This guide covers the 8 dimensions that make healthcare app testing fundamentally different, what each one means for QA strategy, and why understanding these dimensions is the prerequisite for testing health apps effectively.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Healthcare app testing differs from other categories across 8 structural dimensions: regulatory compliance, data sensitivity, real-time clinical workflows, insurance complexity, multi-stakeholder coordination, offline requirements, accessibility mandates, and emotional sensitivity.&lt;/li&gt;
&lt;li&gt;Regulatory compliance isn't a checkbox it's embedded in every screen. A prescription display missing the doctor's registration number isn't a UI bug, it's a legal violation.&lt;/li&gt;
&lt;li&gt;Patient data sensitivity means that a single test data leak during QA has legal consequences that don't exist in e-commerce or social media testing.&lt;/li&gt;
&lt;li&gt;The teleconsult-to-prescription-to-pharmacy pipeline is a real-time clinical workflow where a failure at any point can delay patient care.&lt;/li&gt;
&lt;li&gt;Health apps must work offline in hospital basements, rural clinics, and areas with poor connectivity not as a convenience feature but as a patient safety requirement.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI &lt;/a&gt;testing (Drizz) is relevant for healthcare because health app UIs are information-dense, change frequently with A/B tests, and require visual validation of how clinical data is presented not just that it's present.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 1: Regulatory Compliance on Every Screen
&lt;/h2&gt;

&lt;p&gt;In most app categories, compliance is a backend concern: data storage, privacy policy, terms of service. In healthcare, compliance is visible on every screen the user sees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prescriptions :&lt;/strong&gt; Must display doctor's full name, registration number, qualification, clinic address, patient name, date, medicine name (generic and brand), dosage, frequency, duration, and special instructions. A prescription screen missing any of these fields isn't a design choice; it violates the Telemedicine Practice Guidelines (in India) or equivalent regulations in other markets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lab reports:&lt;/strong&gt; Must show patient name, test name, result value, unit of measurement, normal range, lab name, lab accreditation number, and date of collection. Displaying a blood glucose value without the normal range context is clinically dangerous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consent screens:&lt;/strong&gt; Must capture explicit, informed consent before teleconsultations, data sharing, and prescription generation. The consent must be stored, timestamped, and retrievable. A consent flow that looks like it works but doesn't actually record the consent is a compliance failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt; Every screen that displays clinical information needs validation against regulatory requirements not just "does it render" but "does it render everything it's legally required to show." This is information-dense visual validation that goes beyond element existence checks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dimension 2: Patient Data Sensitivity
&lt;/h2&gt;

&lt;p&gt;Every app category handles some sensitive data. Healthcare handles the most sensitive data a person has.&lt;/p&gt;

&lt;p&gt;A leaked credit card number can be cancelled and reissued. A leaked HIV test result, mental health diagnosis, or pregnancy report cannot be un-leaked. The consequences are legal (HIPAA in the US, DPDP Act in India, GDPR in Europe), reputational (patient trust destroyed permanently), and personal (discrimination, insurance denial, relationship damage).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test environments must use synthetic patient data, never production data. Even "anonymized" health data can be re-identified from combinations of age, location, and diagnosis.&lt;/li&gt;
&lt;li&gt;Screenshots captured during test runs must not contain real patient information. Automated tests that capture screenshots for failure debugging need synthetic data pipelines.&lt;/li&gt;
&lt;li&gt;Test accounts must be clearly separated from production accounts with no crossover path.&lt;/li&gt;
&lt;li&gt;Data deletion tests must verify that deleted records are actually purged not soft-deleted, not archived, not sitting in a backup accessible to engineers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a dimension that e-commerce and social media testing teams rarely consider because the cost of a test data leak in those categories is embarrassment, not a lawsuit.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dimension 3: Real-Time Clinical Workflows
&lt;/h2&gt;

&lt;p&gt;A food delivery order follows a linear flow: order → restaurant prepares → driver picks up → delivery. Each step happens sequentially.&lt;/p&gt;

&lt;p&gt;A teleconsultation is a real-time, multi-step clinical workflow where multiple things happen simultaneously and depend on each other:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Patient joins video call&lt;/li&gt;
&lt;li&gt;Doctor joins video call&lt;/li&gt;
&lt;li&gt;Video and audio stream bidirectionally in real-time&lt;/li&gt;
&lt;li&gt;Doctor takes notes during the consultation (in their app)&lt;/li&gt;
&lt;li&gt;Doctor generates a prescription during or immediately after the call&lt;/li&gt;
&lt;li&gt;Prescription appears on the patient's app&lt;/li&gt;
&lt;li&gt;Patient taps "Order Medicines" which pre-fills the prescription into a pharmacy order&lt;/li&gt;
&lt;li&gt;Pharmacy confirms availability and prepares the order&lt;/li&gt;
&lt;li&gt;Delivery partner picks up medicines&lt;/li&gt;
&lt;li&gt;Patient receives medicines&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Steps 1-6 happen within a single 15-minute session. A failure at step 5 (prescription doesn't generate) blocks steps 7-10 entirely. A failure at step 2 (doctor can't connect) wastes the patient's appointment slot and may delay care by hours or days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt; End-to-end testing in healthcare isn't just "login to checkout." It's "consultation to prescription to pharmacy to delivery" a pipeline where each step depends on the previous step's output and involves a different stakeholder with a different app.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dimension 4: Insurance Integration Complexity
&lt;/h2&gt;

&lt;p&gt;Payment in health apps isn't "tap UPI, pay 499." It's a multi-step verification process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;**Eligibility check: **Is this patient covered for this consultation type under their plan?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-authorization:&lt;/strong&gt; Does this consultation require prior approval from the insurer?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Co-pay calculation:&lt;/strong&gt; Patient pays 20%, insurance pays 80% but the split depends on the plan, the provider, the consultation type, and whether the doctor is in-network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cashless vs reimbursement:&lt;/strong&gt; Is this a cashless transaction (insurer pays directly) or does the patient pay and claim later?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claim submission:&lt;/strong&gt; After the consultation, the claim is submitted with consultation notes, prescription, and invoice.&lt;/li&gt;
&lt;li&gt;Claim tracking: Patients can track claim status (submitted, under review, approved, rejected, settled).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each insurance provider has different plans, different co-pay structures, different pre-auth requirements, and different claim formats. A health app integrating with 20+ insurance providers faces a combinatorial testing challenge that makes payment method diversity in delivery apps look simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt; Insurance flow testing requires validating eligibility, co-pay calculation, and claim submission across multiple plan configurations, not just testing "payment works." A co-pay calculated as 200 instead of 2,000 is a financial error that directly impacts the patient and the provider.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dimension 5: Multi-Stakeholder Flows
&lt;/h2&gt;

&lt;p&gt;A delivery app has three stakeholders: customer, restaurant, delivery partner. A health app has five or more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Patient&lt;/strong&gt; books appointments, joins consultations, views prescriptions, orders medicines, accesses records&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Doctor&lt;/strong&gt; manages availability, conducts consultations, writes prescriptions, reviews reports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pharmacy&lt;/strong&gt; receives prescription orders, confirms availability, dispenses medicines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab&lt;/strong&gt; receives test bookings, uploads results, notifies patients&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insurance&lt;/strong&gt; verifies eligibility, processes claims, communicates approvals/rejections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single patient journey (book appointment → consult → get prescription → order medicine → take lab test → view results → claim insurance) touches all five stakeholders. A bug in the doctor's prescription app that generates an incomplete prescription breaks the pharmacy ordering flow in the patient's app: two different apps, two different users, one connected failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt; Isolated app testing misses cross-stakeholder failures. Testing "prescription displays correctly on patient app" requires also testing "prescription was generated correctly on doctor app" which requires coordinating test scenarios across multiple applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dimension 6: Offline Requirements in Healthcare Settings
&lt;/h2&gt;

&lt;p&gt;A delivery app user ordering from their couch has stable WiFi. A healthcare app user may be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a hospital basement with zero cellular signal, trying to show their prescription to the pharmacy&lt;/li&gt;
&lt;li&gt;In a rural clinic in a tier-3 town with intermittent 2G connectivity, trying to join a teleconsult&lt;/li&gt;
&lt;li&gt;In a metro elevator between floors, trying to check their appointment time&lt;/li&gt;
&lt;li&gt;At a diagnostic lab with spotty WiFi, trying to pull up their doctor's referral&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Offline functionality in health apps isn't a convenience feature, it's a patient safety requirement. A patient who can't access their prescription at the pharmacy because the app needs the internet to load cached data is a patient who doesn't get their medication on time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prescriptions must be viewable offline once downloaded&lt;/li&gt;
&lt;li&gt;Appointment details (time, location, doctor name) must be cached locally&lt;/li&gt;
&lt;li&gt;Lab reports must be accessible without network&lt;/li&gt;
&lt;li&gt;Queue/token numbers for in-person visits must persist offline&lt;/li&gt;
&lt;li&gt;The app must gracefully indicate what's available offline vs what requires connectivity&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Dimension 7: Accessibility Mandates
&lt;/h2&gt;

&lt;p&gt;Health apps serve a broader range of users than most consumer apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Elderly patients&lt;/strong&gt; (60+) who may have reduced vision, slower motor response, and less familiarity with app interfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visually impaired users&lt;/strong&gt; who rely on screen readers (TalkBack, VoiceOver) to navigate appointment booking, read prescriptions, and understand lab results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Users with motor difficulties&lt;/strong&gt; who need larger tap targets, simplified navigation, and voice input options&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Users in distress&lt;/strong&gt; who are anxious, in pain, or emotionally overwhelmed and need the interface to be calming, clear, and forgiving of errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accessibility in health apps isn't a "nice-to-have" or a WCAG compliance checkbox. A prescription that a screen reader can't parse, an appointment booking button too small for arthritic fingers, or a lab result display that requires pinch-to-zoom to read the normal range  these are access barriers to healthcare itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt; Accessibility testing in health apps must go beyond automated WCAG scanners. It requires validating the real experience: can a screen reader user complete a teleconsult booking? Can an elderly user with large font settings see the full prescription without text truncation? Does the app work with system-level accessibility features (magnification, color inversion, switch access)?&lt;/p&gt;




&lt;h2&gt;
  
  
  Dimension 8: Emotional Sensitivity of Health Data
&lt;/h2&gt;

&lt;p&gt;No other app category displays information that can cause the user to cry, panic, or feel relief within seconds of viewing a screen.&lt;/p&gt;

&lt;p&gt;A lab report showing "Abnormal" next to a blood test result without explaining what "abnormal" means in context, how far outside the range the value is, and what the next step should be causes immediate anxiety. A test result showing "Negative" for a cancer screening causes immediate relief. These emotional responses happen in the first 2 seconds of viewing the screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How health data must be presented:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abnormal values need context&lt;/strong&gt;: "Your blood sugar is 180 mg/dL. The normal range is 70-100 mg/dL. This is elevated. Consult your doctor for next steps."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Critical values need immediate action prompts&lt;/strong&gt;: "Your result requires urgent attention. Call your doctor now." with a tap-to-call button.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normal results need reassurance&lt;/strong&gt;: "All values are within normal range."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trend data needs directional context&lt;/strong&gt;: "Your blood sugar has decreased from 220 to 180 over 3 months" (improving) vs "increased from 100 to 180" (worsening).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What this means for testing:&lt;/strong&gt; Testing health data display isn't just "verify the number renders." It's verifying that the number is presented with sufficient clinical context to be understood correctly by a non-medical user. A screen that shows "180 mg/dL" without the normal range, without context, without a next step that's a test failure even if the data is technically correct.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Means for Healthcare QA Strategy
&lt;/h2&gt;

&lt;p&gt;These 8 dimensions don't just add complexity  they change the kind of testing required:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual validation matters more:&lt;/strong&gt; Health app screens are information-dense: prescriptions with 10+ required fields, lab reports with values, ranges, and context, insurance summaries with co-pay calculations. Verifying that all information is present, correctly formatted, and visually accessible requires seeing the screen the way the patient sees it  not just checking element existence in an element tree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-app testing is mandatory:&lt;/strong&gt; A prescription generated on the doctor's app must render correctly on the patient's app and be parseable by the pharmacy's system. Testing each app in isolation misses the integration failures that affect patient care.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test data management is critical:&lt;/strong&gt; Synthetic patient data pipelines, secure test environments, and screenshot sanitization aren't optional overhead  they're legal requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regulatory validation is per-screen, not per-release:&lt;/strong&gt; Every screen displaying clinical information must be validated against regulatory requirements on every build, not just during initial compliance review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Emotional and accessibility testing requires human judgment supplemented by automation:&lt;/strong&gt; Automated tools can verify that elements exist and data renders. They can't evaluate whether the presentation of an abnormal lab result is reassuring or panic-inducing. A combination of automated visual testing and human review is the appropriate strategy.&lt;/p&gt;

&lt;p&gt;&lt;a href="//drizz.dev"&gt;Vision AI testing&lt;/a&gt; is particularly relevant for healthcare because it validates the visual presentation of clinical information the same way a patient reads it. A prescription with a missing registration number, a lab report with truncated normal ranges, an insurance co-pay displayed in the wrong position these are visual validation tasks that require seeing the rendered screen, not just querying the element tree.&lt;/p&gt;

&lt;p&gt;&lt;a href="//drizz.dev"&gt;Learn more about Drizz&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What makes healthcare app testing harder than fintech testing?
&lt;/h3&gt;

&lt;p&gt;Both handle sensitive data and regulatory compliance. Healthcare adds clinical workflows (teleconsult → prescription → pharmacy), multi-stakeholder coordination (patient + doctor + pharmacy + lab + insurance), emotional sensitivity of health data, and offline requirements in healthcare settings. Fintech testing is complex but operates within a more predictable flow (transaction → confirmation → receipt).&lt;/p&gt;

&lt;h3&gt;
  
  
  Do healthcare apps need different testing tools than other apps?
&lt;/h3&gt;

&lt;p&gt;Not necessarily different tools, but different testing strategies. The same automation frameworks (Appium, Vision AI) work, but the test scenarios must account for regulatory compliance validation per screen, multi-stakeholder flow coordination, synthetic patient data management, and emotional/accessibility evaluation. The tooling is similar; the test design is fundamentally different.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the most critical flow to test in a healthcare app?
&lt;/h3&gt;

&lt;p&gt;The teleconsult-to-prescription pipeline. A failed video call that doesn't generate a prescription blocks the entire downstream care pathway (medicine ordering, follow-up scheduling). This flow crosses real-time video infrastructure, clinical documentation, and pharmacy integration making it the highest-risk, highest-complexity flow in any health app.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you handle test data in healthcare app testing?
&lt;/h3&gt;

&lt;p&gt;Use synthetic patient data generated to match production data patterns (realistic names, ages, conditions, lab values) without containing any real patient information. Never copy production data to test environments, even "anonymized." Implement screenshot sanitization if test runs capture screen images. Use dedicated test accounts that cannot access production patient records.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Vision AI relevant for healthcare app testing?
&lt;/h3&gt;

&lt;p&gt;Yes. Health app screens are information-dense (prescriptions, lab reports, insurance summaries) and require visual validation of how data is presented not just that it's present. Vision AI validates that a prescription shows all required fields, a lab report displays values with normal ranges, and insurance co-pay is correctly positioned. These are visual checks that selector-based tools can verify structurally but not contextually.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Testing In-App Chat and Customer Support Flows in Delivery Apps</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Wed, 08 Jul 2026 11:24:04 +0000</pubDate>
      <link>https://dev.to/drizzdev/testing-in-app-chat-and-customer-support-flows-in-delivery-apps-5403</link>
      <guid>https://dev.to/drizzdev/testing-in-app-chat-and-customer-support-flows-in-delivery-apps-5403</guid>
      <description>&lt;p&gt;The help button is the most important button in your delivery app that your QA team almost never clicks during regression.&lt;/p&gt;

&lt;p&gt;Every delivery app has an in-app support layer: chatbot flows, live agent chat, order-specific help menus, photo uploads for issue reporting, refund request forms, and escalation paths. This system sits behind one tap the "Help" or "?" icon on the order screen and it determines whether a failed delivery becomes a retained customer or a one-star review followed by an uninstall.&lt;/p&gt;

&lt;p&gt;Yet in most delivery app QA teams, support flows get tested once during initial development and never again. The chatbot conversation trees change weekly as the support team optimizes deflection rates. The live agent handoff logic gets updated monthly. The refund calculation rules change with every policy revision. And none of these changes trigger a regression run because the help button isn't in anyone's critical path test suite.&lt;/p&gt;

&lt;p&gt;This guide covers what specifically needs testing in in-app support, why it breaks more often than teams realize, why traditional automation struggles with chat interfaces, and how to build support flow testing that actually runs on every build.&lt;/p&gt;

&lt;p&gt;For the complete delivery app testing checklist, see &lt;a href="https://www.drizz.dev/post/how-to-test-a-food-delivery-app-30-test-cases-from-order-to-doorstep" rel="noopener noreferrer"&gt;30 Test Cases from Order to Doorstep.&lt;/a&gt; For checkout-specific testing, see &lt;a href="https://dev.to/drizzdev/why-checkout-flows-break-more-than-anything-else-in-delivery-apps-4637/comments"&gt;Why Checkout Flows Break More Than Anything Else.&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In-app customer support is the most under-tested feature in delivery apps despite being the primary determinant of customer retention after a negative experience.&lt;/li&gt;
&lt;li&gt;Chatbot conversation trees change weekly as support teams optimize for deflection, resolution rate, and CSAT breaking any selector-based test written against the previous tree structure.&lt;/li&gt;
&lt;li&gt;Support flows cross multiple systems simultaneously: chatbot engine, live agent platform, order management, payment/refund system, and push notifications each one a potential failure point.&lt;/li&gt;
&lt;li&gt;The hardest edge case is a user opening support chat while their order is still live the chat must show real-time order status alongside the conversation without either interfering.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI&lt;/a&gt; (Drizz) is suited for chat testing because chat UIs are heavily customized, messages render dynamically, and chatbot flows change weekly all things that break selectors but are visually testable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Is In-App Support the Most Under-Tested Feature?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  It's Behind the Happy Path
&lt;/h3&gt;

&lt;p&gt;QA regression suites are built around the happy path: search, browse, cart, checkout, payment, tracking, delivery. Support flows are unhappy paths they only trigger when something goes wrong. Most automated test suites don't simulate failure scenarios that push users to the help button.&lt;/p&gt;

&lt;h3&gt;
  
  
  It Changes Without Engineering Releases
&lt;/h3&gt;

&lt;p&gt;Chatbot trees are typically managed by the support operations team through a chatbot platform (Intercom, Freshdesk, Zendesk, custom), not through the app's codebase. When the support team adds a new conversation branch or changes the refund flow, no app release is triggered meaning no regression suite runs. The chatbot UI changes silently.&lt;/p&gt;

&lt;h3&gt;
  
  
  It Crosses Multiple Systems
&lt;/h3&gt;

&lt;p&gt;A single support interaction touches the chatbot engine (conversation logic), the live agent platform (handoff and routing), the order management system (fetching order details), the payment system (processing refunds), the notification system (sending resolution updates), and the app's UI layer (rendering all of this). A failure in any one system breaks the support experience, but each system is owned by a different team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nobody Owns Support QA
&lt;/h3&gt;

&lt;p&gt;The support operations team owns the chatbot content. The engineering team owns the app UI. The payments team owns refund logic. The platform team owns the live agent infrastructure. Support flow testing falls between all of them and often falls through the cracks entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Specifically Needs Testing in In-App Support?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Chatbot Conversation Trees
&lt;/h3&gt;

&lt;p&gt;A typical chatbot has 3 levels: issue category ("Order issue") → specific problem ("Missing item") → resolution ("Request refund"). Each path is a test case, and the tree changes weekly as the support team optimizes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Every L1 → L2 → L3 path navigates correctly, "Back" returns without losing context, correct resolution triggers at each endpoint, and new branches render properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Live Agent Handoff
&lt;/h3&gt;

&lt;p&gt;When the chatbot can't resolve, the user hits a live agent queue. This transition is where most support flows fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Queue position displays and updates in real-time, agent assignment shows a visual change, agent's first message appears in the same thread (not a new screen), no-agent fallback works (email form or callback), and mid-chat agent disconnection recovers gracefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Order Context Pre-Loading
&lt;/h3&gt;

&lt;p&gt;Tapping "Help" on a specific order should pre-load that order's context ID, items, status, payment method. The agent shouldn't ask "What's your order number?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Chat opens with correct order context visible, references the right order (not a recent different one), and opening from the general help menu prompts order selection.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Photo Upload in Chat
&lt;/h3&gt;

&lt;p&gt;Users report issues with photos: wrong item, damaged packaging, spilled food.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Camera and gallery both launch from chat, photo uploads with thumbnail in thread, works on 3G with progress indicator, failure shows retry (not silent drop), and multiple photos upload in sequence.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Refund Request and Processing
&lt;/h3&gt;

&lt;p&gt;The most sensitive flow. Refund amount must be correct, routed to the right payment method, and confirmed with a timeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Partial refund matches correct items, refund routes to original method (UPI to UPI, card to card), timeline displays ("5-7 business days"), status is trackable after chat ends, and double-submit doesn't process twice.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. CSAT Rating After Resolution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Rating prompt appears after chat closes (not during), star/emoji scale is tappable, optional text feedback works, submit shows confirmation, skip closes without error.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Live Order + Chat Edge Case
&lt;/h3&gt;

&lt;p&gt;The hardest scenario: user opens chat while their order is still in transit. Chat must show real-time order status alongside the conversation without either interfering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test:&lt;/strong&gt; Order status bar updates in real-time while chatting, sending a message doesn't interrupt tracking, delivery notification appears even while in chat, and chat history persists if user navigates to tracking and back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Traditional Automation Fails at Chat Testing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Chat UIs Are Heavily Customized
&lt;/h3&gt;

&lt;p&gt;Delivery apps use custom chat SDKs or third-party platforms (Intercom, Freshdesk, custom WebView) that render messages with proprietary component structures. The element IDs inside these chat UIs don't follow standard conventions, change with SDK updates, and vary between chatbot messages, agent messages, and system messages. Appium tests written against Intercom SDK v3 break when v4 ships with different element structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Messages Render Dynamically
&lt;/h3&gt;

&lt;p&gt;Chat messages appear in real-time as they're received. The message list is a dynamic, growing view where new elements are appended at the bottom. Tests that assert "the third message says X" break when a system message is inserted above it, pushing everything down. Element position is unreliable in a chat thread.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chatbot Flows Change Without App Releases
&lt;/h3&gt;

&lt;p&gt;When the support team changes a chatbot branch on Tuesday, no app build is triggered. The CI pipeline doesn't run. The existing tests don't execute against the new chatbot tree. By Friday, the chatbot has a new path that's completely untested and users who follow it hit a dead end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Timing Dependencies
&lt;/h3&gt;

&lt;p&gt;Live agent handoff, queue position updates, and message delivery all have timing dependencies. A test that asserts "agent connected" 5 seconds after requesting handoff fails when the agent takes 15 seconds. A test that checks queue position may see "3" or "2" depending on when it reads the element.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does Vision AI Test Support Flows?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="//drizz.dev"&gt;Drizz&lt;/a&gt; validates support flows by reading the chat screen visually, the same way a customer reads messages, taps buttons, and observes status changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chatbot navigation:&lt;/strong&gt; "Tap 'Order issue,' verify next options appear, tap 'Missing item,' verify refund options appear." Drizz reads the button text visually and taps it regardless of which chatbot SDK rendered it or what element IDs the buttons have. When the support team renames "Missing item" to "Item not received" next week, update one line in the test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Message verification:&lt;/strong&gt; "Verify agent message appears in chat thread with timestamp." Drizz sees the message rendered on screen, reads the text, and confirms it appeared without needing to locate it by element index in a dynamic list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Photo upload:&lt;/strong&gt; "Tap camera icon, verify camera launches, take photo, verify thumbnail appears in chat." Drizz sees the camera icon visually, observes the camera viewfinder, and confirms the uploaded thumbnail renders in the chat thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Order context:&lt;/strong&gt; "Open help on Order #12345, verify chat shows order ID and item list." Drizz reads the order information displayed in the chat header or context card visually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live order + chat:&lt;/strong&gt; "While in chat, verify order status bar shows 'On the Way' and updates to 'Delivered.'" Drizz observes both the chat messages and the status indicator on the same screen simultaneously a visual test that captures the full user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSAT rating:&lt;/strong&gt; "After chat closes, verify rating prompt appears, tap 4 stars, verify confirmation." Visual interaction that works regardless of how the rating component is implemented.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In-app support is the feature that saves customers you've already lost. A delivery that went wrong missing item, late arrival, wrong order is recoverable if the support experience is fast, contextual, and leads to resolution. It's unrecoverable if the chatbot hits a dead end, the agent handoff fails, the refund doesn't process, or the photo upload silently drops.&lt;/p&gt;

&lt;p&gt;QA teams that add support flows to their regression suite catch the chatbot changes that break paths weekly, the SDK updates that break rendering monthly, and the refund logic changes that break calculations quarterly. The teams that don't test support flows learn about the breakage from customer churn data weeks after the damage is done.&lt;/p&gt;

&lt;p&gt;For delivery apps where the help button is tapped thousands of times daily, support flow testing isn't a nice-to-have. It's the difference between a retained customer and a lost one.&lt;/p&gt;

&lt;p&gt;&lt;a href="//drizz.dev"&gt;Get started with Drizz&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why don't most QA teams test in-app support flows?
&lt;/h3&gt;

&lt;p&gt;Support flows sit behind the "Help" button on the unhappy path they only trigger after a failed experience. Most regression suites are built around the happy path (browse, order, pay, receive). Additionally, chatbot content is managed by the support team, not engineering, so chatbot changes don't trigger app releases or regression runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you test chatbot trees that change weekly?
&lt;/h3&gt;

&lt;p&gt;Test structurally: "tap first option in Level 1, verify Level 2 options appear, tap first option in Level 2, verify resolution screen appears." This validates the navigation structure regardless of what the specific options are named. For content validation, maintain a lightweight chatbot tree map that's updated when the support team makes changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Vision AI test live agent chat?
&lt;/h3&gt;

&lt;p&gt;Vision AI can test the handoff flow (request agent, verify queue position, verify agent connected, verify first message appears) and the visual chat experience (messages render, timestamps display, photos upload). It cannot test the agent-side experience or agent routing logic those require agent platform testing tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the most common support flow bug?
&lt;/h3&gt;

&lt;p&gt;Dead-end chatbot paths: the user taps through 3 levels of options and reaches a screen with no resolution action no refund button, no agent handoff, no ticket creation. Just a dead end with a "Was this helpful?" prompt. This happens when the support team adds a new category without connecting it to a resolution path.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many support flow test cases does a delivery app need?
&lt;/h3&gt;

&lt;p&gt;A production delivery app typically needs 15-25 support-specific test cases: 5-8 chatbot tree paths (one per major issue category), 3-4 agent handoff scenarios (available, unavailable, disconnection), 2-3 photo upload scenarios, 2-3 refund processing paths, 1-2 CSAT rating flows, and 1-2 edge cases (live order + chat, multi-order context).&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>How to Test On-Demand Logistics Apps: From Booking to Doorstep Deliver</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Thu, 02 Jul 2026 09:34:52 +0000</pubDate>
      <link>https://dev.to/drizzdev/how-to-test-on-demand-logistics-apps-from-booking-to-doorstep-deliver-3le1</link>
      <guid>https://dev.to/drizzdev/how-to-test-on-demand-logistics-apps-from-booking-to-doorstep-deliver-3le1</guid>
      <description>&lt;p&gt;Testing a food delivery app is hard. Testing an on-demand logistics app is harder.&lt;/p&gt;

&lt;p&gt;Food delivery has a fixed pattern: one restaurant, one customer, one delivery partner, 30 minutes. Logistics apps break every one of those constraints. Multiple pickup stops. Multiple drop locations. Vehicle selection based on package size bike, auto-rickshaw, mini-truck, or 3-wheeler. Weight and dimension-based pricing that recalculates mid-booking. Driver allocation across vehicle categories. Package photo verification at pickup and delivery. OTP-based handoffs. And live tracking across routes that can stretch 3 hours across a city instead of 30 minutes across a neighbourhood.&lt;/p&gt;

&lt;p&gt;India's on-demand logistics market is growing at 25%+ annually. Platforms are processing hundreds of thousands of parcels daily across 50+ cities from a document courier within downtown Manhattan to a 50kg furniture shipment from Los Angeles to San Francisco. In India, the same scale plays out across cities like Bangalore, Delhi, and Mumbai. The QA challenge scales with the complexity.&lt;/p&gt;

&lt;p&gt;This guide provides 28 ready-to-use test cases covering every critical flow in an on-demand logistics app, from booking to delivery confirmation. Each test is written in both Appium and Drizz format so you can see the difference in approach and maintenance cost.&lt;/p&gt;

&lt;p&gt;For food delivery testing, see our &lt;a href="https://www.drizz.dev/post/why-delivery-apps-are-the-hardest-to-test-and-what-its-costing-qa-teams" rel="noopener noreferrer"&gt;30 Test Cases from Order to Doorstep&lt;/a&gt;. For the broader delivery app challenge, see &lt;a href="https://dev.to/drizzdev/why-delivery-apps-are-the-hardest-to-test-and-what-its-costing-qa-teams-27fi"&gt;Why Delivery Apps Are the Hardest to Test.&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;On-demand logistics apps are harder to test than food delivery because of multi-stop routes, vehicle type selection, weight-based pricing, package verification (photo + OTP), and tracking across city-scale distances.&lt;/li&gt;
&lt;li&gt;28 test cases cover the complete logistics flow: booking (8), driver matching (4), pickup verification (4), live tracking (4), delivery confirmation (4), payment (4), and cancellation/refund (4).&lt;/li&gt;
&lt;li&gt;Selector-based tools (Appium) struggle with logistics apps because of dynamic fare estimates, map-heavy flows, photo verification screens, and OTP dialogs that cross app boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI&lt;/a&gt; (Drizz) validates the visual experience fare estimates displayed, map pin moving, photo upload confirmed, OTP screen rendered without depending on element IDs that change with every release.&lt;/li&gt;
&lt;li&gt;Region-specific challenges vary by market: in the US, challenges include apartment complex access codes, loading dock scheduling for commercial deliveries, toll route pricing, and multi-timezone scheduling for cross-state shipments. In India, additional challenges include auto rickshaw as a vehicle category, addresses without pin codes in tier-3 cities, intercity parcel flows, and COD for logistics.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Is Logistics App Testing Different from Food Delivery Testing?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Food Delivery&lt;/th&gt;
&lt;th&gt;On-Demand Logistics&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stops&lt;/td&gt;
&lt;td&gt;1 pickup, 1 drop&lt;/td&gt;
&lt;td&gt;1–5+ stops (multi-pickup, multi-drop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vehicle Selection&lt;/td&gt;
&lt;td&gt;None (assigned automatically)&lt;/td&gt;
&lt;td&gt;User chooses: bike, auto, mini-truck, 3-wheeler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing Model&lt;/td&gt;
&lt;td&gt;Menu price + delivery fee&lt;/td&gt;
&lt;td&gt;Weight, dimensions, distance, vehicle type, and time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Route Duration&lt;/td&gt;
&lt;td&gt;15–40 minutes&lt;/td&gt;
&lt;td&gt;30 minutes to 3+ hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Package Verification&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Photo at pickup, photo at delivery, OTP handoff&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scheduling&lt;/td&gt;
&lt;td&gt;Mostly immediate&lt;/td&gt;
&lt;td&gt;Immediate + scheduled (hours or days in advance)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Item Description&lt;/td&gt;
&lt;td&gt;Restaurant handles&lt;/td&gt;
&lt;td&gt;User describes package (fragile, document, furniture, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insurance / Declared Value&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;td&gt;Declared value and optional insurance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Corporate Accounts&lt;/td&gt;
&lt;td&gt;Rare&lt;/td&gt;
&lt;td&gt;Common (businesses shipping daily)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intercity Delivery&lt;/td&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;td&gt;Available on many platforms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Section 1: Booking Flow (Test Cases 1-8)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-01: Enter pickup address
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/pickup_input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/address_search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Brooklyn Heights&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
        &lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//android.widget.TextView[contains(@text, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Brooklyn Heights&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Brooklyn Heights&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Brooklyn Heights&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;suggestions&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-02: Enter drop address
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Midtown Manhattan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Midtown Manhattan&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;suggestions&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="n"&gt;preview&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-03: Add multiple stops (multi-drop)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;setting&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Add Stop&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SoHo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SoHo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;suggestions&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;locations&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;listed&lt;/span&gt;
&lt;span class="mf"&gt;6.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;additional&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-04: Select vehicle type
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
        &lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/vehicle_list&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;vehicles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_elements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//android.widget.RecyclerView[@resource-id=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;com.app:id/vehicle_list&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]//android.widget.FrameLayout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vehicles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;vehicles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Select mini-truck
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="nf"&gt;displayed &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Bike&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Auto&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mini&lt;/span&gt; &lt;span class="n"&gt;Truck&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt; &lt;span class="n"&gt;shows&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;estimated&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Mini Truck&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;Mini&lt;/span&gt; &lt;span class="n"&gt;Truck&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;highlighted&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-05: Fare estimate calculation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Select&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;breakdown&lt;/span&gt; &lt;span class="n"&gt;shows&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="n"&gt;charge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;taxes&lt;/span&gt;
&lt;span class="mf"&gt;6.&lt;/span&gt; &lt;span class="n"&gt;Change&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;
&lt;span class="mf"&gt;7.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-06: Weight and dimension input
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Package Details&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What are you sending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;booking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Select&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="nf"&gt;category &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Small&lt;/span&gt; &lt;span class="n"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Large&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Furniture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Enter&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15 kg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="n"&gt;based&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-07: Schedule a future pickup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Schedule&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Later&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;booking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="n"&gt;picker&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Select&lt;/span&gt; &lt;span class="n"&gt;tomorrow&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s date and 10:00 AM
4. Tap &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Confirm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;
5. Verify the booking screen shows the scheduled date and time
6. Verify the fare reflects the scheduled pricing

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-08: Intercity parcel booking
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Delhi&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Jaipur&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;intercity&lt;/span&gt; &lt;span class="n"&gt;booking&lt;/span&gt; &lt;span class="n"&gt;flow&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;activated&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;intercity&lt;/span&gt; &lt;span class="nf"&gt;deliveries &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;larger&lt;/span&gt; &lt;span class="n"&gt;vehicles&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt; &lt;span class="n"&gt;reflects&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;intercity&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;
&lt;span class="mf"&gt;6.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;estimated&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;hours &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 2: Driver Matching and Acceptance (Test Cases 9-12)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-09: Booking confirmation and driver search
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;selecting&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;confirming&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Book Now&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Confirm Booking&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Searching for driver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Finding your partner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;loading&lt;/span&gt; &lt;span class="n"&gt;animation&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="n"&gt;indicator&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-10: Driver assigned with details
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;accepts&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;booking&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;shown&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;rating&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;span class="mf"&gt;6.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Call Driver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;contact&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-11: No driver available handling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;booking&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;drivers&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No drivers available&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;retry&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;search&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;vehicle&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-12: Driver cancels after accepting
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. After a driver is assigned
2. Trigger a driver cancellation via the test API
3. Verify the "Driver cancelled" message appears
4. Verify automatic driver re-search begins or a rebooking option is displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 3: Pickup Verification (Test Cases 13-16)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-13: OTP verification at pickup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# OTP dialog may be OS-level or in-app
&lt;/span&gt;
&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;
        &lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/otp_display&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/otp_display&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="n"&gt;OTP&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;OTP&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;digit&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;instruction&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Share this OTP with driver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-14: Package photo at pickup
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;OTP&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;verified&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;trigger&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Package picked up&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;confirmation&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;shown&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-15: Pickup address reached by driver
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;changes&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Arrived at pickup&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Driver is at your location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;chat&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;accessible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-16: Wrong pickup location handling
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Wrong address&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot find location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="n"&gt;receives&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="n"&gt;about&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s issue
3. Verify an option to update the address or contact the driver is available
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 4: Live Tracking (Test Cases 17-20)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-17: Map loads with route
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;pickup&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;confirmed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;navigate&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;rendering&lt;/span&gt; &lt;span class="nf"&gt;correctly &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;blank&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;pin&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;visible&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-18: Driver pin moves on map
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;note&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s pin position
2. Wait 15 seconds
3. Verify the driver pin has changed position
4. Verify the ETA has been updated
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-19: ETA updates during transit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Read&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="n"&gt;ETA&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Wait&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;ETA&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;decreased&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;ETA&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;readable&lt;/span&gt; &lt;span class="nf"&gt;format &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;arrival&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-20: Multi-stop tracking transition
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="n"&gt;booking&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tracking&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;shows&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;En route to Stop 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;Stop&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nf"&gt;completed &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;En route to Stop 2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;show&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="n"&gt;destination&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;ETA&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;recalculated&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;remaining&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 5: Delivery Confirmation (Test Cases 21-24)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-21: OTP verification at delivery
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;When&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="n"&gt;arrives&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;drop&lt;/span&gt; &lt;span class="n"&gt;location&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="n"&gt;OTP&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Share OTP with driver to complete delivery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-22: Delivery photo confirmation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="n"&gt;OTP&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;verified&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Delivered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;shown&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-23: Delivery to alternate recipient
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;option&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;alternate&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;phone&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Enter&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;alternate&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s contact details
3. Verify the delivery confirmation displays the alternate recipient information

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-24: Failed delivery attempt
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;Trigger&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="nc"&gt;API &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt; &lt;span class="n"&gt;unavailable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Delivery failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;appears&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nf"&gt;displayed &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Recipient not available&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;Reschedule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Return&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;Sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;Contact&lt;/span&gt; &lt;span class="n"&gt;Support&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 6: Payment (Test Cases 25-28)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-25: Pay with UPI after delivery
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;confirmed&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;shows&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;estimated&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;displays&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;any&lt;/span&gt; &lt;span class="n"&gt;adjustment&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Select&lt;/span&gt; &lt;span class="n"&gt;UPI&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;
&lt;span class="mf"&gt;5.&lt;/span&gt; &lt;span class="n"&gt;Complete&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt;
&lt;span class="mf"&gt;6.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="n"&gt;confirmation&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;receipt&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-26: Cash on Delivery completion
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Cash&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="nc"&gt;Delivery &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;COD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;booking&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;instruction&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pay Cash to Driver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nf"&gt;completed &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;via&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;trigger&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="n"&gt;collected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="n"&gt;shows&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Completed • Paid by Cash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-27: Corporate account billing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Log in with a corporate account
2. Complete a booking
3. Verify the payment is charged to the corporate account (not the personal account)
4. Verify the booking appears in the corporate dashboard or booking history
5. Verify the invoice or receipt displays the company name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-28: Fare adjustment and dispute
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;1.&lt;/span&gt; &lt;span class="n"&gt;After&lt;/span&gt; &lt;span class="n"&gt;delivery&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;If&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;final&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;differs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;adjustment&lt;/span&gt; &lt;span class="n"&gt;reason&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;shown&lt;/span&gt;
&lt;span class="mf"&gt;3.&lt;/span&gt; &lt;span class="n"&gt;Tap&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Help&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dispute Fare&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="mf"&gt;4.&lt;/span&gt; &lt;span class="n"&gt;Verify&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fare&lt;/span&gt; &lt;span class="n"&gt;dispute&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;support&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;displayed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Pattern: Why Vision AI Fits Logistics Apps
&lt;/h2&gt;

&lt;p&gt;Logistics apps have more visual, dynamic, and cross-boundary flows than food delivery:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vehicle selection&lt;/strong&gt; is a visual grid of options with images, names, and prices not a standard dropdown Appium can easily select from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fare estimates&lt;/strong&gt; update dynamically based on distance, weight, vehicle, and time static assertions break instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Photo verification&lt;/strong&gt; at pickup and delivery renders images inside the app that Appium can't validate (it can check if an image element exists, not if it shows the right package).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OTP screens&lt;/strong&gt; may be in-app or OS-level Vision AI sees both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-stop tracking&lt;/strong&gt; requires visual validation that the map route, status text, and ETA all update correctly at each stop transition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Addresses without pin codes&lt;/strong&gt; in tier-3 cities often use landmark-based descriptions that render as long text strings Vision AI confirms the text renders without truncation.&lt;/p&gt;

&lt;p&gt;At 28 test cases with an average of 8 selectors each, an Appium suite has 224 breakage points. A Drizz suite has zero. For logistics apps that iterate on booking UI and tracking flows weekly, the maintenance gap compounds every sprint.&lt;/p&gt;

&lt;p&gt;After 3 months of weekly releases, a selector-based suite has faced 12 rounds of potential breakages across those 224 points. The QA team that started with 28 well-maintained tests is now spending more time fixing broken selectors than writing tests for the new features shipping every sprint scheduled pickups, intercity routes, corporate billing, package insurance. Coverage stalls. The newest, highest-risk flows ship untested.&lt;/p&gt;

&lt;p&gt;A Vision AI suite faces those same 12 releases and needs zero selector updates. The team spends that same time expanding coverage to 50, then 80, then 120 tests covering every new feature as it ships. The architecture doesn't just reduce maintenance. It changes what the team is capable of building.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How is logistics app testing different from food delivery testing?
&lt;/h3&gt;

&lt;p&gt;Logistics apps add vehicle selection, weight-based pricing, multi-stop routing, package photo verification, OTP handoffs at both pickup and delivery, scheduled bookings, intercity routes, and corporate accounts. Food delivery has a simpler fixed pattern (one restaurant, one customer, 30 minutes). Logistics has variable routes, variable durations (30 min to 3+ hours), and variable package types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Appium test photo verification flows?
&lt;/h3&gt;

&lt;p&gt;Appium can verify that an image element exists in the element tree, but it cannot verify what the image shows. A pickup photo showing the wrong package, a blurry image, or a placeholder icon all pass Appium's is_displayed() check. Vision AI can confirm that an image is present, appears to be a photo (not a placeholder), and the surrounding context (timestamp, "Picked up" label) renders correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you test multi-stop routes?
&lt;/h3&gt;

&lt;p&gt;Test each stop transition independently: verify tracking shows the correct current destination, verify ETA updates when a stop is completed, verify the map route changes to the next stop, and verify the status text transitions correctly. Use a test API to trigger stop completions without waiting for real deliveries.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about testing auto-rickshaw as a vehicle option?
&lt;/h3&gt;

&lt;p&gt;Auto-rickshaw is a vehicle category specific to Indian logistics apps. Test it the same as any vehicle: verify it appears in the vehicle selection grid with an image and estimated price, verify selecting it updates the fare, and verify the booking confirms with the correct vehicle type. Vision AI sees "Auto" as a visual option regardless of what element ID the component uses.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many devices should logistics apps test on?
&lt;/h3&gt;

&lt;p&gt;Logistics apps should test on 25-40 devices with emphasis on mid-range and budget Android phones (Samsung A-series, Xiaomi Redmi, Realme) because delivery partners and many customers in tier-2/3 cities use budget devices. Include 3-4GB RAM devices, older Android versions (12-13), and smaller screen sizes where booking forms and tracking maps are most likely to have rendering issues.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>software</category>
      <category>testing</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How QA Teams at High Growth Startups Scale from 50 to 500 Tests Without Hiring 5 More Engineers</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Thu, 25 Jun 2026 19:26:57 +0000</pubDate>
      <link>https://dev.to/drizzdev/how-qa-teams-at-high-growth-startups-scale-from-50-to-500-tests-without-hiring-5-more-engineers-150f</link>
      <guid>https://dev.to/drizzdev/how-qa-teams-at-high-growth-startups-scale-from-50-to-500-tests-without-hiring-5-more-engineers-150f</guid>
      <description>&lt;p&gt;Your QA team built 50 automated tests in the first quarter. Leadership was thrilled. Coverage was growing, bugs were getting caught earlier, and the investment in automation was paying off.&lt;/p&gt;

&lt;p&gt;By the time you hit 200 tests, something shifted. The same two engineers who wrote those tests were now spending most of their week fixing them. New features shipped without test coverage because there was no capacity to write new tests. The team asked for a third QA hire. Then a fourth. By 300 tests, the conversation had changed from "automation is saving us time" to "why does QA keep asking for more headcount?"&lt;/p&gt;

&lt;p&gt;This is the scaling wall that every high-growth startup hits. The test suite grows. The maintenance cost grows faster. And the instinct to solve it by hiring more engineers creates a staffing spiral that never stabilizes because the root cause isn't headcount. It's architecture.&lt;/p&gt;

&lt;p&gt;This guide maps the journey from 50 to 500 tests with specific inflection points, what breaks at each stage, the math that determines whether you hire your way out or tool your way out, and the architectural decision that separates teams that scale from teams that plateau.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Test suite scaling follows a predictable pattern with inflection points at 50, 150, 300, and 500 tests where team dynamics, maintenance burden, and coverage velocity fundamentally change.&lt;/li&gt;
&lt;li&gt;Maintenance scales linearly with test count. Doubling your suite doubles your maintenance cost. There is no efficiency gain at scale with selector-based tools.&lt;/li&gt;
&lt;li&gt;Hiring additional QA engineers solves the capacity problem temporarily but not the structural problem. New engineers inherit the same maintenance burden within 2-3 months.&lt;/li&gt;
&lt;li&gt;The architectural decision selector-based vs visual identification determines the scaling curve. Selector-based suites plateau at 200-300 tests. Vision AI suites scale continuously.&lt;/li&gt;
&lt;li&gt;For a delivery app shipping weekly, the difference between architectures is stark: a 500-test Appium suite consumes 1.5-2.5 FTEs on maintenance. A 500-test Drizz suite consumes less than 0.2 FTEs.&lt;/li&gt;
&lt;li&gt;The decision to change architecture has the highest ROI when made between 100-200 tests before maintenance debt becomes overwhelming but after the team understands their testing patterns.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Four Inflection Points
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stage 1: 0-50 Tests "This Is Working"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it looks like:&lt;/strong&gt; A 1-2 person QA team writes their first automated tests. Login flow, basic checkout, a few critical user paths. Tests run in CI. Bugs get caught before production. Leadership sees green dashboards and approves the automation investment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintenance burden:&lt;/strong&gt; 2-4 hours per week. Manageable. One person handles it between writing new tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coverage velocity:&lt;/strong&gt; 8-12 new tests per sprint. The suite grows steadily.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team mood:&lt;/strong&gt; Optimistic. Automation feels like a superpower.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you don't notice yet:&lt;/strong&gt; Every test has 6-10 selectors. At 50 tests, that's 300-500 selectors each one a future breakage point. But nothing has broken badly yet because the UI hasn't changed much since the tests were written.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 2: 50-150 Tests "The First Cracks"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it looks like:&lt;/strong&gt; The suite is big enough to provide real coverage. Product teams are shipping features faster. The first major UI redesign happens. Suddenly, 20-30 tests fail overnight. None of them are real bugs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintenance burden:&lt;/strong&gt; 8-16 hours per week. One engineer's full Monday is now spent triaging and fixing broken tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coverage velocity:&lt;/strong&gt; Drops to 4-6 new tests per sprint. Half the previous rate, because maintenance is eating into creation time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first hire request:&lt;/strong&gt; QA lead asks for a third engineer. "We need someone focused on maintenance so the rest of the team can write new tests."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's actually happening:&lt;/strong&gt; The 750-1,500 selectors in the suite are now a liability. Every UI change creates a ripple of breakages. The team is in reactive mode fixing broken tests instead of expanding coverage. But the suite is still small enough that hiring one more person feels like it solves the problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 3: 150-300 Tests "The Maintenance Trap"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it looks like:&lt;/strong&gt; The team now has 3-4 QA engineers. Maintenance consumes 40-60% of total QA capacity. The suite theoretically covers the critical paths, but in practice, 15-20% of tests are "known flaky" and ignored. Coverage has plateaued.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintenance burden:&lt;/strong&gt; 16-30 hours per week. Nearly one full-time engineer's worth of work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coverage velocity:&lt;/strong&gt; 2-4 new tests per sprint. Effectively stalled. New features ship faster than tests can be written for them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The VP's question:&lt;/strong&gt; "We've tripled the QA team. Why is coverage flat?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's actually happening:&lt;/strong&gt; The team hit the maintenance ceiling. Every new test adds maintenance load. At current rates, adding 10 tests per sprint adds 2-3 hours of weekly maintenance permanently. The team is running to stand still.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The delivery app example:&lt;/strong&gt; India's largest food delivery platform ships UI updates multiple times per week. A 250-test Appium suite at this release cadence generates 30-50 selector breakages per sprint. Three engineers spend Monday and Tuesday fixing tests. Wednesday through Friday is split between new tests and more maintenance. Coverage of new features (scheduled ordering, group ordering, subscription) is months behind development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage 4: 300-500 Tests "Hire or Rearchitect"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it looks like:&lt;/strong&gt; The team has 4-5 QA engineers. Maintenance consumes 50-70% of total capacity. The suite is large but increasingly unreliable. Test results take 30-60 minutes to triage because many failures are false positives. Engineers have stopped trusting the suite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintenance burden:&lt;/strong&gt; 30-50+ hours per week. 1.5-2.5 full-time engineers on maintenance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coverage velocity:&lt;/strong&gt; Near zero. The team is entirely in maintenance mode with occasional new tests for critical launches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The staffing spiral:&lt;/strong&gt; Hiring a 5th or 6th QA engineer provides temporary relief (2-3 months of increased velocity) before they too are absorbed into maintenance. The cost per test continues rising. The ROI of the automation investment is now questionable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The decision point:&lt;/strong&gt; This is where the path forks. Teams either continue hiring (and accept that QA headcount will grow proportionally with test count) or rearchitect (change the testing approach to break the linear maintenance curve).&lt;/p&gt;




&lt;h2&gt;
  
  
  The Math: Hiring vs Rearchitecting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Hiring Path (Selector-Based Architecture)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftxlw2uvzjspa5k0x8hr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftxlw2uvzjspa5k0x8hr5.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At 500 tests, 1.25 FTEs are consumed by maintenance. You need 5-6 QA engineers to maintain 500 tests AND write new ones AND do exploratory testing. Annual cost: 60-72L INR.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Rearchitect Path (Vision AI)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv8qinxrdc035432qqxyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv8qinxrdc035432qqxyb.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At 500 tests with Vision AI, maintenance is 5 hours per week one person's half-day. You need 3 QA engineers total. Annual cost: 36L INR.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Delta
&lt;/h3&gt;

&lt;p&gt;At 500 tests, the difference between architectures is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2-3 fewer QA engineers needed&lt;/strong&gt; (24-36L INR annual savings in India)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;45 fewer maintenance hours per week&lt;/strong&gt; redirected to coverage expansion, exploratory testing, and strategic QA work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous coverage velocity&lt;/strong&gt; vs plateau the Vision AI team keeps adding tests while the selector-based team is stuck maintaining what they have&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The breakeven point for switching architectures (including migration effort) is typically 3-4 months. After that, the savings compound every sprint.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Hiring Doesn't Solve the Problem
&lt;/h2&gt;

&lt;p&gt;The instinct to hire more engineers when maintenance overwhelms the team is logical but wrong. Here's why:&lt;/p&gt;

&lt;h3&gt;
  
  
  New Engineers Inherit the Maintenance Burden
&lt;/h3&gt;

&lt;p&gt;A new QA engineer joins, learns the codebase, and starts contributing within 4-6 weeks. Within 8-12 weeks, they're spending 40-60% of their time on the same maintenance work as everyone else. The per-person maintenance burden doesn't decrease with headcount because the root cause selector fragility is proportional to test count, not team size.&lt;/p&gt;

&lt;h3&gt;
  
  
  ‍Maintenance Scales Linearly, Team Output Doesn't
&lt;/h3&gt;

&lt;p&gt;Adding a 4th engineer to a 3-person team doesn't produce a 33% increase in output. Coordination overhead, context switching, and the irreducible time per selector fix mean that the 4th engineer adds maybe 20-25% effective capacity while the suite continues growing and adding maintenance load.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Budget Conversation Gets Harder Each Time
&lt;/h3&gt;

&lt;p&gt;The first hire request ("we need a third QA engineer") is easy to approve. The fifth request ("we need two more people to maintain 400 tests") triggers executive scrutiny: "Why is QA headcount growing faster than engineering headcount? What's the ROI on this automation investment?"&lt;/p&gt;

&lt;p&gt;This is the conversation where QA leads lose credibility not because they're wrong about needing help, but because they're solving a structural problem with a staffing solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Make the Architecture Decision
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Too Early (Under 50 Tests)
&lt;/h3&gt;

&lt;p&gt;At under 50 tests, maintenance is minimal and the team is still learning its testing patterns. Switching tools adds complexity without clear ROI. Build your first 50 tests with whatever tool you know, establish your critical-path coverage, then evaluate.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Sweet Spot (100-200 Tests)
&lt;/h3&gt;

&lt;p&gt;This is the optimal migration window:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintenance is noticeable but not yet overwhelming (8-16 hours/week)&lt;/li&gt;
&lt;li&gt;The team has enough test history to identify highest-maintenance areas&lt;/li&gt;
&lt;li&gt;The migration can happen incrementally (rewrite 10-20 highest-maintenance tests first)&lt;/li&gt;
&lt;li&gt;The comparison data (maintenance hours per test, selector vs Vision AI) is compelling within 2 sprints&lt;/li&gt;
&lt;li&gt;You avoid the sunk cost psychology that makes switching harder at 300+ tests&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Late but Still Worth It (200-400 Tests)
&lt;/h3&gt;

&lt;p&gt;Migration at this stage is harder more tests to rewrite, more maintenance debt to dig out of, more team inertia to overcome. But the ROI is also larger because the maintenance savings are immediate and substantial. Start with the top 20% of tests that cause 80% of maintenance. Run them in parallel with existing tests. Let the data make the case.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Parallel Pilot
&lt;/h3&gt;

&lt;p&gt;Regardless of stage, the migration path is the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify your 10-20 highest-maintenance tests (the ones that break every sprint)&lt;/li&gt;
&lt;li&gt;Rewrite them in &lt;a href="//drizz.dev"&gt;Drizz&lt;/a&gt; (plain English, no selectors)&lt;/li&gt;
&lt;li&gt;Run both versions for 4 sprints&lt;/li&gt;
&lt;li&gt;Compare maintenance hours per test&lt;/li&gt;
&lt;li&gt;Present the data to leadership&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If 20 Drizz tests require zero maintenance while 20 Appium tests require 12+ hours of fixes over 4 sprints, the math speaks for itself. No pitch required.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the VP of Engineering Actually Needs to See
&lt;/h2&gt;

&lt;p&gt;QA leads often make the case for tool changes in QA language: selectors, XPath, locator strategies, flaky tests. VPs of Engineering think in different terms. Here's how to translate:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzk800t2c53r0urxb7l2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzk800t2c53r0urxb7l2.png" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The difference between a QA team that scales to 500 tests and one that plateaus at 200 isn't talent, effort, or budget. It's architecture.&lt;/p&gt;

&lt;p&gt;Selector-based test suites have a mathematical scaling limit: maintenance grows linearly with test count, and no amount of better practices, hiring, or process optimization changes the slope. You can slow it down (accessibility IDs instead of XPath, Page Object Model, retry logic) but you can't flatten it.&lt;/p&gt;

&lt;p&gt;Vision AI testing flattens the curve by removing the coupling between tests and internal element identifiers. Tests describe what the user sees, not what the element tree contains. When the UI changes, the user still sees a login button, a cart icon, a checkout screen. The tests still pass.&lt;/p&gt;

&lt;p&gt;For delivery apps shipping weekly, the math is unambiguous: a 3-person QA team with Vision AI outperforms a 6-person team with selector-based tools more coverage, fewer regressions, higher velocity, lower cost.&lt;/p&gt;

&lt;p&gt;The question isn't whether your team will hit the maintenance wall. It's whether you'll rearchitect before it happens or after.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.drizz.dev/book-a-demo" rel="noopener noreferrer"&gt;Get started with Drizz&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  At what test count does maintenance become unsustainable?
&lt;/h3&gt;

&lt;p&gt;For teams shipping weekly with selector-based tools, maintenance typically becomes unsustainable at 150-200 tests. At this point, 40-60% of QA capacity is consumed by maintenance, coverage velocity drops below 4 new tests per sprint, and the team enters a maintenance trap where the suite grows slower than the product.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long does it take to migrate from Appium to Vision AI?
&lt;/h3&gt;

&lt;p&gt;Migration is incremental, not all-or-nothing. Rewriting 20 high-maintenance tests in Drizz takes approximately 2-3 days. Running a 4-sprint parallel pilot takes 8 weeks. Full suite migration (200-300 tests) typically takes 4-8 weeks with a 2-person team, done alongside normal testing work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a 2-person QA team maintain 500 tests?
&lt;/h3&gt;

&lt;p&gt;With selector-based tools, no. A 500-test Appium suite requires 50+ hours per week of maintenance more than one person's full capacity. With Vision AI, yes. A 500-test Drizz suite requires approximately 5 hours per week of maintenance, leaving a 2-person team with 75 hours per week for new test creation, exploratory testing, and strategic QA work. A third person is recommended at 500+ tests for coverage breadth, not maintenance.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the ROI timeline for switching testing architecture?
&lt;/h3&gt;

&lt;p&gt;Most teams see positive ROI within 3-4 months. Month 1-2 is the parallel pilot (20 tests, both tools, compare maintenance). Month 3-4 is incremental migration of the highest-maintenance tests. By month 4, the maintenance savings on migrated tests exceed the migration effort, and the delta grows every sprint thereafter.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I convince my VP of Engineering to approve the switch?
&lt;/h3&gt;

&lt;p&gt;Don't pitch tools. Pitch data. Run the parallel pilot (20 tests, 4 sprints), calculate maintenance hours per test for both approaches, and present the projected annual cost at 300 and 500 tests on each path. The Hiring vs Rearchitecting table in this article is the slide format that resonates: FTEs consumed, QA team size needed, annual cost. Let the math make the case.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>How to Test Payment Flows in Mobile Apps Without Test Cards Failing Every Sprint</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Mon, 22 Jun 2026 17:19:43 +0000</pubDate>
      <link>https://dev.to/drizzdev/how-to-test-payment-flows-in-mobile-apps-without-test-cards-failing-every-sprint-287k</link>
      <guid>https://dev.to/drizzdev/how-to-test-payment-flows-in-mobile-apps-without-test-cards-failing-every-sprint-287k</guid>
      <description>&lt;p&gt;Your payment tests passed in staging. Then PhonePe pushed an SDK update on Tuesday, the UPI intent deep link stopped launching on Samsung devices, and 12% of Wednesday's checkout attempts failed silently. The payment was never charged. The order was never placed. The user saw a frozen screen and uninstalled.&lt;/p&gt;

&lt;p&gt;Payment testing is the highest-stakes, highest-maintenance area of mobile QA. It's also the area where most teams have the least automation coverage because payment flows depend on third-party SDKs, external app launches, OS-level intents, and provider-specific UI that changes without warning and without your involvement.&lt;/p&gt;

&lt;p&gt;This guide covers how to build payment testing that actually survives sprint-to-sprint: what specifically breaks, why traditional automation struggles with payment flows, what to test at each layer, and how Vision AI validates the payment experience users actually see.&lt;/p&gt;

&lt;p&gt;For the complete checkout testing deep dive, see W&lt;a href="https://dev.to/drizzdev/why-checkout-flows-break-more-than-anything-else-in-delivery-apps-4637"&gt;hy Checkout Flows Break More Than Anything Else&lt;/a&gt;. For the full delivery app checklist, see &lt;a href="https://dev.to/drizzdev/how-to-test-a-food-delivery-app-30-test-cases-from-order-to-doorstep-4kok"&gt;30 Test Cases from Order to Doorstep.&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Payment flow testing is the highest-maintenance area of mobile QA because it depends on third-party SDKs (Razorpay, Juspay, Google Pay, PhonePe) that update independently of your release cycle, breaking your tests without any change to your code.&lt;/li&gt;
&lt;li&gt;India's payment landscape requires testing 15-20+ payment paths: UPI (5+ apps), cards (Visa, Mastercard, RuPay), net banking (50+ banks), wallets (Paytm, Amazon Pay, Mobikwik), COD, platform credits, EMI, and split payments.&lt;/li&gt;
&lt;li&gt;UPI is the most failure-prone payment method to test because it crosses app boundaries (your app → OS intent → UPI app → callback), and the OS-level app selector is invisible to Appium's element tree.&lt;/li&gt;
&lt;li&gt;Four-layer testing strategy: API-level payment logic (every PR) → Vision AI visual flow validation (every build) → provider sandbox integration (weekly) → edge case and network resilience (pre-release).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI&lt;/a&gt; (Drizz) validates payment flows visually, so payment provider SDK updates don't break tests a card number field still looks like a card number field regardless of which SDK version rendered it.&lt;/li&gt;
&lt;li&gt;A production app with 8-12 payment methods needs 40-60 payment-specific test cases. With selector-based tools, these require 10-15 hours of maintenance per sprint. With Vision AI, 1-2 hours.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Makes Payment Flow Testing So Difficult?
&lt;/h2&gt;

&lt;p&gt;Payment flow testing is uniquely difficult because it crosses the boundary between your app and external systems you don't control. Five structural factors make it the hardest area to automate reliably:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Third-Party SDK Dependency
&lt;/h3&gt;

&lt;p&gt;A typical Indian mobile app integrates 3-5 payment SDKs: Razorpay or Juspay as the payment gateway, Google Pay / PhonePe / Paytm for UPI, and individual card network processors. Each SDK has its own release cycle, its own UI components, and its own breaking changes. When Razorpay pushes SDK version 4.2.1, your checkout screen may render differently, timeout differently, or return different callback formats without a single line of your code changing.&lt;/p&gt;

&lt;p&gt;Your test suite has zero visibility into when these SDK updates ship. The first sign is failing tests on Monday morning.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. OS-Level Intent and Deep Link Fragility
&lt;/h3&gt;

&lt;p&gt;UPI payments on Android work through intents: your app fires an intent, the OS presents a list of UPI apps, the user selects one (Google Pay, PhonePe, Paytm), the selected app handles the transaction and returns the result to your app. Each step in this chain can break:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The intent format (the technical instruction Android uses to launch UPI apps) changes between Android versions&lt;/li&gt;
&lt;li&gt;Samsung's One UI handles intent resolution differently than stock Android&lt;/li&gt;
&lt;li&gt;Some UPI apps don't return proper success/failure callbacks&lt;/li&gt;
&lt;li&gt;The UPI app selector dialog is an OS-level component invisible to your app's element tree&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Appium can fire the intent. It cannot reliably interact with the OS-level app selector or the UPI app's own UI those are outside your app's process and element tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Payment State Complexity
&lt;/h3&gt;

&lt;p&gt;A payment flow has more failure states than success states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payment initiated but never completed (user abandoned)&lt;/li&gt;
&lt;li&gt;Payment processing (stuck in limbo between your app and the provider)&lt;/li&gt;
&lt;li&gt;Payment succeeded but callback not received (money deducted, order not placed)&lt;/li&gt;
&lt;li&gt;Payment failed with retry available&lt;/li&gt;
&lt;li&gt;Payment failed with no retry (card blocked, insufficient funds)&lt;/li&gt;
&lt;li&gt;Payment succeeded on retry but first attempt also succeeded (double charge)&lt;/li&gt;
&lt;li&gt;Partial payment completed (wallet deducted, UPI portion failed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each state requires specific UI handling: error messages, retry buttons, refund notifications, and status indicators. Testing every state requires mocking provider responses which means your tests depend on your mock accuracy matching the provider's actual behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. India's Payment Method Diversity
&lt;/h3&gt;

&lt;p&gt;The Indian market has more payment permutations than almost any other geography:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UPI&lt;/strong&gt; (Google Pay, PhonePe, Paytm, BHIM, WhatsApp Pay) each with its own app, its own UI, its own callback behavior&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credit/Debit Cards&lt;/strong&gt; (Visa, Mastercard, RuPay) via Razorpay, Juspay, or direct integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Net Banking&lt;/strong&gt; (50+ banks, each with their own login flow)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wallets&lt;/strong&gt; (Paytm Wallet, Amazon Pay, Mobikwik, Freecharge)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cash on Delivery&lt;/strong&gt; (toggle logic interacting with coupons and minimum order rules)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform Credits/Coins&lt;/strong&gt; (partial payment requiring balance calculation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EMI&lt;/strong&gt; (card-based installment options with eligibility checks)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split Payments&lt;/strong&gt; (wallet balance + UPI for the remainder)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Testing "payment works" means testing 15-20+ payment paths, each with its own failure modes.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Provider-Specific Element IDs Change Without Notice
&lt;/h3&gt;

&lt;p&gt;When a payment provider updates their SDK, the element IDs inside their payment UI change. The Razorpay checkout sheet that had resource-id="rzp_card_number" in version 4.1 might use resource-id="card_number_input" in version 4.2. Your Appium tests targeting Razorpay elements break and you didn't change anything.&lt;/p&gt;

&lt;p&gt;This is the unique maintenance burden of payment testing: your tests break because of someone else's code changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Specifically Breaks in Payment Testing?
&lt;/h2&gt;

&lt;p&gt;Based on patterns across mobile apps processing millions of daily transactions in India:&lt;/p&gt;

&lt;h3&gt;
  
  
  UPI Failures (Most Common)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intent not launching:&lt;/strong&gt; The UPI app selector doesn't appear, or appears but shows "No UPI apps installed" on a device that has Google Pay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App-specific failures:&lt;/strong&gt; Payment works via Google Pay but fails via PhonePe on the same device, same amount, same merchant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Callback not received:&lt;/strong&gt; The UPI app deducts money and shows success, but your app never receives the callback. User sees a frozen "Processing" screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeout handling:&lt;/strong&gt; User opens UPI app, gets distracted for 3 minutes, the transaction times out but your app doesn't show a timeout message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collect vs Pay flow confusion:&lt;/strong&gt; Some integrations use collect requests (merchant initiates), others use pay flows (user initiates). The UI flow differs and tests written for one break on the other.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Card Payment Failures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3D Secure redirect breaking:&lt;/strong&gt; The bank's OTP/authentication page fails to load inside the payment gateway's WebView.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saved card tokens expiring:&lt;/strong&gt; A test using saved card credentials fails when the token expires or the card is re-issued.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RuPay-specific flows:&lt;/strong&gt; RuPay cards route through different processors than Visa/Mastercard, with different UI and different timeout behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Wallet and Split Payment Failures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partial payment state corruption:&lt;/strong&gt; Wallet balance deducted successfully, but the UPI portion for the remainder fails. Total is now wrong. Refund for wallet portion doesn't trigger automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wallet balance display stale:&lt;/strong&gt; Cached wallet balance shows 500 but actual balance is 200. User selects wallet, payment fails with insufficient funds but the UI showed enough balance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform credits + coupon interaction:&lt;/strong&gt; A 100-credit platform discount applied alongside a 20% coupon does the coupon apply before or after credits? Different builds have calculated this differently.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  COD-Specific Failures
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;COD availability logic:&lt;/strong&gt; COD is available for orders under 1,500 but the threshold changes by city. Test written for Delhi (1,500 limit) fails in a tier-3 city (500 limit).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COD + coupon interaction:&lt;/strong&gt; Free delivery coupon applied with COD does the delivery fee get added back to the COD amount or absorbed?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COD toggle state:&lt;/strong&gt; User selects COD, then switches to UPI, then switches back to COD the order total should be identical. Sometimes it's not.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Should You Test at Each Layer?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Layer 1: API-Level Payment Logic (Run on every PR)
&lt;/h3&gt;

&lt;p&gt;Test payment calculation, coupon interaction, and state management without touching the UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Order total calculation with different item combinations&lt;/li&gt;
&lt;li&gt;Coupon discount applied correctly (flat, percentage, capped)&lt;/li&gt;
&lt;li&gt;Delivery fee calculation by distance and time&lt;/li&gt;
&lt;li&gt;Surge pricing applied and reflected in total&lt;/li&gt;
&lt;li&gt;Wallet balance deduction and remainder calculation&lt;/li&gt;
&lt;li&gt;Payment callback handling for each status (success, failure, pending, timeout)&lt;/li&gt;
&lt;li&gt;Refund trigger logic for failed partial payments&lt;/li&gt;
&lt;li&gt;COD availability rules by city and order amount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Postman, RestAssured, pytest with API client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2: Visual Payment Flow Testing (Run on every build)
&lt;/h3&gt;

&lt;p&gt;Validate what the user actually sees during each payment method:&lt;br&gt;
Select UPI as payment method&lt;br&gt;
Verify UPI app selector or UPI ID input appears&lt;br&gt;
Verify at least one UPI app option is visible&lt;/p&gt;

&lt;p&gt;Select Credit/Debit Card as payment method&lt;br&gt;
Verify card number input field appears&lt;br&gt;
Verify expiry and CVV fields are visible&lt;br&gt;
Verify "Pay" button is displayed with correct amount&lt;/p&gt;

&lt;p&gt;Select Cash on Delivery&lt;br&gt;
Verify order total updates (no payment processing fee)&lt;br&gt;
Tap "Place Order"&lt;br&gt;
Verify order confirmation shows COD as payment method&lt;/p&gt;

&lt;p&gt;Toggle "Use Wallet Balance" on&lt;br&gt;
Verify wallet balance is deducted from total&lt;br&gt;
Verify remaining amount is displayed&lt;br&gt;
Select UPI for remaining amount&lt;br&gt;
Complete payment&lt;br&gt;
Verify order confirmed with split payment summary&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool:&lt;/strong&gt; Drizz (Vision AI) tests validate the visual payment flow regardless of which payment SDK version is running or what element IDs the provider uses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3: Payment Provider Integration Testing (Run weekly)
&lt;/h3&gt;

&lt;p&gt;With test/sandbox credentials from each payment provider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete a full transaction via each UPI app (Google Pay, PhonePe, Paytm)&lt;/li&gt;
&lt;li&gt;Complete a card transaction with 3D Secure OTP&lt;/li&gt;
&lt;li&gt;Complete a net banking transaction with at least 2 banks&lt;/li&gt;
&lt;li&gt;Test timeout behavior (wait for provider timeout, verify your app handles it)&lt;/li&gt;
&lt;li&gt;Test failure scenarios (insufficient funds, declined, network error)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Provider sandbox environments + Drizz for visual flow validation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 4: Edge Case and Regression (Run before releases)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Double-tap on "Place Order"  verify order isn't placed twice&lt;/li&gt;
&lt;li&gt;Network drop during payment processing  verify graceful recovery&lt;/li&gt;
&lt;li&gt;App backgrounded during UPI payment  verify callback still received on return&lt;/li&gt;
&lt;li&gt;Payment succeeded but app crashed verify order status on relaunch&lt;/li&gt;
&lt;li&gt;Retry after failed payment  verify amount is correct (not doubled)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Manual testing + network simulation (Charles Proxy) + Vision AI for visual state validation.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does Vision AI Change Payment Testing?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.drizz.dev/" rel="noopener noreferrer"&gt;Drizz&lt;/a&gt; is a Vision AI mobile testing platform that validates payment flows by looking at the rendered screen the same way a user does rather than querying element IDs inside third-party payment SDKs. The core advantage for payment testing: your tests don't break when someone else's SDK updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment provider SDK updates don't break tests:&lt;/strong&gt; When Razorpay changes their checkout sheet UI, the card number field still looks like a card number field on screen. Vision AI finds it visually. The test passes without updating selectors for the new SDK version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPI app selector is testable:&lt;/strong&gt; The OS-level UPI app selector that's invisible to Appium (it's outside your app's process) is visible to Vision AI it's rendered on the screen. "Verify UPI app options are displayed" works because the AI sees what's on screen, not what's in your app's element tree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment confirmation is visually verified:&lt;/strong&gt; "Verify Order Confirmed screen appears with order ID and payment method" validates the actual rendered result, not an element tree property that might say "success" while the screen shows an error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual bugs in payment flows are caught:&lt;/strong&gt; "Pay 449" button text truncated to "Pay 4..." on a small screen. Card input field covered by keyboard. CVV field not visible without scrolling. Dark mode rendering showing white text on white input field. These are invisible to Appium but visible to Vision AI.&lt;/p&gt;

&lt;p&gt;Watch &lt;a href="https://www.youtube.com/watch?si=yKNqYxCPQyIQxevT&amp;amp;v=Lei4fvGqgtQ&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;Drizz testing the Licious app&lt;/a&gt; for a real example of Vision AI navigating a payment flow on a delivery app handling product selection, cart, and payment confirmation visually.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Many Payment Tests Does a Typical App Need?
&lt;/h2&gt;

&lt;p&gt;A production app with 8-12 payment methods typically maintains 40-60 payment-specific test cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;8-12 happy path flows (one per payment method)&lt;/li&gt;
&lt;li&gt;5-8 failure/error handling flows (timeout, decline, insufficient funds)&lt;/li&gt;
&lt;li&gt;3-5 split/partial payment flows (wallet + UPI, credits + card)&lt;/li&gt;
&lt;li&gt;3-5 coupon + payment interaction flows&lt;/li&gt;
&lt;li&gt;3-5 COD-specific flows (availability, toggle state, amount calculation)&lt;/li&gt;
&lt;li&gt;2-3 retry and double-charge prevention flows&lt;/li&gt;
&lt;li&gt;3-5 visual rendering tests (keyboard overlap, truncation, dark mode)&lt;/li&gt;
&lt;li&gt;2-3 network resilience flows (payment under poor connectivity)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With selector-based tools, these 40-60 tests require 10-15 hours of maintenance per sprint largely driven by payment provider SDK updates breaking element references. With Vision AI, the same suite requires 1-2 hours because tests validate visual patterns rather than provider-specific element IDs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Payment testing will always be harder than testing any other flow in a mobile app. The dependency on third-party SDKs, OS-level intents, and external provider UIs makes it structurally different from testing screens you fully control.&lt;/p&gt;

&lt;p&gt;But the majority of payment test maintenance the selector updates every time Razorpay ships an SDK bump, the element ID changes every time PhonePe redesigns their checkout sheet, the broken intents every time Android updates its intent resolver is caused by coupling your tests to internal identifiers inside systems you don't own.&lt;/p&gt;

&lt;p&gt;Vision AI eliminates that coupling. A card number field is tested as a card number field, not as rzp_card_input_v4_2_1. A UPI app selector is tested as a list of payment apps on screen, not as an OS-level intent that may or may not be in your element tree. The payment confirmation screen is verified as what the user actually sees, not as an element property that says "success" while the screen says nothing.&lt;/p&gt;

&lt;p&gt;The teams that build resilient payment testing don't test more. They test differently at the API layer for logic, at the visual layer for experience, and at the provider layer for integration. That combination catches the payment bugs that cost revenue while spending a fraction of the maintenance time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.drizz.dev/" rel="noopener noreferrer"&gt;Get started with Drizz&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can you fully automate payment testing?
&lt;/h3&gt;

&lt;p&gt;You can automate the UI flow (selecting payment method, entering credentials, verifying confirmation) and the API logic (calculation, callbacks, state management). Actual money movement requires sandbox/test credentials from each payment provider. Most providers (Razorpay, Juspay, Stripe) offer test modes that simulate transactions without real charges.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you test UPI payments in CI/CD?
&lt;/h3&gt;

&lt;p&gt;UPI testing in CI requires either mocked UPI responses (API-level) or test UPI credentials that complete without launching a real UPI app. Vision AI validates the visual flow up to the UPI app selector and after the callback returns. The actual UPI transaction is either mocked or uses a test-mode integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do payment tests break more than other tests?
&lt;/h3&gt;

&lt;p&gt;Payment tests depend on third-party SDKs (Razorpay, Juspay, Google Pay) that update independently of your app's release cycle. When a provider changes their SDK, the element IDs inside their payment UI change breaking your selectors without any change to your code. This is unique to payment testing and doesn't affect other flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does Vision AI handle different payment provider UIs?
&lt;/h3&gt;

&lt;p&gt;Vision AI identifies payment elements visually a card number field looks like a card number field regardless of whether it's Razorpay's UI or Juspay's UI. When a provider updates their SDK and changes element IDs, the visual appearance remains similar and the test continues passing. This eliminates the most frequent cause of payment test maintenance.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the most critical payment test to automate first?
&lt;/h3&gt;

&lt;p&gt;The "happy path" for your highest-volume payment method. In India, that's typically UPI (60-70% of digital transactions). Automate: select UPI → verify app selector → complete payment → verify order confirmed. This single flow catches the most common payment failure the UPI intent not launching or the callback not returning.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Testing Real Time Features in Delivery Apps: Maps, Live Tracking, and ETA Updates</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Thu, 18 Jun 2026 21:29:19 +0000</pubDate>
      <link>https://dev.to/drizzdev/testing-real-time-features-in-delivery-apps-maps-live-tracking-and-eta-updates-3mp</link>
      <guid>https://dev.to/drizzdev/testing-real-time-features-in-delivery-apps-maps-live-tracking-and-eta-updates-3mp</guid>
      <description>&lt;p&gt;The moment a customer taps "Place Order," the most anxiety-driven part of the delivery experience begins. They're watching a pin move on a map, a countdown tick from 25 minutes to 3 minutes, and a status bar shift from "Preparing" to "On the Way" to "Delivered." These real-time features are the entire experience between paying and eating.&lt;/p&gt;

&lt;p&gt;They're also the features that almost no QA team can automate properly.&lt;/p&gt;

&lt;p&gt;Here's why: Appium can verify that a map element exists on screen. It cannot confirm the delivery partner's pin actually moved. A find_element(AppiumBy.ID, "map_view").is_displayed() returns True whether the map is rendering correctly, frozen on stale coordinates, showing the wrong route, or displaying the partner in the middle of an ocean. The test passes. The user sees a broken map.&lt;/p&gt;

&lt;p&gt;Live tracking, ETA countdown, order status transitions, and push notifications are all visual, dynamic, and time-dependent everything that selector-based automation was not built for.&lt;/p&gt;

&lt;p&gt;This guide covers how to test these real-time features at scale: what specifically needs validating, why traditional tools hit a wall, and how Vision AI validates what users actually see on screen not what the element tree reports underneath.&lt;/p&gt;

&lt;p&gt;For the complete delivery app testing checklist, see our &lt;a href="https://www.drizz.dev/post/how-to-test-a-food-delivery-app-30-test-cases-from-order-to-doorstep" rel="noopener noreferrer"&gt;30 Test Cases from Order to Doorstep guide&lt;/a&gt;. For the broader challenge, see &lt;a href="https://dev.to/drizzdev/why-delivery-apps-are-the-hardest-to-test-and-what-its-costing-qa-teams-27fi"&gt;Why Delivery Apps Are the Hardest to Test&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Real-Time Features in Delivery Apps?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxo4u3o46ei88qel49nj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxo4u3o46ei88qel49nj.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Real-time features are UI elements that update continuously based on server-pushed data, GPS coordinates, or time-based state changes without the user taking any action. In delivery apps, five features are real-time:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.Live map tracking:&lt;/strong&gt; A map displaying the delivery partner's current position, updated every 3-5 seconds via GPS coordinates pushed from the partner's device. The map shows the route, the partner's pin moving along it, and the restaurant and customer location markers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.ETA countdown:&lt;/strong&gt; An estimated time of arrival that recalculates based on the delivery partner's real-time position, traffic conditions, and route changes. The ETA text updates on screen without user interaction "18 min" becomes "15 min" becomes "3 min" as the partner approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Order status transitions:&lt;/strong&gt; The order moves through a state machine: Order Placed → Restaurant Confirmed → Preparing → Ready for Pickup → Partner Assigned → Picked Up → On the Way → Nearby → Delivered. Each transition triggers a UI change status text, icon, animation, and sometimes a full screen transition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.Push notifications:&lt;/strong&gt; Each order status transition generates a push notification: "Your order is being prepared," "Driver is on the way," "Your order has arrived." These notifications must arrive in sequence, with correct content, at the right time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.Dynamic pricing updates:&lt;/strong&gt; Surge pricing, delivery fee recalculation, and promotional timers that count down on screen. A "Free delivery for next 4:32" timer ticking in real-time on the home screen.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Can't Selector-Based Tools Test Real-Time Features?
&lt;/h2&gt;

&lt;p&gt;Traditional automation tools (Appium, Espresso, XCUITest) interact with the element tree a structured representation of UI components with properties like text, resource-id, and content-description. Real-time features break this model in four ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  Maps Are Opaque Canvas Elements
&lt;/h3&gt;

&lt;p&gt;Map views (Google Maps SDK, Mapbox) render to a canvas or GL surface. Appium sees one  or  element. The delivery partner pin, route line, restaurant marker, and customer marker are all rendered inside that canvas invisible to the element tree. Appium can verify the map element exists. It cannot verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether the delivery partner pin is at the correct coordinates&lt;/li&gt;
&lt;li&gt;Whether the pin moved since the last check&lt;/li&gt;
&lt;li&gt;Whether the route line renders correctly&lt;/li&gt;
&lt;li&gt;Whether the partner pin is on the route or off it&lt;/li&gt;
&lt;li&gt;Whether the map is zoomed to show both partner and customer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ETA Text Changes Are Timing-Dependent
&lt;/h3&gt;

&lt;p&gt;The ETA text updates server-side, pushed to the client at intervals. A test that asserts eta_text == "15 min" fails 3 seconds later when it updates to "14 min." The test is technically correct it verified a specific value at a specific moment but it tells you nothing about whether the ETA is updating correctly, calculating accurately, or displaying at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Status Transitions Are Sequential and Time-Bound
&lt;/h3&gt;

&lt;p&gt;Order status transitions happen over 20-45 minutes in production. A test can't wait 45 minutes for a status to change. Most teams mock status transitions by pushing state changes through a test API but this only validates that the app renders a given state, not that the transition from one state to the next triggers the correct UI change, animation, and notification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Push Notifications Are External to the App
&lt;/h3&gt;

&lt;p&gt;Push notifications are delivered by the OS notification system, not rendered inside the app's element tree. Appium can check if a notification appeared in the notification shade (on Android via UiAutomator), but correlating "this notification appeared at the right time in the right sequence for&lt;/p&gt;




&lt;h2&gt;
  
  
  What Specifically Needs Testing for Each Real-Time Feature?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Live Map Tracking: 8 Test Scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmdyue59ztiuhz9kj7xmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmdyue59ztiuhz9kj7xmw.png" alt=" " width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ETA Updates: 5 Test Scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcv3x7xbcfux1h0ye5an8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcv3x7xbcfux1h0ye5an8.png" alt=" " width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Order Status Transitions: 6 Test Scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft7id9f411z83lyp2jcv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft7id9f411z83lyp2jcv5.png" alt=" " width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Push Notifications: 4 Test Scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5wlch7c83vcg39817mf1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5wlch7c83vcg39817mf1.png" alt=" " width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How Does Vision AI Test Real-Time Features?
&lt;/h2&gt;

&lt;p&gt;Vision AI (Drizz) validates real-time features by observing the rendered screen exactly what the user sees rather than querying the element tree underneath. This is the fundamental architectural advantage for real-time testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Map Pin Movement
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Place an order and navigate to tracking screen
Verify map is visible and rendering (not blank or grey)
Verify a delivery partner marker is visible on the map
Wait 15 seconds
Verify the delivery partner marker has changed position
Verify a route line is visible connecting partner to destination

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Vision AI takes a screenshot, identifies the partner pin visually, waits, takes another screenshot, and confirms the pin has moved. No element tree. No coordinate comparison through APIs. The AI sees what the user sees: a pin that either moved or didn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this catches that Appium can't:&lt;/strong&gt; a frozen map where the MapView element exists and returns is_displayed() = True but the pin hasn't moved in 5 minutes. Appium passes. Vision AI fails correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing ETA Countdown
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On tracking screen, read the current ETA text
Wait 60 seconds
Read the ETA text again
Verify the second ETA is less than the first
Verify ETA displays in readable format (minutes or time)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Vision AI reads the rendered text on screen ("18 min"), waits, reads again ("16 min"), and confirms the value decreased. No element ID for the ETA text needed. If the ETA field is redesigned, moved to a different position, or rendered in a different component the AI still reads it because it's looking at the screen, not querying com.app:id/eta_text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Order Status Transitions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;After placing order, verify status shows "Order Placed" or "Confirmed"
Wait for status to change
Verify status now shows "Preparing" or "Being Prepared"
Verify a progress indicator has advanced
Wait for status to change
Verify status shows "On the Way"
Verify delivery partner name or info is displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For testing status transitions without waiting 45 minutes, most teams trigger status changes through a test API while Vision AI observes the visual result. The API pushes "status: preparing" → the AI confirms the screen shows "Preparing" with the correct visual treatment. The API pushes "status: on_the_way" → the AI confirms the screen transitions correctly.&lt;/p&gt;

&lt;p&gt;This validates the complete loop: backend state change → frontend receives update → UI renders correctly → user sees the right status.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Push Notifications
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Place an order
Wait for push notification
Verify notification appears with order-related content
Tap the notification
Verify the app opens to the order tracking screen
Verify current order status is displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vision AI observes the notification as it appears on the device screen reading the notification text visually to confirm it matches the expected order status. On tap, it verifies the app navigates to the correct tracking screen.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Vision AI Cannot Test in Real-Time Features
&lt;/h2&gt;

&lt;p&gt;Transparency matters. Vision AI has clear limitations for real-time testing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPS coordinate accuracy:&lt;/strong&gt; Vision AI can confirm a pin moved on the map but cannot verify the pin is at the mathematically correct GPS coordinates. Coordinate accuracy requires API-level validation comparing the displayed position to the expected latitude/longitude.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network latency measurement:&lt;/strong&gt; Vision AI can't measure how long a status update takes to propagate from server to client. Latency measurement requires instrumentation or network-level monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Notification delivery timing:&lt;/strong&gt; Vision AI can confirm a notification appeared but can't measure the delay between the server sending it and the device receiving it. Timing precision requires push notification analytics tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Map rendering performance:&lt;/strong&gt; Whether the map renders at 60fps or drops frames during pin movement requires performance profiling tools (GameBench, HeadSpin), not visual testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Audio alerts:&lt;/strong&gt; Notification sounds, in-app audio feedback for order arrival, and other audio cues require audio testing tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is the Recommended Strategy for Real-Time Feature Testing?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Three-Layer Approach
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Layer 1 API validation (backend):&lt;/strong&gt; Verify that the real-time data pipeline is correct: GPS coordinates are pushed at expected intervals, status transitions follow the state machine, ETA calculations use the correct algorithm, push notifications are triggered on each status change. Run on every PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2 Visual validation (Vision AI / Drizz):&lt;/strong&gt; Verify that the user sees the correct result of real-time data: map renders and pin moves, ETA text updates and decreases, status transitions display with correct visual treatment, notifications arrive with correct content. Run on every build across 3-5 devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3 Performance and timing validation (profiling tools):&lt;/strong&gt; Measure map rendering FPS, push notification latency, status update propagation delay, and ETA accuracy over real delivery routes. Run weekly or before releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Triggering Status Changes in Test Environments
&lt;/h3&gt;

&lt;p&gt;Since real-time features depend on external state (GPS, backend status), most teams use one of these approaches to make them testable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test API for status transitions:&lt;/strong&gt; A backend endpoint that advances order status on demand: POST /test/order/{id}/advance-status. The test triggers each transition while Vision AI observes the front-end result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GPS simulation:&lt;/strong&gt; Mock GPS coordinates using Appium's setLocation, Android's mock location provider, or iOS's simulated location scheme. Simulate a delivery route by pushing a sequence of coordinates and validating that the map pin follows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staged test orders:&lt;/strong&gt; In staging environments, create orders with accelerated timelines where the full Placed → Delivered cycle completes in 5 minutes instead of 45. Vision AI observes each transition in real-time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can Appium verify that a map pin moved?
&lt;/h3&gt;

&lt;p&gt;No. Appium sees the map as a single opaque element (MapView or SurfaceView). It can verify the map element exists and is displayed, but it cannot see individual pins, routes, or markers rendered inside the map canvas. Vision AI can observe the pin visually and confirm its position changed between two screenshots.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you test ETA accuracy, not just display?
&lt;/h3&gt;

&lt;p&gt;ETA accuracy requires comparing the displayed ETA against the actual delivery time. This is a data analysis task, not a UI test: log the ETA at order placement, log the actual delivery timestamp, and compare across hundreds of orders. Vision AI validates that the ETA displays and updates correctly on screen. Accuracy validation happens in analytics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Vision AI test real-time features on every build?
&lt;/h3&gt;

&lt;p&gt;Yes, when combined with a test API that triggers status transitions. A CI pipeline can: place a test order, trigger status transitions via API, and have Vision AI validate each visual transition all within a 2-3 minute automated run. This catches rendering regressions on every build without waiting for real deliveries.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about testing real-time features across different network conditions?
&lt;/h3&gt;

&lt;p&gt;Combine network simulation (Charles Proxy, Network Link Conditioner) with Vision AI observation. Simulate 3G or high-latency conditions, trigger a status update, and have Vision AI measure how long until the visual change appears. This catches cases where the UI shows stale data under poor connectivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do delivery apps test live tracking in staging vs production?
&lt;/h3&gt;

&lt;p&gt;Staging environments typically use simulated delivery partners that follow predefined routes at accelerated speed. The GPS coordinates are pushed at 1-second intervals instead of real-time, completing a "delivery" in 2-5 minutes. Vision AI validates the visual experience of this simulated delivery the same way it would validate a real one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>How to Test a Food Delivery App: 30 Test Cases from Order to Doorstep</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Tue, 16 Jun 2026 15:02:35 +0000</pubDate>
      <link>https://dev.to/drizzdev/how-to-test-a-food-delivery-app-30-test-cases-from-order-to-doorstep-4kok</link>
      <guid>https://dev.to/drizzdev/how-to-test-a-food-delivery-app-30-test-cases-from-order-to-doorstep-4kok</guid>
      <description>&lt;p&gt;Every food delivery app has the same promise: you tap a button, food shows up at your door. Testing that promise requires covering everything between those two moments  search, browse, cart, coupons, payments, tracking, delivery confirmation, ratings, and the dozen things that can go wrong at each step.&lt;/p&gt;

&lt;p&gt;This guide provides 30 ready-to-use test cases covering every critical flow in a food delivery app, from opening the app to the food arriving. Each test case is written two ways: the traditional Appium approach (selectors, waits, assertions) and the Vision AI approach (plain English, no code). By the end, you'll have a complete QA checklist you can execute today.&lt;/p&gt;

&lt;p&gt;These test cases are based on patterns from production delivery apps processing over a million orders daily in India, including platforms tested with &lt;a href="https://www.youtube.com/watch?si=yKNqYxCPQyIQxevT&amp;amp;v=Lei4fvGqgtQ&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;Drizz Vision AI.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the broader delivery app testing strategy, see our &lt;a href="https://dev.to/drizzdev/why-delivery-apps-are-the-hardest-to-test-and-what-its-costing-qa-teams-27fi"&gt;Why Delivery Apps Are the Hardest to Test &lt;/a&gt; guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Read These Test Cases
&lt;/h2&gt;

&lt;p&gt;Each test case is shown in two formats:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Appium (traditional):&lt;/strong&gt; Python code using selectors, explicit waits, and element assertions. Requires Appium server, platform SDKs, and element inspection setup.&lt;br&gt;
&lt;strong&gt;Drizz (Vision AI):&lt;/strong&gt; Plain English steps that describe what the user sees and does. No selectors, no code, no setup beyond connecting a device.&lt;/p&gt;


&lt;h2&gt;
  
  
  Section 1: App Launch and Location (Test Cases 1-5)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  TC-01: App launches and home screen loads
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;launch_app&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/home_screen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/restaurant_list&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;is_displayed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Launch the app
Verify home screen is visible
Verify restaurant listings are displayed

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-02: Location permission prompt appears and is accepted
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.android.permissioncontroller:id/permission_allow_foreground_only_button&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.android.permissioncontroller:id/permission_allow_foreground_only_button&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;‍Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Verify location permission dialog appears
Tap "Allow only while using the app"
Verify home screen loads with restaurant listings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-03: Change delivery location manually
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/location_bar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/search_location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Koramangala&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//android.widget.TextView[contains(@text, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Koramangala&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//android.widget.TextView[contains(@text, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Koramangala&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap the delivery location bar
Type "Koramangala" in location search
Tap "Koramangala" from suggestions
Verify restaurant listings update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ‍TC-04: Restaurants update when location changes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Store current first restaurant name
&lt;/span&gt;&lt;span class="n"&gt;first_restaurant_before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//android.widget.RecyclerView/android.widget.FrameLayout[1]//android.widget.TextView[@resource-id=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;com.app:id/restaurant_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="c1"&gt;# Change location
&lt;/span&gt;&lt;span class="nf"&gt;change_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Whitefield&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;first_restaurant_after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//android.widget.RecyclerView/android.widget.FrameLayout[1]//android.widget.TextView[@resource-id=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;com.app:id/restaurant_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;first_restaurant_before&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;first_restaurant_after&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Note the first restaurant name on screen
Change location to "Whitefield"
Verify restaurant listings have changed
Verify a different restaurant appears first
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-05: "Not serviceable" message for unsupported location
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;change_location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Remote Village&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/not_serviceable_text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;not available&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/not_serviceable_text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Change location to an unsupported area
Verify "not available in your area" message is displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ‍Section 2: Search and Browse (Test Cases 6-10)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-06: Search for a cuisine and verify results
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap the search bar
Type "Biryani"
Verify search results show restaurants with "Biryani" in name or cuisine tags
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-07: Filter by rating (4.0+ stars)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "Filters"
Select "Rating 4.0+"
Tap "Apply"
Verify all displayed restaurants show 4.0 or higher rating
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-08: Sort by delivery time
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "Sort"
Select "Delivery Time"
Verify restaurants are listed with shortest delivery time first
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-09: Browse a restaurant menu
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap on the first restaurant card
Verify restaurant menu screen loads
Verify menu categories are visible
Verify at least one menu item shows name and price
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-10: Restaurant closed message displays correctly
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Navigate to a restaurant marked as closed
Verify "Currently closed" or schedule information is displayed
Verify "Add to Cart" button is disabled or not visible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 3: Cart Management (Test Cases 11-16)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-11: Add item to cart
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;XPATH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;//android.widget.TextView[@text=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Chicken Biryani&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]/following-sibling::android.widget.Button[@resource-id=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;com.app:id/add_btn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/cart_badge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/cart_badge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "Add" next to the first menu item
Verify cart icon shows item count of 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-12: Increase item quantity
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "+" on the added item
Verify quantity shows 2
Verify cart total updates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-13: Remove item from cart
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "-" until item quantity reaches 0
Verify item is removed from cart
Verify cart icon shows empty or disappea
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-14: Add items from different restaurants (multi-restaurant warning)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add an item from Restaurant A
Navigate back and open Restaurant B
Tap "Add" on an item from Restaurant B
Verify "Replace cart" or "Start new cart" dialog appears

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-15: Cart persists after app restart
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add 2 items to cart
Close the app completely
Reopen the app
Verify cart still shows 2 items with correct names and prices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-16: Item unavailable after adding to cart
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add an item to cart
Navigate to checkout
Verify if any "item unavailable" message appears
Verify cart total recalculates if items are removed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Section 4: Checkout and Payment (Test Cases 17-24)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-17: Checkout screen displays order summary correctly
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Appium:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/checkout_btn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nc"&gt;WebDriverWait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;presence_of_element_located&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/order_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/item_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;is_displayed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/delivery_fee&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;is_displayed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;com.app:id/grand_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;is_displayed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "Checkout" or "View Cart"
Verify order summary screen shows item names and quantities
Verify delivery fee is displayed
Verify total amount is displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TC-18: Apply coupon code successfully
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "Apply Coupon" on checkout screen
Type "FLAT50" in coupon field
Tap "Apply"
Verify discount is reflected in the order total
Verify coupon tag shows "FLAT50 applied"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-19: Apply invalid coupon code
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tap "Apply Coupon"
Type "INVALIDCODE" in coupon field
Tap "Apply"
Verify error message "Invalid coupon" or "Coupon not applicable" appears
Verify total remains unchanged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-20: Pay with UPI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On checkout screen, select "UPI" as payment method
Verify UPI app selection or UPI ID input appears
Complete payment
Verify "Order Confirmed" screen appears

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-21: Pay with credit/debit card
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Select "Credit / Debit Card" as payment method
Verify card input form appears
Enter test card details
Tap "Pay"
Verify order confirmation screen appears
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-22: Pay with Cash on Delivery
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Select "Cash on Delivery" as payment method
Tap "Place Order"
Verify order confirmation screen appears
Verify order status shows "COD" payment method

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-23: Pay with wallet (partial + UPI)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Verify wallet balance is displayed on checkout
Toggle "Use wallet balance" on
Verify remaining amount to pay is calculated
Select "UPI" for the remaining amount
Complete payment
Verify order confirmed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-24: Delivery tip selection
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On checkout screen, verify tip options are displayed
Tap a tip amount (e.g., "20")
Verify total updates to include tip
Tap "Place Order"
Verify order confirmation includes tip

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ‍Section 5: Order Tracking (Test Cases 25-27)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-25: Order status updates in real-time
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;After placing an order, verify order tracking screen loads
Verify status shows "Order Placed" or "Confirmed"
Wait for status to update to "Preparing" or "Being Prepared"
Verify status transition is visible on screen

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-26: Live map tracking shows delivery partner
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On order tracking screen, verify map is displayed
Verify delivery partner icon or marker appears on map
Verify ETA is displayed and updates

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-27: Cancel order flow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;On order tracking screen, tap "Cancel Order" or "Help"
Verify cancellation options or reasons are displayed
Select a reason and confirm cancellation
Verify "Order Cancelled" confirmation appears

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ‍Section 6: Post-Delivery (Test Cases 28-30)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TC-28: Rate the order
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;After delivery, verify rating prompt appears
Tap a star rating (e.g., 4 stars)
Verify rating is submitted
Verify "Thank you" or confirmation message appears

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-29: Reorder previous order
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Navigate to order history
Tap "Reorder" on a previous order
Verify items are added to cart with correct quantities
Navigate to checkout
Verify order summary matches previous order

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TC-30: Report an issue with delivered order
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Drizz:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Navigate to order history
Tap on a completed order
Tap "Help" or "Report an Issue"
Verify issue categories are displayed (wrong item, missing item, quality)
Select an issue and submit
Verify confirmation that issue is reported
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Pattern You Just Saw
&lt;/h2&gt;

&lt;p&gt;Look at the 30 test cases above. Every Drizz test reads like instructions you'd give a human tester: "tap this, verify that, check this appears." Every Appium test reads like code written for a machine: element IDs, XPath expressions, explicit waits, type assertions.&lt;/p&gt;

&lt;p&gt;Now ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which version survives a checkout screen redesign?&lt;/li&gt;
&lt;li&gt;Which version breaks when a developer renames com.app:id/add_btn to com.app:id/add_to_cart?&lt;/li&gt;
&lt;li&gt;Which version can a manual QA tester write without learning Python?&lt;/li&gt;
&lt;li&gt;Which version takes 5 minutes to write vs 45 minutes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Appium versions require 6-12 selectors per test, each one a potential breakage point. The Drizz versions require zero selectors. When the UI changes, the Appium tests break. The Drizz tests keep passing because the button still says "Add" on screen.&lt;/p&gt;

&lt;p&gt;At 30 test cases with an average of 8 selectors each, an Appium suite has 240 breakage points. A Drizz suite has zero.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Use This Checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you're starting from zero:&lt;/strong&gt; Use the Drizz versions. Install Drizz Desktop, connect a device, and start with TC-01 through TC-10. You'll have your first 10 automated tests running within an hour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have an existing Appium suite:&lt;/strong&gt; Compare your current tests against this checklist. Identify which of the 30 flows you're missing. Rewrite your highest-maintenance tests (checkout, payment, cart) in Drizz and run them in parallel for 2 sprints to compare maintenance cost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you're a QA lead building a strategy:&lt;/strong&gt; This checklist maps to the 5-layer testing strategy recommended for delivery apps. TC-01 through TC-05 are Layer 1 smoke tests. TC-06 through TC-30 are Layer 2-3 regression tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.drizz.dev/book-a-demo" rel="noopener noreferrer"&gt;Get started with Drizz&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How many test cases does a delivery app need?
&lt;/h3&gt;

&lt;p&gt;A production delivery app typically maintains 300-500+ automated test cases. This checklist of 30 covers the critical path from order to doorstep. Additional tests cover edge cases (network failures, concurrent modifications, multi-device sessions), payment permutations (8-12 methods), location-based variations, and device compatibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can these test cases run on both Android and iOS?
&lt;/h3&gt;

&lt;p&gt;The Drizz versions run identically on Android and iOS from a single test file because they describe what the user sees, not platform-specific element identifiers. The Appium versions require separate element locators for Android (resource-id, XPath) and iOS (accessibility-id, predicate string).&lt;/p&gt;

&lt;h3&gt;
  
  
  How long does it take to automate all 30 test cases?
&lt;/h3&gt;

&lt;p&gt;With Drizz: approximately 2-3 hours for all 30 test cases (5-6 minutes each). With Appium: approximately 15-20 hours including element inspection, selector identification, wait configuration, and cross-device validation.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about test data (restaurant names, menu items, prices)?
&lt;/h3&gt;

&lt;p&gt;The Drizz test cases use structural validation ("verify a restaurant card shows name, rating, and delivery time") rather than specific data ("verify Pizza Palace shows Margherita at 299"). This means tests pass regardless of which restaurants are available at test time. For data-specific tests (coupon codes, test payment credentials), parameterize the test data separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need a test environment or can I test on production?
&lt;/h3&gt;

&lt;p&gt;Drizz tests can run on production builds because they don't require instrumentation or debug builds. Use test accounts with test payment credentials to avoid real transactions. Most delivery apps provide sandbox payment modes for QA.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
    <item>
      <title>Why Checkout Flows Break More Than Anything Else in Delivery Apps</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Wed, 10 Jun 2026 16:08:39 +0000</pubDate>
      <link>https://dev.to/drizzdev/why-checkout-flows-break-more-than-anything-else-in-delivery-apps-4637</link>
      <guid>https://dev.to/drizzdev/why-checkout-flows-break-more-than-anything-else-in-delivery-apps-4637</guid>
      <description>&lt;p&gt;Every QA team knows the feeling. The home screen works. Browse works. Search works. Cart works. And then checkout breaks on a Friday night dinner rush and 50,000 orders fail in two hours.&lt;/p&gt;

&lt;p&gt;Checkout is where delivery apps are most fragile and most expensive to get wrong. It's the one screen that touches payments, coupons, delivery fees, surge pricing, tip selection, address validation, and order confirmation simultaneously. A single misaligned element, a failed payment integration, or a state management bug at checkout doesn't just create a support ticket it creates a refund, a lost customer, and a one-star review.&lt;/p&gt;

&lt;p&gt;India's largest food delivery platforms process over a million checkout transactions daily. When checkout breaks, the blast radius is measured in crores, not bug counts.&lt;/p&gt;

&lt;p&gt;This guide breaks down why checkout flows break more than any other flow in delivery apps, what specifically goes wrong, why traditional automation struggles to catch it, and how to build a testing strategy that protects checkout without writing a new script for every payment permutation.&lt;/p&gt;

&lt;p&gt;For the broader delivery app testing challenge, see our &lt;a href="https://www.drizz.dev/post/the-real-cost-of-maintaining-test-suites-for-delivery-apps-and-any-app-that-ships-weekly" rel="noopener noreferrer"&gt;Why Delivery Apps Are the Hardest to Test&lt;/a&gt; guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does Checkout Break More Than Other Flows?
&lt;/h2&gt;

&lt;p&gt;Checkout breaks disproportionately because it is the most complex screen in a delivery app. While home, browse, and search screens primarily display content, checkout actively processes transactions across multiple external systems simultaneously.&lt;/p&gt;

&lt;p&gt;Seven structural reasons make checkout the most failure-prone flow:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Payment provider integration surface:&lt;/strong&gt; A single checkout screen integrates with 8-12 external payment providers: UPI (Google Pay, PhonePe, Paytm), credit/debit card processors (Visa, Mastercard, RuPay via Razorpay/Juspay), net banking, wallets, cash on delivery logic, and platform credits. Each provider has its own SDK, its own timeout behavior, its own error codes, and its own UI overlay. Any provider pushing an SDK update can break checkout without a single line of your code changing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.Coupon and discount logic stacking:&lt;/strong&gt; A checkout may simultaneously apply a platform coupon, a restaurant-specific offer, a first-order discount, a bank cashback offer, and loyalty coins. The stacking logic (which discounts apply together, which override, which cap at a maximum) is complex business logic that changes frequently. A new coupon campaign launched by marketing on Tuesday can break discount calculation on Wednesday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.Dynamic pricing that changes mid-session:&lt;/strong&gt; Delivery fees, surge pricing, packaging charges, small order fees, and platform fees are calculated server-side based on real-time conditions: distance, demand, time of day, and partner availability. A user who opens checkout at 7:58 PM may see different pricing than one who opens at 8:01 PM when surge activates. Tests that assert a specific total break whenever pricing rules change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.Address and delivery slot complexity:&lt;/strong&gt; Checkout validates the delivery address against restaurant delivery radius, checks if the selected delivery slot is still available, and recalculates ETA based on current conditions. An address that was valid when the user started browsing may become undeliverable by the time they reach checkout if the restaurant closes or the delivery radius shifts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.State management across multiple screens:&lt;/strong&gt; The cart is built on the browse screen, modified on the cart screen, and finalized on the checkout screen. Items can go out of stock between cart and checkout. Restaurants can stop accepting orders. Prices can change. Every state transition between screens is a potential point of failure where the checkout screen shows stale data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.Concurrent modification from three apps:&lt;/strong&gt; In a delivery marketplace, the restaurant can modify menu items, mark items unavailable, or change prices while the customer is in the checkout flow. The customer app must handle these server-pushed changes gracefully updating the cart, recalculating the total, or showing an error without corrupting the checkout state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7.Weekly UI iteration on the highest-stakes screen:&lt;/strong&gt; Product teams iterate on checkout more than any other screen because it directly impacts conversion rate. A/B tests on button placement, payment method ordering, tip UI, coupon input design, and order summary layout run continuously. Every iteration changes element positions, IDs, and component structures breaking every selector-based test targeting checkout.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Specifically Goes Wrong at Checkout?
&lt;/h2&gt;

&lt;p&gt;Based on patterns across delivery app QA teams, checkout failures cluster into five categories:&lt;/p&gt;

&lt;h3&gt;
  
  
  Payment Failures
&lt;/h3&gt;

&lt;p&gt;The most common and most costly. Payment failures include: UPI intent not launching (deep link broken), payment provider SDK timeout not handled gracefully, success callback not received (payment succeeded but app shows failure), double-charge on retry, partial payment state corruption (wallet deducted but UPI failed, total not recalculated).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's hard to catch:&lt;/strong&gt; Each payment method has its own failure mode. Testing "checkout works" requires testing 8-12 payment paths independently. Most teams test 2-3 and hope the others work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coupon and Pricing Errors
&lt;/h3&gt;

&lt;p&gt;Discount applied but total not recalculated. Coupon removed but discount still showing. Bank offer applied to ineligible payment method. Surge pricing not reflected in the displayed total. Negative delivery fee after discount stacking. Free delivery coupon applied but delivery fee still charged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's hard to catch:&lt;/strong&gt; Coupon logic is business logic that changes weekly with new campaigns. Static test scripts can't keep up with the coupon catalog. A test written for "FLAT50" breaks when the campaign ends and "SAVE30" replaces it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cart-to-Checkout State Drift
&lt;/h3&gt;

&lt;p&gt;Item marked unavailable after user reached checkout. Price changed between cart and checkout. Restaurant stopped accepting orders mid-flow. Delivery slot expired during payment processing. Cart quantity modified on another device (multi-device session).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's hard to catch:&lt;/strong&gt; These are timing-dependent bugs that only appear when external state changes during the checkout flow. Static test scripts that run in sequence can't reproduce the timing conditions that trigger these failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Address and Delivery Validation
&lt;/h3&gt;

&lt;p&gt;Address outside delivery radius but checkout still accessible. ETA showing "30 min" but actual delivery time is 90 min due to calculation error. Delivery fee calculated for wrong distance. "Deliver to current location" using stale GPS coordinates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's hard to catch:&lt;/strong&gt; Address validation depends on real-time GPS, restaurant radius, and delivery partner availability all of which change continuously. A test that passes at coordinates A may fail at coordinates B, not because of a bug but because of legitimate business rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI Rendering Failures
&lt;/h3&gt;

&lt;p&gt;"Place Order" button hidden behind keyboard on smaller devices. Payment method icons not loading. Order summary text truncated on long item names. Tip selector overlapping with total amount on certain screen sizes. Dark mode rendering showing white text on white background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's hard to catch:&lt;/strong&gt; These are visual bugs invisible to selector-based automation. Appium can verify the "Place Order" button exists in the element tree while it's visually hidden behind the keyboard. The test passes; the user can't order.&lt;/p&gt;




&lt;h2&gt;
  
  
  ‍Why Does Traditional Automation Fail at Checkout Testing?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Selector Fragility on the Most-Changed Screen
&lt;/h3&gt;

&lt;p&gt;Checkout is the screen that gets redesigned most often (weekly A/B tests, conversion optimization experiments). Every redesign changes element IDs, component structure, and layout hierarchy. Selector-based tests break on the screen that matters most.&lt;/p&gt;

&lt;p&gt;A QA team maintaining 40 checkout test cases with Appium reports spending 30-40% of their total maintenance time on checkout tests alone more than any other feature area.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payment Permutation Explosion
&lt;/h3&gt;

&lt;p&gt;Testing every combination of: payment method (8-12) x coupon type (5-10 active) x address type (in-radius, edge, out-of-radius) x time condition (normal, surge, late-night) = hundreds of permutations. Traditional automation requires a separate test script per permutation with hardcoded expected values. Maintaining 200+ checkout permutation scripts is unsustainable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Values Break Assertions
&lt;/h3&gt;

&lt;p&gt;A test that asserts "total = 449" breaks when delivery fee changes, when surge activates, when a coupon campaign ends, or when platform fee is updated. Checkout totals are dynamic by design. Static assertions on dynamic values produce false failures constantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Should Teams Test Checkout Flows in Delivery Apps?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Structural Testing Approach
&lt;/h3&gt;

&lt;p&gt;Instead of testing specific values ("total is 449"), test structural behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Verify order summary shows item name, quantity, and a price"&lt;/li&gt;
&lt;li&gt;"Verify delivery fee is displayed as a positive number"&lt;/li&gt;
&lt;li&gt;"Verify at least one payment method is selectable"&lt;/li&gt;
&lt;li&gt;"Verify tapping Place Order initiates a payment flow"&lt;/li&gt;
&lt;li&gt;"Verify order confirmation screen appears after payment"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These structural tests pass regardless of which items are in the cart, which price they are, or which payment method is used because they validate the checkout pattern, not specific checkout data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vision AI for Checkout Testing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI &lt;/a&gt;(Drizz) is structurally suited for checkout testing because it validates what the user sees rather than what the element tree contains:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment method selection:&lt;/strong&gt; "Verify UPI option is visible, tap UPI, verify UPI app selection screen appears." Works regardless of which UPI SDK version is running or what the payment provider's element IDs are.&lt;br&gt;
&lt;strong&gt;Coupon application:&lt;/strong&gt; "Type SAVE30 in coupon field, tap Apply, verify discount is reflected in the total." If the coupon changes from SAVE30 to FLAT50, update one line not an entire test script with new selectors.&lt;br&gt;
&lt;strong&gt;Order summary validation:&lt;/strong&gt; "Verify cart shows item names, quantities, and prices. Verify total amount is displayed." The Vision AI reads the rendered text on screen, so it works even when the order summary component is completely redesigned.&lt;br&gt;
&lt;strong&gt;Place Order flow:&lt;/strong&gt; "Tap Place Order, verify payment processing screen appears, verify Order Confirmed screen loads." Tests the end-to-end visual flow regardless of which payment provider handles the transaction.&lt;br&gt;
&lt;strong&gt;Visual bug detection:&lt;/strong&gt; Vision AI catches the bugs Appium can't see: "Place Order" button hidden behind keyboard, payment icons not loading, text truncation, dark mode rendering issues. If the user can't see it, the AI can't find it and the test fails with a clear reason.&lt;/p&gt;

&lt;p&gt;Watch &lt;a href="https://www.youtube.com/watch?v=Lei4fvGqgtQ" rel="noopener noreferrer"&gt;Drizz testing the Licious app&lt;/a&gt; for a real example of Vision AI navigating a checkout flow on a delivery app handling dynamic product listings, cart modifications, and payment confirmation visually.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Recommended Checkout Testing Stack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Layer 1 API tests for payment logic:&lt;/strong&gt; Validate coupon calculation, pricing rules, discount stacking, and payment processing at the API level. Run on every PR. Most stable layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2 Vision AI structural UI tests (Drizz):&lt;/strong&gt; Validate the visual checkout experience: cart summary renders correctly, payment methods are visible and tappable, order confirmation appears after payment. Run on every build across 5+ devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3  Payment method smoke tests:&lt;/strong&gt; For each payment method (UPI, card, wallet, COD), run one end-to-end checkout flow. Vision AI handles the visual flow; API mocks or test payment credentials handle the payment provider.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 4 Manual testing for new payment integrations and coupon campaigns:&lt;/strong&gt; When a new payment method is added or a major coupon campaign launches, manual testing validates the full flow before automation catches up.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Many Checkout Tests Does a Delivery App Need?
&lt;/h2&gt;

&lt;p&gt;A production delivery app typically maintains 40-80 checkout-specific test cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;8-12 payment method flows (one per method)&lt;/li&gt;
&lt;li&gt;5-10 coupon/discount scenarios (apply, remove, stack, expired, invalid)&lt;/li&gt;
&lt;li&gt;5-8 pricing edge cases (surge, small order fee, free delivery threshold)&lt;/li&gt;
&lt;li&gt;3-5 address validation scenarios (in-radius, boundary, out-of-radius)&lt;/li&gt;
&lt;li&gt;3-5 cart state scenarios (item unavailable, price changed, restaurant closed)&lt;/li&gt;
&lt;li&gt;3-5 device/rendering tests (small screen, dark mode, keyboard overlap)&lt;/li&gt;
&lt;li&gt;5-10 cross-condition combinations (surge + coupon, COD + tip, wallet + UPI split)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With selector-based tools, these 40-80 tests consume 15-25 hours of maintenance per sprint due to weekly checkout UI changes. With Vision AI structural testing, the same suite requires less than 2 hours because tests validate visual patterns rather than element identifiers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why does checkout break more than login or browse flows?
&lt;/h3&gt;

&lt;p&gt;Login and browse flows are relatively static the UI doesn't change based on real-time external conditions. Checkout simultaneously processes payments through external SDKs, applies dynamic pricing, validates addresses, and manages state across multiple screens. The integration surface is 5-10x larger than any other flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can you automate payment testing in delivery apps?
&lt;/h3&gt;

&lt;p&gt;Yes, but with limitations. Test payment credentials (sandbox mode) from payment providers enable automated checkout flows without real transactions. Vision AI validates the visual flow (selecting payment method, confirming payment screen, verifying order confirmation) while API tests validate the transaction logic. Real payment testing with actual transactions is typically done manually before major releases.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you test coupon flows when coupons change weekly?
&lt;/h3&gt;

&lt;p&gt;Test structural coupon behavior rather than specific coupons: "enter a coupon code, tap apply, verify discount appears in order summary." The specific coupon code can be parameterized and updated from a test data file without changing the test script. Vision AI reads whatever discount text appears on screen rather than asserting a specific discount value.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's the most expensive checkout bug in delivery apps?
&lt;/h3&gt;

&lt;p&gt;Double-charge bugs (payment succeeds twice due to retry logic) and silent payment failures (money deducted but order not placed) are the most expensive because they require manual refund processing, generate support tickets, and cause immediate customer trust loss. These bugs typically occur when payment provider callbacks are mishandled during network instability.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does Vision AI catch checkout bugs that Appium misses?
&lt;/h3&gt;

&lt;p&gt;Appium verifies that a "Place Order" button exists in the element tree. Vision AI verifies that the button is actually visible on the rendered screen. If the button is hidden behind the keyboard, obscured by another element, or rendered in the wrong color against its background, Appium's test passes but Vision AI's test fails correctly identifying a bug the user would experience.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>android</category>
      <category>mobile</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Your Logs Have the Answer. You Just Can't Find It Fast Enough.</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Mon, 08 Jun 2026 17:13:00 +0000</pubDate>
      <link>https://dev.to/steadwing/your-logs-have-the-answer-you-just-cant-find-it-fast-enough-15bh</link>
      <guid>https://dev.to/steadwing/your-logs-have-the-answer-you-just-cant-find-it-fast-enough-15bh</guid>
      <description>&lt;p&gt;Three weeks ago, one of the teams we work with had a checkout outage. The root cause a malformed database query introduced in a deploy 40 minutes earlier was sitting in their CloudWatch logs the entire time. Timestamped. Stack-traced. Perfectly clear.&lt;/p&gt;

&lt;p&gt;They found it 22 minutes after the alert fired.&lt;/p&gt;

&lt;p&gt;Not because they weren't looking. Because they were looking in Elasticsearch first. Their checkout service logs to CloudWatch, but the API gateway that routes to checkout logs to Elasticsearch. The engineer on call didn't remember which was which. So they spent 8 minutes searching Elasticsearch, found nothing relevant, switched to CloudWatch, spent another 6 minutes getting the query syntax right, then another 8 minutes narrowing the time window to find the specific error.&lt;/p&gt;

&lt;p&gt;Twenty-two minutes. The log line had been sitting there since minute one.&lt;/p&gt;

&lt;p&gt;This isn't a story about a bad engineer or bad tooling. It's a story about what happens when incident data is scattered across platforms that don't talk to each other.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The root cause of your last incident was probably in the logs within minutes of the alert firing. Your engineer found it 20 minutes later because they were searching the wrong platform first.&lt;/li&gt;
&lt;li&gt;Nobody decides to run three logging platforms. It happens over two years because different teams pick different tools, and by the time you notice, checkout logs to CloudWatch and payments logs to Elasticsearch and nobody has a map.&lt;/li&gt;
&lt;li&gt;Log search during an incident is nothing like normal debugging. You're guessing at queries, in a syntax you use once a month, looking for something you can't describe yet, while Slack is asking for a status update.&lt;/li&gt;
&lt;li&gt;Steadwing searches all six supported logging platforms in parallel CloudWatch, Elasticsearch, Loki, GCP Logging, Mezmo, and Scalyr scoped by alert timestamps, recent deploys, and metric anomalies. The 13–22 minute manual hunt drops to about 30 seconds.&lt;/li&gt;
&lt;li&gt;You don't need to migrate to one logging platform. That project takes a year and most teams never finish it. You just need your existing platforms to be searchable as one system when something breaks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Logging Landscape Nobody Planned
&lt;/h2&gt;

&lt;p&gt;Here's how it typically happens. Your first few services log to CloudWatch because you're on AWS and it was the default. Then the data team sets up Elasticsearch because they need full-text search on application events. Someone on the platform team introduces Loki because it's lightweight and works well with their Grafana setup. A couple of services that run on GCP use GCP Cloud Logging.&lt;/p&gt;

&lt;p&gt;Nobody sat in a room and decided to run four logging platforms. It happened incrementally over two years, and by the time anyone noticed, each platform had different services, different retention policies, different query languages, and different people who knew how to use them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dash0.com/comparisons/best-log-monitoring-tools-2025" rel="noopener noreferrer"&gt;Dash0's 2025 analysis&lt;/a&gt; describes this perfectly: "when logs are spread across disconnected tools, investigations slow down and critical signals get buried in noise." But the standard advice consolidate onto one platform is a multi-quarter migration that most teams never finish. And it doesn't solve the problem for the incidents happening right now.&lt;/p&gt;

&lt;p&gt;The practical reality for most engineering teams is that logs will continue to live in multiple places. The question isn't how to fix that. It's how to make it not matter during a P0.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Log Investigation Actually Looks Like at 2 AM
&lt;/h2&gt;

&lt;p&gt;Let's walk through what happens when an engineer gets paged for a service returning errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first problem is figuring out where to look:&lt;/strong&gt; Which service is affected? Which platform does that service log to? If it's a cascading failure across multiple services, the logs might be in two or three different platforms. The engineer either knows this from memory or they don't. If they don't, they're checking the wiki which may or may not be accurate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second problem is the query itself:&lt;/strong&gt; CloudWatch Logs Insights, LogQL, Elasticsearch's query DSL, GCP's logging query language each has its own syntax. The engineer is writing queries in a language they might use once a month, typo-checking field names, waiting for results, getting nothing, adjusting the time window, trying again. Middleware's research puts it bluntly: "only the engineer who built the logging setup actually knows how to query it."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The third problem is time ranges:&lt;/strong&gt; The alert fired at 2:47 PM but the actual problem might have started at 2:30. Or 2:00. The engineer picks a window and hopes. Too narrow and they miss the cause. Too wide and they're scrolling through thousands of irrelevant lines trying to spot the one that matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fourth problem and the one nobody talks about is that log search without context is basically guessing:&lt;/strong&gt; The engineer is typing "timeout" or "500 error" or "connection refused" into a search bar, hoping something relevant comes back. But the most useful log search happens when you already know what you're looking for. During an incident, you don't. That's the whole point you're using logs to figure out what happened. Without knowing which deploy changed what, which metric spiked when, and which alert correlates with which service, the search is unfocused.&lt;/p&gt;

&lt;p&gt;This is why log investigation takes 13–22 minutes during a typical incident not because the tools are slow, but because the human has to navigate platform fragmentation, query syntax, time window ambiguity, and lack of context simultaneously. Under pressure. While Slack is asking for updates.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hidden Cost: Duplicated Effort
&lt;/h2&gt;

&lt;p&gt;There's one more layer that makes this worse.&lt;/p&gt;

&lt;p&gt;During a multi-engineer incident, two or three people often search logs independently. Engineer A opens CloudWatch. Engineer B opens CloudWatch. They're running similar queries with slightly different parameters. Neither knows the other is looking.&lt;/p&gt;

&lt;p&gt;When someone finally finds the relevant log line, they paste it in Slack. The other engineers have already spent 5–10 minutes on redundant searches. Multiply that across the team and you've burned 15–20 minutes of collective engineering time on work that needed to happen once.&lt;/p&gt;

&lt;p&gt;This isn't a coordination failure. It's a tooling gap. If the log search happened once, automatically, with results delivered to everyone the duplication disappears entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Parallel Search With Context Looks Like
&lt;/h2&gt;

&lt;p&gt;Steadwing connects to six logging platforms: AWS CloudWatch, GCP Cloud Logging, Elasticsearch, Mezmo, Scalyr, and Grafana Loki.&lt;/p&gt;

&lt;p&gt;When an investigation triggers, it doesn't search them one at a time. It queries all connected platforms simultaneously using the alert timestamp from PagerDuty, the recent deploy data from GitHub, and the metric anomalies from Datadog to scope the search precisely.&lt;/p&gt;

&lt;p&gt;The engineer doesn't pick a platform. They don't write a query. They don't guess at a time range. The relevant log lines show up in the RCA with timestamps, context, and links back to the source platform correlated with deploy data, metric changes, error tracking from Sentry, and infrastructure events from Kubernetes.&lt;/p&gt;

&lt;p&gt;The 22-minute log hunt from the story at the top of this post? The log line was in CloudWatch at minute one. With parallel search and deploy context, Steadwing would have surfaced it in under 30 seconds already correlated with the deploy that caused it and the fix needed to resolve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Engineering Leaders
&lt;/h2&gt;

&lt;p&gt;The instinct when log investigation is slow is to consolidate platforms. One tool, one query language, one place to search. It makes sense in theory.&lt;/p&gt;

&lt;p&gt;In practice, platform consolidation is a 6–12 month project that touches every team's logging pipeline. Most organizations start it and never finish. And it doesn't help with the incidents happening between now and whenever the migration is done.&lt;/p&gt;

&lt;p&gt;The alternative: leave your logs where they are and make them searchable as one system during incidents. Steadwing connects to the platforms you already run, queries them in parallel, and delivers the results as part of a complete RCA alongside metrics, deploys, alerts, and infrastructure data.&lt;/p&gt;

&lt;p&gt;No migration. No agents. No code changes. Your logs stay where they are. They just become findable when it matters.&lt;br&gt;
Start free at &lt;a href="https://steadwing.com/" rel="noopener noreferrer"&gt;steadwing.com&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How does Steadwing search logs across multiple platforms?
&lt;/h3&gt;

&lt;p&gt;When an investigation triggers, Steadwing queries all connected logging platforms in parallel. It uses context from the alert (PagerDuty), recent deploys (GitHub/GitLab), and metric anomalies (Datadog) to automatically scope the search the right services, the right time window, the right error patterns. Results come back correlated with everything else in the RCA.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do we need to change our logging setup?
&lt;/h3&gt;

&lt;p&gt;No. Steadwing reads from your logging platforms as they are. Your logs stay in CloudWatch, Elasticsearch, Loki, or wherever they live. No changes to your ingestion pipeline, retention policies, or log format.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if different services log to different platforms?
&lt;/h3&gt;

&lt;p&gt;That's exactly the problem Steadwing is built for. It doesn't matter if checkout logs to CloudWatch and payments logs to Elasticsearch. When an incident involves both, Steadwing searches both simultaneously and correlates the results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which logging platforms are supported?
&lt;/h3&gt;

&lt;p&gt;AWS CloudWatch, GCP Cloud Logging, Elasticsearch, Mezmo (formerly LogDNA), Scalyr, and Grafana Loki. Full details at &lt;a href="https://docs.steadwing.com/integrations" rel="noopener noreferrer"&gt;docs.steadwing.com/integrations.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>sre</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Why Delivery Apps Are the Hardest to Test (And What It's Costing QA Teams)</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Fri, 05 Jun 2026 06:18:11 +0000</pubDate>
      <link>https://dev.to/drizzdev/why-delivery-apps-are-the-hardest-to-test-and-what-its-costing-qa-teams-27fi</link>
      <guid>https://dev.to/drizzdev/why-delivery-apps-are-the-hardest-to-test-and-what-its-costing-qa-teams-27fi</guid>
      <description>&lt;p&gt;India's largest food delivery platform processes over 1.5 million orders every single day. One missed bug during a Friday night dinner rush doesn't cost a support ticket. It costs thousands of failed orders, refund payouts, a ratings drop, and a trending hashtag you didn't want.&lt;/p&gt;

&lt;p&gt;Delivery apps sit at the intersection of everything that makes mobile testing hard: real-time GPS, live order tracking, payment processing, multi-sided marketplaces (customers, restaurants, delivery partners), surge pricing, dynamic UI personalization, push notifications, and all of it running on 3G networks in areas with spotty coverage.&lt;/p&gt;

&lt;p&gt;And yet, most QA teams test delivery apps the same way they test a to-do list app. Same tools. Same locator strategies. Same static test scripts that break the moment someone moves a banner.&lt;/p&gt;

&lt;p&gt;This guide breaks down why delivery apps are structurally the hardest category of mobile apps to test, what it's actually costing teams who don't adapt, and what changes when you test the way users actually experience the app visually.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Test Suite Maintenance and Why Does It Cost So Much?
&lt;/h2&gt;

&lt;p&gt;Test suite maintenance is the ongoing engineering effort required to keep automated tests passing after application changes that don't affect functionality. It includes updating broken element selectors, adjusting wait times, fixing synchronization failures, re-recording test flows after UI redesigns, and debugging false failures caused by environment changes.&lt;/p&gt;

&lt;p&gt;Test maintenance is expensive because it scales linearly with test count and release frequency. Doubling either your test suite or your release cadence roughly doubles your maintenance burden. Unlike test creation (a one-time cost per test), maintenance is a recurring cost that compounds over the life of every test.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is This Costing QA Teams?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Maintenance Trap
&lt;/h3&gt;

&lt;p&gt;QA teams at delivery companies routinely report spending 60-70% of their engineering time on test maintenance rather than test creation or bug discovery. The cause is structural: delivery app UIs change faster than selector-based tests can be updated.&lt;/p&gt;

&lt;p&gt;A typical cycle: the product team redesigns the restaurant listing card on Monday. By Tuesday, 30 tests that reference elements on that card are failing. None of the failures are real bugs. QA spends Wednesday and Thursday updating selectors. On Friday, a marketing campaign changes the home screen layout and 15 more tests break.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Coverage Gap
&lt;/h3&gt;

&lt;p&gt;Because maintenance consumes most QA capacity, test coverage plateaus. Teams can't write new tests for new features because they're too busy fixing old tests for unchanged functionality. The result: the newest, most-frequently-changed parts of the app the parts most likely to contain bugs have the least test coverage.&lt;/p&gt;

&lt;h3&gt;
  
  
  The False Confidence Problem
&lt;/h3&gt;

&lt;p&gt;A green test suite that's actually testing yesterday's UI gives teams false confidence. Tests pass because they're verifying elements that no longer reflect what users see. The checkout flow test passes, but the actual checkout screen has a new payment method that's completely untested.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Staffing Spiral
&lt;/h3&gt;

&lt;p&gt;When test maintenance overwhelms the team, the response is usually to hire more QA engineers. But new engineers inherit the same maintenance burden. Within months, they're spending 60-70% of their time on maintenance too. The problem scales with headcount because the root cause selector fragility is architectural.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Do Most Teams Currently Test Delivery Apps?
&lt;/h2&gt;

&lt;p&gt;The standard approach combines multiple tools and techniques:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Appium&lt;/strong&gt; for E2E flow automation: login, browse restaurants, add to cart, checkout, track order. Appium handles native UI elements but depends on selectors (XPath, accessibility IDs, resource IDs) that break with every UI change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API testing&lt;/strong&gt; (Postman, RestAssured) for backend validation: order creation, payment processing, restaurant availability, delivery assignment. API tests are more stable than UI tests but don't catch visual bugs or front-end integration issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual testing&lt;/strong&gt; for visual verification, new features, and edge cases. Manual testing catches what automation misses but doesn't scale to cover 1.5 million daily order permutations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud device farms&lt;/strong&gt; (BrowserStack, Sauce Labs) for device compatibility. Run the same tests across 20-50 device models to catch device-specific rendering and performance issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network simulation&lt;/strong&gt; tools (Charles Proxy, Network Link Conditioner) for connectivity testing. Simulate 3G, packet loss, and connection drops during critical flows.&lt;/p&gt;

&lt;p&gt;This stack works, but the maintenance cost of the Appium layer, which is the broadest automation layer is where teams lose the most time.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Changes with Vision AI Testing?
&lt;/h2&gt;

&lt;p&gt;Vision AI testing (Drizz) addresses the structural cause of delivery app test maintenance: the coupling between tests and internal UI element identifiers.&lt;/p&gt;

&lt;p&gt;Instead of finding a "restaurant card" by its resource ID (which changes when the card is redesigned), Vision AI looks at the screen and identifies the restaurant card visually by its image, name text, rating stars, and delivery time estimate. The same way a user sees it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Example: Testing a D2C Meat Delivery App with Drizz
&lt;/h3&gt;

&lt;p&gt;To see this in action, watch Drizz testing the Licious app India's leading D2C meat and seafood delivery platform. &lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Lei4fvGqgtQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The demo shows Drizz automating a complete order flow on the Licious app: browsing categories, selecting products, adding items to cart, applying coupons, and validating the checkout screen all in plain English, without a single selector or XPath.&lt;/p&gt;

&lt;p&gt;What makes this demo compelling is that Licious has exactly the type of UI that breaks selector-based tools: dynamic product listings that change based on availability and location, personalized recommendations, promotional banners, and a complex checkout with multiple payment options. The Vision AI test navigates all of it visually, the same way a customer would tapping on what it sees on screen rather than querying an element tree underneath.&lt;/p&gt;

&lt;p&gt;If a product image changes, the category layout shifts, or the checkout UI gets redesigned, the Drizz test keeps passing because the screen still shows a product card, an "Add to Cart" button, and an order summary. The visual content persists even when every internal identifier changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What This Solves for Delivery Apps Specifically
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Dynamic home screens:&lt;/strong&gt; The personalized, always-changing home screen is testable because Vision AI evaluates what's visually present, not what element IDs exist. Banners rotate? AI sees the current banner. Promotions change? AI reads the current promotion text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-app flow validation:&lt;/strong&gt; "Place an order on customer app, verify it appears on restaurant app" works through visual identification on both apps. No shared element IDs needed across apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment flow resilience:&lt;/strong&gt; "Tap UPI, verify payment screen, confirm order" works regardless of which payment provider's UI renders, because Vision AI identifies the payment confirmation visually rather than through provider-specific element trees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Post-redesign stability:&lt;/strong&gt; When the product team redesigns the checkout screen, Vision AI tests keep passing because the screen still shows a cart summary, item list, payment button, and total amount even though every element ID underneath has changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network condition testing:&lt;/strong&gt; Vision AI validates what the user actually sees during poor connectivity: loading spinners, error messages, retry prompts, cached content. Not what the element tree reports, but what's rendered on screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Vision AI Doesn't Replace
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;API testing:&lt;/strong&gt; Backend validation of order logic, payment processing, and delivery assignment still requires API-level testing. Vision AI tests the front-end experience, not the backend logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance profiling:&lt;/strong&gt; Load testing for 1.5 million concurrent orders, API response times, and database performance require dedicated performance tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Network simulation:&lt;/strong&gt; Vision AI doesn't simulate network conditions you still need Charles Proxy or similar tools. But Vision AI validates the visual result of poor network conditions.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is the Recommended Testing Stack for Delivery Apps in 2026?
&lt;/h2&gt;

&lt;p&gt;The most effective delivery app testing strategy layers multiple approaches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 1  Vision AI smoke tests (Drizz):&lt;/strong&gt; Run on every build across 10+ devices. "Open app, verify home screen loads, search restaurant, add item, go to checkout, verify cart total." Catches UI regressions, broken screens, and rendering issues automatically. Survives UI redesigns without maintenance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 2  API regression tests (Postman/RestAssured):&lt;/strong&gt; Run on every PR. Validate order creation, payment processing, restaurant availability, delivery assignment, and coupon logic at the API level. The most stable layer is not affected by UI changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 3 Vision AI full flow regression (Drizz):&lt;/strong&gt; Run nightly. Complete order flows across customer, restaurant, and delivery partner apps. Payment method permutations. Coupon application. Rating and review submission.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 4 Network condition testing:&lt;/strong&gt; Run weekly. Simulate 3G, packet loss, and connection drops during order placement, payment, and tracking. Validate graceful degradation visually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer 5 Manual exploratory testing:&lt;/strong&gt; Run before major releases. New feature flows, edge cases, competitive comparison, UX evaluation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Many Test Cases Does a Typical Delivery App Need?
&lt;/h2&gt;

&lt;p&gt;A production delivery app typically maintains 300-500+ automated test cases covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;50-80 customer app flows (browse, search, order, payment, tracking, ratings, support)&lt;/li&gt;
&lt;li&gt;30-50 restaurant app flows (order management, menu updates, availability, analytics)&lt;/li&gt;
&lt;li&gt;20-40 delivery partner app flows (assignment, navigation, pickup, delivery confirmation)&lt;/li&gt;
&lt;li&gt;50-100 payment permutation tests (UPI, cards, wallets, split, COD, coupons)&lt;/li&gt;
&lt;li&gt;30-50 cross-app integration tests (order placed → restaurant receives → partner assigned)&lt;/li&gt;
&lt;li&gt;20-30 network resilience tests&lt;/li&gt;
&lt;li&gt;30-50 device compatibility tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At 300+ tests maintained with selector-based tools, the maintenance burden consumes 1.5-2.5 full-time QA engineers. With Vision AI, the same suite requires less than 0.3 FTEs on maintenance freeing 1.2-2.2 engineers for coverage expansion and bug discovery.&lt;/p&gt;

&lt;p&gt;The math is simple: delivery apps that ship weekly generate more selector breakages per sprint than any other app category. The teams that win are the ones that stop paying the maintenance tax and redirect that engineering capacity toward catching the bugs that actually affect the 1.5 million orders flowing through the system every day. The testing strategy that worked for apps shipping monthly doesn't survive contact with a weekly release cadence. The architecture has to change.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why are delivery apps harder to test than e-commerce apps?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Delivery apps add real-time coordination across three user types (customer, restaurant, delivery partner), GPS-dependent features, time-sensitive availability, and network resilience requirements that standard e-commerce apps do not have. An e-commerce app has a static product catalog; a delivery app has a dynamic, location-and-time-dependent menu that changes every hour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the biggest QA challenge for food delivery apps?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The biggest QA challenge is test maintenance caused by rapid UI iteration. Delivery apps in competitive markets (India, Southeast Asia, Middle East) ship UI changes weekly. Each change breaks selector-based tests, consuming 60–70% of QA time on maintenance rather than on bug discovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can Appium test delivery apps effectively?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Appium can automate delivery app flows (login, browse, order, checkout) but depends on element selectors that break with every UI update. For delivery apps with weekly UI changes, Appium's maintenance cost becomes unsustainable at 200+ tests. Appium works best for stable flows combined with Vision AI (Drizz) for frequently-changing screens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does Vision AI handle the constantly changing home screen?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vision AI evaluates what is visually present on screen rather than querying element IDs. When banners rotate, promotions change, or restaurant recommendations update, Vision AI reads the current visual state. A test that says "verify a restaurant card with a rating and delivery time is visible" passes, regardless of which restaurant is displayed or how the card is styled.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What tools does India's largest food delivery platform use for testing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Large-scale food delivery platforms typically use a combination of Appium (UI automation), API testing frameworks (RestAssured, Postman), cloud device farms (BrowserStack, AWS Device Farm), performance testing tools (JMeter, Gatling), and network simulation tools (Charles Proxy). Increasingly, Vision AI platforms like Drizz are being adopted to reduce the maintenance burden of selector-based UI automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many devices should delivery apps be tested on?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Delivery apps should be tested on 30-50 devices covering the range of Android manufacturers (Samsung, Xiaomi, Realme, OnePlus, Vivo, Oppo), chipsets (Snapdragon, MediaTek), RAM tiers (3GB to 8GB+), and Android versions (12-15) that represent the actual user base. Include 2-3 low-end devices (2-3GB RAM) since delivery partners frequently use budget Android phones. iOS testing should cover iPhone 12 through current generation.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to Automate Mobile App Testing Without Writing a Single Line of Code</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Fri, 29 May 2026 08:09:23 +0000</pubDate>
      <link>https://dev.to/drizzdev/how-to-automate-mobile-app-testing-without-writing-a-single-line-of-code-5d17</link>
      <guid>https://dev.to/drizzdev/how-to-automate-mobile-app-testing-without-writing-a-single-line-of-code-5d17</guid>
      <description>&lt;p&gt;You don't need to be a developer to automate your mobile app testing. Not in 2026.&lt;/p&gt;

&lt;p&gt;For years, automated testing was gated behind programming skills. If you wanted to automate a login flow, you needed to write Python or Java, configure Appium, learn XPath, and debug flaky selectors. If your job title was "Manual QA Tester" or "Product Manager" or "QA Lead without a coding background", automation was something your engineering team did not something you could touch.&lt;/p&gt;

&lt;p&gt;That's changed. A new generation of no-code testing tools has made it possible for anyone who can describe a user flow in plain language to automate it. No scripts. No selectors. No environment variables.&lt;/p&gt;

&lt;p&gt;This guide walks you through exactly how to automate mobile app testing without coding what's possible, how it works, the different approaches available, and a complete step-by-step walkthrough using Drizz's Vision AI platform, with links to the official documentation so you can follow along.&lt;/p&gt;

&lt;p&gt;If you're new to mobile testing in general, our &lt;a href="https://www.drizz.dev/post/best-mobile-test-automation-frameworks-2026-when-to-choose-drizz" rel="noopener noreferrer"&gt;Best Mobile Test Automation Frameworks (2026)&lt;/a&gt; guide provides the broader landscape.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No-code mobile testing lets QA testers, PMs, and non-developers create and maintain automated test suites without writing scripts.&lt;/li&gt;
&lt;li&gt;Three approaches dominate the space: record-and-replay, visual flow builders, and plain English / &lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Record-and-replay tools are easiest to start but break frequently and create heavy maintenance burdens.&lt;/li&gt;
&lt;li&gt;Visual flow builders offer more control but still depend on element selectors under the surface.&lt;/li&gt;
&lt;li&gt;Plain English + &lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI&lt;/a&gt; (Drizz) is the most resilient approach tests describe what you see on screen, and the AI identifies elements visually without selectors. Read our deep dive on how Vision Language Models power this technology.&lt;/li&gt;
&lt;li&gt;Drizz consists of two components: &lt;a href="https://docs.drizz.dev/getting-started/drizz-desktop-app?_gl=1*xe7gsq*_gcl_au*MTI3MzI4MzUzMC4xNzc1NzE5MTg5*_ga*MTk1ODgyOTcxMy4xNzY5MzE4MTM1*_ga_ZTWW6LF0G6*czE3ODAwMzc0OTgkbzE2MiRnMSR0MTc4MDAzNzk5OSRqMTkkbDAkaDEyODQ1NTY5NTQkZGJ5a3g4UGR2WmViVVdxT0szSXZDcmhjQ1NpMHBYclctSXc." rel="noopener noreferrer"&gt;Drizz Desktop&lt;/a&gt; for local test creation and validation, and &lt;a href="https://www.drizz.dev/cloud-app" rel="noopener noreferrer"&gt;Drizz Cloud&lt;/a&gt; for scaled execution, reporting, and CI/CD integration.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Automation Felt Impossible (Until Now)
&lt;/h2&gt;

&lt;p&gt;Traditional mobile test automation was built by developers, for developers. A typical Appium test requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A programming language&lt;/strong&gt; Java, Python, JavaScript, or Ruby&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A test framework&lt;/strong&gt; JUnit, pytest, Mocha, or similar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An automation server&lt;/strong&gt; Appium, installed via npm, configured with environment variables&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform SDKs&lt;/strong&gt; Android SDK, Xcode, JDK&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Element locators&lt;/strong&gt; XPath, accessibility IDs, resource IDs copied from &lt;a href="https://www.drizz.dev/post/using-appium-inspector-full-guide-why-drizz-doesnt-need-it" rel="noopener noreferrer"&gt;Appium Inspector&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Synchronization logic&lt;/strong&gt; explicit waits to handle loading states, animations, and async behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an experienced developer, this takes half a day to set up and weeks to become productive with. For someone without coding experience, it's a wall.&lt;/p&gt;

&lt;p&gt;This meant that in most organizations, automation was bottlenecked by engineering capacity. Manual testers who often have the deepest product knowledge and the sharpest eye for UX issues couldn't contribute to the automation suite. Their expertise stayed locked in spreadsheets and manual test runs.&lt;/p&gt;

&lt;p&gt;No-code tools remove that wall. If you know your app well enough to describe what a user does ("tap Login, enter email, tap Submit, verify dashboard"), you can automate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Approaches to No-Code Mobile Testing
&lt;/h2&gt;

&lt;p&gt;Not all no-code tools work the same way. Understanding the differences helps you pick the right one.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Record and Replay
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; You interact with your app on a device or emulator while the tool records your actions taps, swipes, text input. It converts those actions into a replayable test script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt; Katalon Recorder, Ranorex, some features of BrowserStack and Perfecto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fastest way to create your first test literally just use the app&lt;/li&gt;
&lt;li&gt;No learning curve for the initial recording&lt;/li&gt;
&lt;li&gt;Good for quick smoke tests and demos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extremely fragile. Recordings capture exact coordinates, element positions, and timing. Any UI change breaks the recording.&lt;/li&gt;
&lt;li&gt;Hard to maintain. When your app updates, you re-record from scratch rather than editing a specific step.&lt;/li&gt;
&lt;li&gt;Limited logic. Conditional flows, data-driven testing, and dynamic content handling are difficult or impossible.&lt;/li&gt;
&lt;li&gt;The "easy to create, impossible to maintain" trap: teams build 50 recorded tests, then spend all their time re-recording them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Quick one off validations and proof of concept demos. Not for production regression suites.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Visual Flow Builders
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; You build tests using a drag-and-drop interface or visual editor. Each step is a block "Tap element," "Enter text," "Assert visible" that you configure by selecting elements from the screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt; ACCELQ, Leapwork, Sofy, TestGrid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More structured than record-and-replay tests are editable at the step level&lt;/li&gt;
&lt;li&gt;Reusable components and modular test design&lt;/li&gt;
&lt;li&gt;Some tools include AI-powered element healing that adapts when selectors change&lt;/li&gt;
&lt;li&gt;Better suited for regression suites than raw recordings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Still depends on element identifiers under the surface. The visual builder is a UI layer on top of selectors when elements change significantly, tests still break.&lt;/li&gt;
&lt;li&gt;Learning curve for the platform's specific UI and workflow&lt;/li&gt;
&lt;li&gt;Vendor lock-in: your tests live inside the tool's proprietary format&lt;/li&gt;
&lt;li&gt;Enterprise pricing can be steep for teams just getting started&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Mid-size QA teams with some technical depth who want a structured but low-code approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Plain English + Vision AI
&lt;/h2&gt;

&lt;p&gt;How it works: You write test steps in plain English "tap the Login button," "type &lt;a href="mailto:user@example.com"&gt;user@example.com&lt;/a&gt; into the email field," "verify the dashboard is visible." The AI identifies elements visually on the rendered screen, the same way a human looks at a phone.&lt;/p&gt;

&lt;p&gt;Example: &lt;a href="//drizz.dev"&gt;Drizz&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Truly no-code if you can describe a user flow, you can automate it&lt;/li&gt;
&lt;li&gt;No element selectors, no XPath, no accessibility IDs required&lt;/li&gt;
&lt;li&gt;Tests survive UI changes because they reference what's visible on screen, not internal element structures&lt;/li&gt;
&lt;li&gt;Works on release builds test the actual app your users download&lt;/li&gt;
&lt;li&gt;Cross-platform same test works on Android and iOS (&lt;a href="https://docs.drizz.dev/getting-started/overview/supported-platforms" rel="noopener noreferrer"&gt;Supported Platforms&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Near-zero maintenance the Vision AI adapts to visual changes automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Newer category smaller ecosystem than established record and replay tools&lt;/li&gt;
&lt;li&gt;For apps with minimal text and many similar looking icons, visual identification has less to differentiate&lt;/li&gt;
&lt;li&gt;Less granular device level control than coded frameworks for specialized use cases (see &lt;a href="https://docs.drizz.dev/getting-started/overview/drizz-usage-expectations-and-operational-guidelines" rel="noopener noreferrer"&gt;Drizz Usage Expectations&lt;/a&gt; for details on what Drizz handles)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams where non-developers need to create and maintain tests, UIs change frequently, and long-term maintenance cost matters more than initial setup speed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Drizz: Two Components, One Platform
&lt;/h2&gt;

&lt;p&gt;Before diving into the walkthrough, it's helpful to understand how Drizz is structured. The &lt;a href="https://docs.drizz.dev/getting-started/overview/product-components" rel="noopener noreferrer"&gt;Product Components&lt;/a&gt; documentation explains the full architecture, but here's the summary:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step: Automating Your First Test Without Code
&lt;/h3&gt;

&lt;p&gt;Here's a practical walkthrough using Drizz. We'll automate a login flow the most common first test for any mobile app. Each step references the relevant documentation page so you can go deeper.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Set Up Drizz Desktop (5 minutes)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Download Drizz Desktop from &lt;a href="//drizz.dev/start"&gt;drizz.dev/start&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Connect your device USB (real device), Android emulator, or iOS simulator. Drizz surfaces platform and state details automatically. See &lt;a href="https://docs.drizz.dev/getting-started/overview/supported-platforms" rel="noopener noreferrer"&gt;Supported Platforms&lt;/a&gt; for the full list of supported device types.&lt;/li&gt;
&lt;li&gt;Upload your app build (APK or IPA)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. No Node.js. No JDK. No SDK configuration. No environment variables. The &lt;a href="https://docs.drizz.dev/getting-started/drizz-desktop-app?_gl=1*1vtdabj*_gcl_au*MTI3MzI4MzUzMC4xNzc1NzE5MTg5*_ga*MTk1ODgyOTcxMy4xNzY5MzE4MTM1*_ga_ZTWW6LF0G6*czE3ODAwMzc0OTgkbzE2MiRnMSR0MTc4MDAzODg4NyRqNjAkbDAkaDEyODQ1NTY5NTQkZGJ5a3g4UGR2WmViVVdxT0szSXZDcmhjQ1NpMHBYclctSXc." rel="noopener noreferrer"&gt;Drizz Desktop App&lt;/a&gt; documentation covers the complete setup process.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Understand the Command System
&lt;/h4&gt;

&lt;p&gt;Drizz tests are built from structured commands each step describes one user action or verification. The full list is available in the Commands Reference, but the most common ones for getting started are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tap Tap on an element identified by its visible text or description&lt;/li&gt;
&lt;li&gt;Type / Enter Text - Input text into a field&lt;/li&gt;
&lt;li&gt;Verify / Assert Check that something is visible on screen&lt;/li&gt;
&lt;li&gt;Swipe / Scroll - Navigate through scrollable content&lt;/li&gt;
&lt;li&gt;Wait Pause for a specific condition or duration&lt;/li&gt;
&lt;li&gt;Launch App  Start or restart the application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Commands support conditional logic and reusable modules for more complex scenarios. See What You Can Automate for the full scope of supported interactions.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Write Your Test Plan
&lt;/h4&gt;

&lt;p&gt;A &lt;a href="https://docs.drizz.dev/test-plan" rel="noopener noreferrer"&gt;Test Plan&lt;/a&gt; in Drizz is an ordered sequence of commands that describes a user flow. Open a new test plan and describe the login flow:&lt;/p&gt;

&lt;p&gt;Each step describes exactly what a user would do and see. The Vision AI engine interprets the rendered screen to find and interact with the described elements.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 4: Run the Test Locally
&lt;/h4&gt;

&lt;p&gt;Click Run in Drizz Desktop. The Vision AI will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch your app on the connected device&lt;/li&gt;
&lt;li&gt;Look at the screen and find the "Login" button visually&lt;/li&gt;
&lt;li&gt;Tap it&lt;/li&gt;
&lt;li&gt;Find the email field by visual context, type the text&lt;/li&gt;
&lt;li&gt;Find the password field, type the text&lt;/li&gt;
&lt;li&gt;Find the "Sign In" button, tap it&lt;/li&gt;
&lt;li&gt;Verify "Welcome" text appears on screen&lt;/li&gt;
&lt;li&gt;Verify the dashboard screen loaded&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can watch each step execute in real time on the device. Drizz provides immediate visibility into execution flow, outcomes, and on-device behavior.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 5: Review Results and Debug Failures
&lt;/h4&gt;

&lt;p&gt;When a test passes, you see step-by-step results with screenshots showing exactly what happened at each step.&lt;/p&gt;

&lt;p&gt;When a step fails, Drizz generates &lt;strong&gt;AI-based failure reasoning&lt;/strong&gt; explaining what was expected, what was observed, and why execution failed. Visual highlights and device logs are included automatically. This is covered in detail in the &lt;a href="https://docs.drizz.dev/drizz-api-integration/common-issues" rel="noopener noreferrer"&gt;Common Issues&lt;/a&gt; documentation.&lt;/p&gt;

&lt;p&gt;No digging through raw logs. The failure explanation tells you whether the issue is a real bug or a test configuration problem.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 6: Scale to Your Full Test Suite
&lt;/h4&gt;

&lt;p&gt;Once your login test works, build out your critical flows:&lt;/p&gt;

&lt;p&gt;Onboarding / sign-up&lt;br&gt;
Search and browse&lt;br&gt;
Add to cart / checkout&lt;br&gt;
Profile editing&lt;br&gt;
Settings and permissions&lt;br&gt;
Push notification handling&lt;br&gt;
Multi-app journeys (deep links, OTP flows)&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.drizz.dev/different-use-cases-supported-by-drizz?_gl=1*jbchoq*_gcl_au*MTI3MzI4MzUzMC4xNzc1NzE5MTg5*_ga*MTk1ODgyOTcxMy4xNzY5MzE4MTM1*_ga_ZTWW6LF0G6*czE3ODAwMzc0OTgkbzE2MiRnMSR0MTc4MDAzOTE1NiRqNjAkbDAkaDEyODQ1NTY5NTQkZGJ5a3g4UGR2WmViVVdxT0szSXZDcmhjQ1NpMHBYclctSXc." rel="noopener noreferrer"&gt;Different Use Cases Supported&lt;/a&gt; by Drizz documentation covers the full range of scenarios you can automate, including multi-app workflows, API validation integrated into UI flows, and variable network conditions.&lt;/p&gt;

&lt;p&gt;For test authoring &lt;a href="https://docs.drizz.dev/drizz-api-integration/best-practices" rel="noopener noreferrer"&gt;best practices&lt;/a&gt; naming conventions, modular structure, reusable flows, and conditional logic see the Best Practices guide.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 7: Move to CI/CD with Drizz Cloud
&lt;/h4&gt;

&lt;p&gt;Once your tests are validated locally, move them to Drizz Cloud for automated execution in your CI/CD pipeline.&lt;/p&gt;

&lt;p&gt;The CI/CD Platform Integration documentation covers setup for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Actions trigger test runs on every PR or push&lt;/li&gt;
&lt;li&gt;Jenkins integrate with existing Jenkins pipelines&lt;/li&gt;
&lt;li&gt;Bitrise native mobile CI integration&lt;/li&gt;
&lt;li&gt;GitLab CI, Azure DevOps and other platforms via Drizz's API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For API-based integration, the Drizz API Integration docs walk through the full lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication secure token-based access&lt;/li&gt;
&lt;li&gt;Upload push app builds programmatically&lt;/li&gt;
&lt;li&gt;Trigger Run execute test plans via API&lt;/li&gt;
&lt;li&gt;Error Codes handle responses and failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cloud devices are provisioned fresh for every run, ensuring no residual state impacts results. Parallel execution distributes test plans across available device slots automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  How This Compares to Traditional Automation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnv7k21xp0upggmvbsid6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnv7k21xp0upggmvbsid6.png" alt=" " width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Concerns (And Honest Answers)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "Can no-code testing handle complex scenarios?"
&lt;/h3&gt;

&lt;p&gt;It depends on the approach. Record-and-replay tools struggle with anything beyond linear flows. Visual flow builders handle moderate complexity. Drizz supports conditional logic, reusable modules, and multi-step branching enough for the vast majority of E2E regression scenarios. The Drizz documentation covers the full scope of what you can automate, including multi-app journeys, API calls integrated into UI flows, and handling dynamic pop-ups and overlays.&lt;/p&gt;

&lt;p&gt;For extremely specialized use cases (biometric testing, sensor data, low-level OS APIs), coded frameworks still offer deeper control. The Drizz documentation is transparent about what Drizz handles and what falls outside its scope.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Will my tests be as reliable as coded tests?"
&lt;/h3&gt;

&lt;p&gt;Vision AI tests are typically more reliable than coded tests at scale because they don't depend on selectors that break with every UI change. Drizz reports 97%+ test accuracy in production and 95%+ test stability, compared to 70-80% for typical Appium suites. The maintenance difference compounds over time - coded suites get flakier as they grow; visual suites stay stable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is no-code testing a precursor to 'real' automation?
&lt;/h3&gt;

&lt;p&gt;It can be, but it doesn't have to be. Some teams use no code as an entry point and later add coded tests for specialized scenarios. Others use Drizz as their primary automation platform indefinitely because the maintenance math favors it at any scale. The choice depends on your team's needs, not on a hierarchy of "real" vs "not real" automation.&lt;/p&gt;

&lt;h3&gt;
  
  
  "What about CI/CD integration?"
&lt;/h3&gt;

&lt;p&gt;Drizz integrates natively with GitHub Actions, Jenkins, Bitrise, GitLab CI, and Azure DevOps. Tests run automatically on every build, PR, or scheduled interval. The Drizz documentation provides setup guides for each CI/CD platform, and the API integration docs allow fully programmatic control over uploads, test triggers, and result retrieval.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Can I version-control my tests?"
&lt;/h3&gt;

&lt;p&gt;Yes. Drizz test files are simple text-based instructions that commit cleanly into Git repositories. Engineers can branch, diff, and review test logic just like application code. This is a significant advantage over visual flow builders where tests live in proprietary formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  "What happens when a test fails?"
&lt;/h3&gt;

&lt;p&gt;Drizz provides AI-based failure reasoning for every failure explaining what was expected, what was observed, and why execution failed. Step-level screenshots, visual highlights, and device logs are included automatically. For Cloud runs, execution metadata, logs, and audit trails are preserved in a structured format for traceability across releases. See the Drizz documentation for debugging guidance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;This approach works best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manual QA testers who want to automate without learning Python or Java&lt;/li&gt;
&lt;li&gt;QA leads who need to scale automation without hiring more developers&lt;/li&gt;
&lt;li&gt;Product managers who want to define and validate test scenarios using product language&lt;/li&gt;
&lt;li&gt;Startup teams where one person wears multiple hats and can't spend weeks learning Appium&lt;/li&gt;
&lt;li&gt;Enterprise QA teams where the 60% maintenance tax of selector-based automation has become unsustainable&lt;/li&gt;
&lt;li&gt;Flutter, React Native, and cross-platform teams where traditional selector-based tools are structurally more fragile due to custom rendering engines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these describe your situation, you can have your first automated test running in under 15 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drizz Documentation Reference
&lt;/h2&gt;

&lt;p&gt;For quick access to the docs referenced throughout this guide:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffd35fhl8gthwsa0p769s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffd35fhl8gthwsa0p769s.png" alt=" " width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Download Drizz Desktop&lt;/strong&gt; from &lt;a href="//drizz.dev/start"&gt;drizz.dev/start&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect your device&lt;/strong&gt; USB, emulator, or simulator&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload your app&lt;/strong&gt; no SDK changes, no code modifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write your first test in plain English&lt;/strong&gt; using the &lt;a href="https://docs.drizz.dev/commands-reference" rel="noopener noreferrer"&gt;Commands Reference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run it locally&lt;/strong&gt; and review results with AI-powered failure reasoning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move to CI/CD using&lt;/strong&gt; the &lt;a href="https://docs.drizz.dev/drizz-api-integration/ci-cd-platform-integration" rel="noopener noreferrer"&gt;CI/CD Integration&lt;/a&gt; guide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your 20 most critical test cases can be automated in a day without writing a single line of code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.drizz.dev/book-a-demo" rel="noopener noreferrer"&gt;Get started with Drizz&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do I need any technical background to use Drizz?
&lt;/h3&gt;

&lt;p&gt;No. If you can describe what a user does in your app ("tap Login, enter email, tap Submit"), you can write automated tests. The &lt;a href="https://docs.drizz.dev/getting-started/overview/core-concepts" rel="noopener noreferrer"&gt;Core Concepts&lt;/a&gt; documentation explains the foundational ideas in plain language. Familiarity with your app's user flows is more important than any technical skill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can no-code tests run on real devices?
&lt;/h3&gt;

&lt;p&gt;Yes. Drizz supports real devices (via USB), Android emulators, and iOS simulators. &lt;a href="https://www.drizz.dev/cloud-app" rel="noopener noreferrer"&gt;Drizz Cloud&lt;/a&gt; provides additional real device infrastructure with clean provisioning per run for parallel execution at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do no-code tests handle app updates?
&lt;/h3&gt;

&lt;p&gt;This is where approach matters. Record-and-replay tests usually break on any update. Visual flow builders partially self-heal. Drizz's Vision AI adapts automatically because it identifies elements visually if the button still says "Login" on screen, the test still works regardless of what changed under the hood. Tests that repair themselves is a core capability of the platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use Drizz alongside coded frameworks?
&lt;/h3&gt;

&lt;p&gt;Absolutely. Many teams use Drizz for broad regression coverage (written by QA testers and PMs) alongside Detox or Espresso for unit-level UI tests (written by developers). The two approaches complement each other no code handles breadth, coded handles depth. See our &lt;a href="https://www.drizz.dev/post/detox-vs-appium-vs-drizz-the-react-native-testing-showdown-2026" rel="noopener noreferrer"&gt;Detox vs Appium vs Drizz&lt;/a&gt; comparison for how teams layer these approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  What types of mobile apps can be tested?
&lt;/h3&gt;

&lt;p&gt;Drizz supports native Android, native iOS, React Native, Flutter, hybrid (WebView), and mobile web apps. See Supported Platforms for the complete list. Because Vision AI identifies elements on the rendered screen rather than through framework-specific APIs, it works regardless of how your app is built.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where can I find the full documentation?
&lt;/h3&gt;

&lt;p&gt;The complete Drizz documentation is available at &lt;a href="//docs.drizz.dev"&gt;docs.drizz.dev&lt;/a&gt;. Start with the &lt;a href="https://docs.drizz.dev/?_gl=1*wad1kg*_gcl_au*MTI3MzI4MzUzMC4xNzc1NzE5MTg5*_ga*MTk1ODgyOTcxMy4xNzY5MzE4MTM1*_ga_ZTWW6LF0G6*czE3ODAwMzc0OTgkbzE2MiRnMSR0MTc4MDA0MTkyNCRqMjkkbDAkaDEyODQ1NTY5NTQkZGJ5a3g4UGR2WmViVVdxT0szSXZDcmhjQ1NpMHBYclctSXc." rel="noopener noreferrer"&gt;Overview&lt;/a&gt; and work through the Getting Started section.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Mobile Visual Regression Testing in 2026: Why Vision AI Catches What Script-Based Tools Miss</title>
      <dc:creator>Jay Saadana</dc:creator>
      <pubDate>Fri, 15 May 2026 08:26:13 +0000</pubDate>
      <link>https://dev.to/drizzdev/mobile-visual-regression-testing-in-2026-why-vision-ai-catches-what-script-based-tools-miss-2bfm</link>
      <guid>https://dev.to/drizzdev/mobile-visual-regression-testing-in-2026-why-vision-ai-catches-what-script-based-tools-miss-2bfm</guid>
      <description>&lt;p&gt;Your functional tests pass. Your unit tests pass. Your E2E suite is green.&lt;/p&gt;

&lt;p&gt;And then a user reports that the checkout button is invisible on the Galaxy S24. The login form overlaps the keyboard on iPhone 15. The navigation bar is the wrong colour after the last merge.&lt;/p&gt;

&lt;p&gt;This isn't a testing failure. It's a testing blind spot. Functional tests verify that things work. They don't verify that things look right. A button can be fully functional clickable, wired to the correct handler, returning the right response while being completely invisible to the user because a CSS change pushed it off screen.&lt;/p&gt;

&lt;p&gt;Visual regression testing exists to close this gap. But in mobile, the problem is harder than on web - and most tools weren't built for it.&lt;/p&gt;

&lt;p&gt;This guide covers how visual regression testing works on mobile in 2026, why traditional screenshot-diffing tools generate more noise than signal, and how vision AI approaches the problem differently by understanding what's on screen rather than comparing pixels.&lt;/p&gt;

&lt;p&gt;If you're new to mobile testing frameworks in general, our Best &lt;a href="https://www.drizz.dev/post/best-mobile-test-automation-frameworks-2026-when-to-choose-drizz" rel="noopener noreferrer"&gt;Mobile Test Automation Frameworks (2026)&lt;/a&gt; guide provides the broader landscape.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Visual regression testing catches UI bugs that functional tests are structurally blind to: layout shifts, colour changes, overlapping elements, misaligned text, and rendering issues across devices.&lt;/li&gt;
&lt;li&gt;Traditional visual regression tools (Percy, Applitools, and BackstopJS) rely on screenshot comparison capturing baseline images and diffing against new builds pixel by pixel or with perceptual algorithms.&lt;/li&gt;
&lt;li&gt;On mobile, screenshot diffing generates excessive false positives from device fragmentation, dynamic content, OS-level rendering differences, and animation timing eroding team trust in results.&lt;/li&gt;
&lt;li&gt;Script-based testing tools (Appium, Espresso, and XCUITest) verify element presence and function but cannot detect visual bugs at all a misaligned button passes every functional assertion.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/drizzdev/vision-language-models-in-mobile-app-testing-4a6f"&gt;Vision AI &lt;/a&gt;(Drizz) combines functional testing with built-in visual understanding, seeing the screen like a human and catching visual regressions as part of every test run without maintaining separate visual baselines.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Visual Regression Testing Actually Catches
&lt;/h2&gt;

&lt;p&gt;Visual regression testing is the practice of verifying that your app's user interface looks correct after a code change not just that it functions correctly. While functional tests check that a button clicks and a form submits, visual regression testing checks that the button is visible, properly aligned, the right colour, and not overlapping anything else on screen. It's the difference between "Does this work?" and "Does this look right to a real user?"&lt;/p&gt;

&lt;p&gt;Before comparing tools, it helps to understand what visual bugs look like in practice. These are real categories of issues that ship to production regularly because functional tests can't see them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layout shifts.&lt;/strong&gt; A component moves 20px to the right after a library update changes the default padding on a container. Every functional test passes because the element is still tappable and still returns the correct data. But the UI looks broken to every user on every device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overlapping elements.&lt;/strong&gt; A text label expands after localisation into German (notoriously longer strings) and now overlaps the adjacent button. Functionally, both elements work. Visually, the screen is unusable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Colour and styling regressions.&lt;/strong&gt; A theme variable changes from #1A1A1A to #1A1A1B imperceptibly. But if another changes from #FFFFFF to #000000, the entire background flips. No functional test checks the background colour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Font rendering issues.&lt;/strong&gt; A custom font fails to load on certain Android devices, falling back to a system font with different metrics. Text wraps differently, buttons resize, and the layout breaks but only on those specific devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Device-specific rendering.&lt;/strong&gt; A screen that looks perfect on a Pixel 8 has a notch cutout hiding the status bar on a Samsung Galaxy Fold. Safe area insets vary across hundreds of device models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dark mode mismatches.&lt;/strong&gt; A new component renders correctly in light mode but shows white text on a white background in dark mode. If your E2E tests only run in light mode, this ships to every dark mode user.&lt;/p&gt;

&lt;p&gt;These bugs are invisible to Appium, Espresso, XCUITest, Detox, Maestro, and every other script-based testing tool. They verify that elements exist and function. They cannot verify that elements look correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Traditional Visual Regression Tools Work
&lt;/h2&gt;

&lt;p&gt;The established approach to visual regression testing follows a three-step loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Capture.&lt;/strong&gt; Take a screenshot of the app in a known-good state. This becomes the baseline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compare.&lt;/strong&gt; After a code change, take a new screenshot of the same screen. Diff it against the baseline using one of three methods:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pixel-by-pixel comparison&lt;/strong&gt; flags any pixel that changed.  Extremely sensitive but generates massive false positives from anti-aliasing, sub-pixel rendering, and font smoothing differences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perceptual diffing&lt;/strong&gt; uses algorithms that model human visual perception to ignore insignificant changes. Better than pixel-level but still struggles with dynamic content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered diffing&lt;/strong&gt; uses computer vision to understand layout semantics (Applitools Eyes, Percy's AI review). This is the most sophisticated approach, but it is still fundamentally dependent on the baseline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3.&lt;strong&gt;Review.&lt;/strong&gt; Present the differences to a human reviewer who decides whether each change is intentional (approve the new baseline) or a regression (file a bug).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Major Players
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Applitools Eyes:&lt;/strong&gt; The most advanced AI-powered visual testing platform. It uses visual AI to understand layout semantics rather than raw pixels. Strong cross-browser support. Enterprise pricing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Percy(BrowserStack):&lt;/strong&gt; AI-powered visual UI testing integrated into BrowserStack's ecosystem. Generous free tier (5,000 screenshots/month). Strong CI/CD integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chromatic&lt;/strong&gt; Built for Storybook. Excellent for component-level visual testing. Less suited for full-app mobile regression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BackstopJS:&lt;/strong&gt; open-source, free, and well-maintained. Uses headless Chrome for screenshot capture. The application is strong for web use but has limited support on mobile devices.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Screenshot Diffing Breaks on Mobile
&lt;/h2&gt;

&lt;p&gt;These tools work reasonably well for web applications where rendering is relatively consistent. On mobile, the approach hits structural problems that make it impractical at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Device Fragmentation
&lt;/h3&gt;

&lt;p&gt;There are over 24,000 distinct Android device models in active use. Screen sizes, pixel densities, notch shapes, corner radii, system font sizes, and accessibility settings all vary. A screenshot baseline captured on a Pixel 8 is useless for validating the same screen on a Samsung Galaxy A54 every pixel is different even when the UI is correct.&lt;/p&gt;

&lt;p&gt;Traditional visual regression tools require maintaining baselines per device multiplying storage, review time, and false positives by every device in your matrix.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Dynamic Content
&lt;/h3&gt;

&lt;p&gt;Mobile apps are full of content that changes between screenshots: timestamps, user avatars, notification badges, ad placements, personalised recommendations, and live data feeds. Each of these creates a diff that is flagged as a potential regression, but this behaviour is actually expected.&lt;/p&gt;

&lt;p&gt;Tools offer masking regions to ignore dynamic content, but configuring masks for every dynamic element on every screen is a maintenance project of its own.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Animation and Timing
&lt;/h3&gt;

&lt;p&gt;Mobile UIs use transitions, loading spinners, skeleton screens, and animated content. Capturing a screenshot at a slightly different moment in an animation creates a diff. Screenshots taken 50ms apart during a fade transition look entirely different even though the UI is functioning correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. OS-Level Rendering Differences
&lt;/h3&gt;

&lt;p&gt;Android and iOS render the same UI elements differently. Status bar heights, navigation bar styles, keyboard appearances, and system dialog presentations vary between OS versions. A screenshot baseline from Android 14 creates false positives on Android 15 due to system-level visual changes that have nothing to do with your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The Review Bottleneck
&lt;/h3&gt;

&lt;p&gt;Even with AI-powered diffing, someone has to review flagged changes. A mobile regression suite running across 10 devices and 50 screens generates 500 comparisons per build. If 15% are false positives, that's 75 diffs a human must review and dismiss every single build.&lt;/p&gt;

&lt;p&gt;Teams lose trust in the results. Reviewers start approving everything without looking. The tool becomes noise.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Deeper Problem: Two Separate Testing Systems
&lt;/h2&gt;

&lt;p&gt;The traditional architecture forces teams to maintain two completely separate testing systems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System 1: Functional testing&lt;/strong&gt; (Appium, Espresso, Detox, Maestro, etc.) verifies that elements exist, respond to interactions, and produce correct results. Cannot detect visual issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System 2: Visual regression testing&lt;/strong&gt; (Applitools, Percy, BackstopJS, etc.) captures screenshots, compares baselines, and flags visual changes. Cannot verify functional behaviour.&lt;/p&gt;

&lt;p&gt;Each system has its own setup, configuration, maintenance burden, and CI/CD integration. Each generates its own reports. Each requires its own expertise to operate.&lt;/p&gt;

&lt;p&gt;And the gap between them is precisely where bugs hide. A button that is functionally correct but visually hidden. An element that renders perfectly on the baseline device but breaks on 30% of production devices. A flow appears fine in screenshots, but users experience a 200ms layout shift during navigation that screenshots miss.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Vision AI Changes the Equation
&lt;/h2&gt;

&lt;p&gt;Vision AI doesn't compare screenshots against baselines. It looks at the rendered screen and understands what's there the same way a human tester does.&lt;/p&gt;

&lt;p&gt;This is a fundamentally different architecture:&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional + Visual in One Pass
&lt;/h3&gt;

&lt;p&gt;When Drizz executes a test step like "tap the Login button", the Vision AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looks at the screen and identifies the Login button visually&lt;/li&gt;
&lt;li&gt;Verifies the button is visible, correctly positioned, and tappable&lt;/li&gt;
&lt;li&gt;Taps it&lt;/li&gt;
&lt;li&gt;Observes the result on the next screen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Steps 1 and 2 are inherently visual. The AI is already able to see the screen in order to interact with it. If the button is hidden behind another element, shifted off screen, or rendered in the wrong colour against its background, the Vision AI either can't find it (the test fails with a meaningful error) or identifies the visual anomaly as part of its screen understanding.&lt;/p&gt;

&lt;p&gt;There is no separate visual testing tool. Visual verification is built into every interaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Baselines to Maintain
&lt;/h3&gt;

&lt;p&gt;Screenshot diffing requires a "known-good" baseline that must be updated every time the UI intentionally changes. This creates a perpetual maintenance loop: intentional redesigns trigger hundreds of diffs that must be manually approved.&lt;/p&gt;

&lt;p&gt;Vision AI doesn't use baselines. It evaluates each screen independently by understanding what's on it. A redesigned login screen is still a login screen the AI recognises the email field, password field, and login button regardless of their visual treatment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Device-Agnostic Understanding
&lt;/h3&gt;

&lt;p&gt;A pixel-diff tool sees a Pixel 8 screenshot and a Galaxy S24 screenshot as entirely different images. Vision AI sees both and understands: there's a login form with an email field, a password field, and a submit button. The layout is different. The rendering is different. The semantic content is identical.&lt;/p&gt;

&lt;p&gt;This means one test validates the UI across every device without per-device baselines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic Content Resilience
&lt;/h3&gt;

&lt;p&gt;Screenshot diffing flags a changed timestamp as a visual regression. Vision AI understands that a timestamp is a timestamp it changes, and that's expected. The AI focuses on structural visual elements (buttons, fields, navigation, layout) rather than pixel-level content.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Looks Like in Practice
&lt;/h2&gt;

&lt;p&gt;The same login flow tested three different ways and what each approach can and can't catch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhd91tj8pro11ugk4xh20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhd91tj8pro11ugk4xh20.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Traditional Approach: Two Separate Systems
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Functional test (Appium):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Passes even if button is invisible, misaligned, or wrong colour
&lt;/span&gt;
&lt;span class="n"&gt;login_btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_element&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AppiumBy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ACCESSIBILITY_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;login-btn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;login_btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Visual regression (Percy):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Requires baseline management, masking, and human review
&lt;/span&gt;
&lt;span class="c1"&gt;# Generates false positives from device/OS differences
&lt;/span&gt;
&lt;span class="nf"&gt;percy_snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Login Screen&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two tools. Two configurations. Two CI/CD integrations. Two types of reports. And still a gap between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vision AI Approach: One System
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Drizz test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tap on "Login" button&lt;br&gt;
Enter "&lt;a href="mailto:user@example.com"&gt;user@example.com&lt;/a&gt;" in email field&lt;br&gt;
Tap "Sign In"&lt;br&gt;
Verify the dashboard is visible&lt;/p&gt;

&lt;p&gt;Each step sees the screen. If the login button is visually broken hidden, overlapping, the wrong colour against the background, or off screen the &lt;a href="https://www.drizz.dev/post/vision-language-models-the-next-frontier-in-ai-powered-mobile-app-testing" rel="noopener noreferrer"&gt;Vision AI&lt;/a&gt; either can't find it (clear failure) or flags the anomaly. No separate visual tool. No baselines. No pixel diffs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The key difference&lt;/strong&gt;: The traditional approach answers two separate questions with two separate tools ("does it work?" and "does it look right?"). Vision AI answers both questions simultaneously because it has to see the screen to interact with it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  When You Still Need Traditional Visual Regression
&lt;/h2&gt;

&lt;p&gt;Vision AI doesn't replace every visual testing scenario. Traditional tools still have value for:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pixel-perfect design compliance.&lt;/strong&gt; If your design system requires exact pixel measurements between elements, dedicated visual regression tools with Figma integration (like Applitools' design-to-code comparison) provide that granularity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Component-level visual testing.&lt;/strong&gt; Chromatic and Storybook-based tools excel at testing isolated UI components across states (hover, focus, disabled, error). This area is a different scope than full-app visual regression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web application visual testing.&lt;/strong&gt; Percy and Applitools are mature, well-integrated tools for web visual regression where device fragmentation is less extreme than mobile.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regulatory visual compliance.&lt;/strong&gt; Some industries require screenshot-based audit trails of UI state at specific points in time. Baseline comparison tools provide this documentation.&lt;/p&gt;

&lt;p&gt;Vision AI offers a more efficient architecture for full-app mobile regression, providing both functional and visual coverage across devices without the need to maintain separate systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  When You Need Vision AI
&lt;/h2&gt;

&lt;p&gt;Vision AI is the stronger choice when your testing challenges are defined by scale, fragmentation, and speed of iteration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your app ships UI changes weekly or faster&lt;/strong&gt;. When the UI evolves every sprint, baseline-dependent tools create a perpetual approval cycle. Vision AI evaluates each screen independently, so intentional redesigns don't generate hundreds of false diffs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You test across 10+ device models&lt;/strong&gt;. Screenshot diffing requires per-device baselines. At 10 devices across 50 screens, that's 500 baselines to maintain. Vision AI validates semantically one test covers every device without separate baselines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your app has heavy dynamic content&lt;/strong&gt;. Personalised feeds, live data, A/B tests, and user-generated content create constant diffs in screenshot tools. Vision AI understands that a changed avatar or updated timestamp is expected behaviour, not a regression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your team maintains separate functional and visual testing systems&lt;/strong&gt;. There are two tools, two configurations, two CI pipelines, and two types of reports. Vision AI consolidates both into a single pass functional interaction and visual verification happen simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You need to catch visual bugs across both platforms.&lt;/strong&gt; A layout issue that only manifests on Android or only in dark mode is invisible to a baseline captured on iOS in light mode. Vision AI sees whatever the user sees, on whatever device they're using.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your QA team is bottlenecked on review&lt;/strong&gt;. If your visual regression tool generates more false positives than real catches, the review process becomes a bottleneck. Vision AI's semantic understanding dramatically reduces noise.&lt;/p&gt;

&lt;p&gt;For teams where &lt;a href="https://www.drizz.dev/post/self-healing-mobile-test-automation" rel="noopener noreferrer"&gt;test maintenance has become the primary bottleneck&lt;/a&gt;, Vision AI offers a more efficient architecture providing both functional and visual coverage across devices without the need to maintain separate systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Vision AI Visual Testing
&lt;/h2&gt;

&lt;p&gt;If you're running separate functional and visual regression systems and want to consolidate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Download Drizz Desktop&lt;/strong&gt; from &lt;a href="//drizz.dev/start"&gt;drizz.dev/start&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect a device USB&lt;/strong&gt;, emulator, or simulator&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upload your app&lt;/strong&gt; no SDK changes required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write tests in plain English&lt;/strong&gt; that describe user flows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run their vision&lt;/strong&gt; AI handles functional interaction and visual verification in one pass&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review results&lt;/strong&gt; step level screenshots with AI failure reasoning for every failure
Your functional tests and visual coverage run as a single suite. No baselines. No pixel diffs. No separate tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.drizz.dev/book-a-demo" rel="noopener noreferrer"&gt;Get started with Drizz&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between visual regression testing and functional testing?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Functional testing verifies that elements work: buttons click, forms submit, and pages load. Visual regression testing verifies that elements look correct proper layout, colours, alignment, and rendering. A button can pass every functional test while being completely invisible to users. You need both types of coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can Appium or Espresso detect visual bugs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Appium, Espresso, XCUITest, Detox, and Maestro verify the presence, state, and behaviour of elements through the accessibility layer or element tree. They cannot detect visual issues such as layout shifts, colour regressions, overlapping elements, or rendering inconsistencies. You need a visual testing layer on top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does Drizz handle visual regression differently from Applitools or Percy?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Applitools and Percy compare screenshots against stored baselines and flag pixel or perceptual differences. Drizz's Vision AI sees the screen in real-time during functional test execution. Visual verification happens as part of every interaction, not as a separate screenshot comparison step. This eliminates baseline management and reduces false positives from device fragmentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need to maintain visual baselines with Drizz?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Drizz doesn't use screenshot baselines. The Vision AI evaluates each screen independently by understanding what's on it identifying elements, layout, text, and visual context in real-time. This means intentional UI redesigns don't trigger hundreds of false diffs that need manual approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does Vision AI handle device fragmentation?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vision AI understands the semantic content of a screen rather than comparing pixel patterns. A login form on a Pixel 8 and a Galaxy S24 looks different at the pixel level but contains the same elements. The AI recognises the form, fields, and buttons regardless of device-specific rendering differences; one test covers all devices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I use Drizz alongside Percy or Applitools?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes. Some teams use Drizz for functional + visual coverage in their regression suite and keep Percy or Applitools for component-level visual testing (via Storybook) or pixel-perfect design compliance checks. The tools serve different scopes and can complement each other.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
