How to Test Comments on Android (Complete Guide)

Comments are one of the most interactive surfaces in modern apps. Users leave feedback, ask questions, tag friends, and sometimes upload media through a comment field. Because the UI is simple—a text

June 13, 2026 · 16 min read · How-To Guides

Why Testing Comments Matters on Android

Comments are one of the most interactive surfaces in modern apps. Users leave feedback, ask questions, tag friends, and sometimes upload media through a comment field. Because the UI is simple—a text input, a submit button, and a list view—teams often assume it is low‑risk. In production, however, comments become a hotspot for crashes, ANRs, privacy leaks, and accessibility failures. A malformed payload can trigger a server‑side injection, a soft‑keyboard clash can hide the submit button, and a TalkBack user may never reach the field if focus order is broken. Testing comments therefore validates not only the happy‑path flow but also the robustness of input handling, network error recovery, UI state persistence, and compliance with accessibility and security guidelines. Skipping any of these dimensions invites user‑facing bugs that are costly to fix after release and can damage brand trust.

Comprehensive Test Matrix for Comments

CategorySub‑caseTest Steps (high‑level)Expected Result
Happy PathBasic submitTap comment field, type “Hello”, press submitComment appears in list with correct text, timestamp, and author avatar
Emoji & UnicodeInsert 😀, 🇺🇸, and a CJK character sequenceAll glyphs render correctly, no truncation
Mentions & hashtagsType @alice and #featureMentions trigger user lookup, hashtags become tappable links
Media attachmentTap attach icon, select image, add caption, submitImage uploads, thumbnail shows, caption preserved
Edit own commentLong‑press own comment, choose Edit, modify text, saveUpdated text reflects instantly, edit indicator appears
Delete own commentLong‑press own comment, choose Delete, confirmComment removed from list, undo toast appears (if implemented)
Error PathsEmpty submitTap submit with no textInput field shows error (e.g., “Comment cannot be empty”), no network call
Max length exceededPaste 5000‑character string, attempt submitInput blocked or trimmed to server limit, error shown if exceeded
Network loss during submitEnable airplane mode after typing, press submitSubmission fails gracefully, UI shows retry option, data not lost
Server error (5xx)Mock backend to return 500, submitError toast displayed, comment not added, optional retry offered
Invalid UTF‑8Send over‑long surrogate pair via automationApp sanitizes or rejects input, no crash
Edge CasesSoft‑keyboard obscures submitRotate to landscape, open keyboard, verify button visibilitySubmit button remains above keyboard or scrolls into view
IME action changeChange keyboard “Done” to “Search” via settings, testAction triggers submit as expected
Copy/paste from clipboardCopy rich text, paste into comment field, submitPlain text only (or sanitized rich text) appears, no hidden formatting
Multi‑window / split‑screenLaunch comment UI in split‑screen with another appUI remains functional, no layout overlap
Picture‑in‑picture (PiP)Enter PiP while comment field focusedField loses focus appropriately, no leaked input
Font scaling (large / smallest)Set system font size to 200% and 50%, testAll text readable, UI elements not clipped
Dark modeForce dark theme, verify contrastText and icons meet WCAG AA contrast ratios
TalkBack navigationEnable TalkBack, swipe to comment field, submitFocus lands on field, labels announced, actions accessible
Switch ControlConnect switch device, navigate to submitSwitch can activate submit via scanning
AccessibilityContent descriptionsInspect via Accessibility ScannerAll interactive elements have meaningful contentDescription
Touch target sizeMeasure with UI AutomatorMinimum 48dp × 48dp for tap targets
Heading structureVerify TalkBack announces list as “comments, 5 items”Proper heading or list semantics
Live region updatesAdd new comment, verify TalkBack announces itNew item announced without manual focus change
Security / PrivacySQL / NoSQL injectionAttempt ' OR 1=1-- in comment fieldInput sanitized, no query error or data leak
XSS via webview comment renderInject if comment rendered in WebViewScript not executed, content escaped or sanitized
File upload type validationTry to upload .apk or .exe as imageServer rejects, client shows appropriate error
Permission leakageCheck that comment draft is not written to external storage without consentNo stray files appear in /sdcard/
Data minimizationVerify only needed fields (text, user ID, timestamp) sentNo extra personal data (e.g., device ID) included in payload
Rate limiting abuseSubmit 100 rapid comments via scriptBackend throttles, client shows “too many requests” UI

> Note: Each sub‑case can be expanded with concrete data values (e.g., exact character counts, specific emoji code points) to make regression scripts deterministic.

Manual Testing Approach Step‑by‑Step

  1. Prepare a clean test environment
  1. Authenticate (if required)
  1. Navigate to the comment UI
  1. Execute the happy‑path matrix
  1. Inject error conditions
  1. Test edge‑case interactions
  1. Validate accessibility and security
  1. Document observations
  1. Retest after fixes

Automated Testing with Android Tools

Unit‑level verification


@Test
fun `submit empty comment throws validation error`() {
    val viewModel = CommentViewModel(repository = mockRepository)
    viewModel.onCommentSubmitted("")   // empty string
    assertTrue(viewModel.uiState.value is CommentUiState.Error)
    assertEquals("Comment cannot be empty", (viewModel.uiState.value as CommentUiState.Error).message)
}

Instrumented UI tests with Espresso


@RunWith(AndroidJUnit4::class)
class CommentUiTest {

    @get:Rule
    val activityRule = ActivityScenarioRule(MainActivity::class.java)

    @Test
    fun happyPath_basicSubmit() {
        onView(withId(R.id.comment_edit_text))
            .perform(replaceText("Hello"), closeSoftKeyboard())
        onView(withId(R.id.comment_submit_button))
            .perform(click())

        // Verify comment appears in RecyclerView
        onView(withId(R.id.comments_recycler_view))
            .check(matches(hasDescendant(withText("Hello"))))
    }

    @Test
    fun errorPath_emptySubmit_blocked() {
        onView(withId(R.id.comment_submit_button))
            .check(matches(not(isEnabled())))   // button disabled when empty
        onView(withId(R.id.comment_edit_text))
            .perform(replaceText(" "))   // whitespace only
        onView(withId(R.id.comment_submit_button))
            .check(matches(not(isEnabled())))
        onView(withId(R.id.comment_edit_text))
            .perform(replaceText("Hello"))
        onView(withId(R.id.comment_submit_button))
            .check(matches(isEnabled()))
    }
}

UIAutomator for system‑level interactions


@Test
public void commentFromShareIntent_showsCorrectUI() {
    Context instrContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
    Intent share = new Intent();
    share.setAction(Intent.ACTION_SEND);
    share.setType("text/plain");
    share.putExtra(Intent.EXTRA_TEXT, "Check this out");
    share.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    instrContext.startActivity(share);

    UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    // Wait for comment field to appear
    UiObject commentField = device.findObject(new UiSelector().resourceId("com.example.app:id/comment_edit_text"));
    assertTrue(commentField.waitForExists(5000));
    commentField.setText("Shared text");
    device.findObject(new UiSelector().resourceId("com.example.app:id/comment_submit_button")).click();
    // Verify that the shared text appears in the comment list
    UiObject listItem = device.findObject(new UiSelector()
            .resourceId("com.example.app:id/comment_item_text")
            .textContains("Shared text"));
    assertTrue(listItem.waitForExists(5000));
}

Robolectric for fast JVM tests


@Test
fun viewModel_showsErrorOnNetworkFailure() {
    val mockRepo = mock<CommentRepository>()
    whens(mockRepo.submitComment(any())).thenReturn(Single.error(IOException()))
    val viewModel = CommentViewModel(mockRepo)

    viewModel.onCommentSubmitted("Test")
    assertTrue(viewModel.uiState.value is CommentUiState.Error)
}

Mocking the backend


mockWebServer.enqueue(new MockResponse()
        .setResponseCode(500)
        .setBody("{\"error\":\"internal\"}"));

Continuous Integration integration

Autonomous Persona‑Driven Exploration with SUSA

SUSA explores an app without pre‑written scripts by simulating distinct user personalities. Each persona has a configured interaction model:

PersonaInteraction traitsTypical comment‑related behavior
CuriousTaps every visible element, reads tooltips, tries long‑pressOpens comment field, tries to attach images, explores edit/delete menus
ImpatientRapid taps, skips reading, attempts submit before keyboard fully appearsSubmits while keyboard animating, triggers race conditions
NovicePrefers default actions, avoids obscure gestures, relies on hintsRelies on hint text, may leave field empty if hint unclear
AdversarialAttempts malformed input, injects scripts, tries to bypass limitsPastes SQL strings, huge text, invalid file types
ElderlyLarger tap targets, slower navigation, uses accessibility featuresRelies on TalkBack, may need larger fonts, avoids hidden controls
Power userUses shortcuts, swipe gestures, copy/paste from clipboardUses swipe‑to‑delete, pastes from clipboard, attempts batch actions

When SUSA runs against an APK, it:

  1. Installs the app on an emulator or device via adb install.
  2. Creates a virtual session for each persona, seeding a realistic account (if login is required).
  3. Navigates to the comment screen using heuristics (e.g., looking for a “Comment” text or a speech‑bubble icon).
  4. Executes actions according to the persona’s policy, while monitoring for crashes, ANRs, unhandled exceptions, and accessibility violations (via Android’s AccessibilityEvent broadcast).
  5. Records every visited screen, every input value, and every network request, building a graph of explored states.
  6. Generates regression scripts (Appium for Android, Playwright for Web) that capture the exact interaction sequences that led to a failure.

Example command line:


susatest run \
  --apk ./app-release.apk \
  --personas curious impatient adversarial elderly \
  --output-dir ./susatest-out \
  --max-depth 6 \
  --timeout-per-action 2s

SUSA will automatically try to submit a comment while the keyboard is still animating (impatient persona), paste a 10 KB string of random Unicode (adversarial), and verify that TalkBack announces the newly added comment (elderly persona). If any of these actions cause a crash, the platform outputs a detailed report that includes:

Because SUSA does not rely on hard‑coded locators, it discovers issues that scripted tests often miss: a comment submit button that becomes invisible only when a specific third‑party IME is active, or a TalkBack focus loop that skips the comment field when the app uses a custom RecyclerView.ItemDecoration. Integrating a nightly SUSA run into your release pipeline therefore adds a layer of exploratory validation that complements unit and instrumented tests.

Edge Cases That Appear Only in Production

Production‑only factorWhy it matters for commentsHow to simulate / observe
Variable network latency & packet lossReal‑world Wi‑Fi or cellular networks cause delayed ACKs, leading to duplicate submissions or optimistic UI updates that never roll back.Use tc qdisc add dev wlan0 root netem delay 200ms loss 5% on the emulator (adb shell su -c "tc ...") or a tool like Clumsy on Windows.
Locale‑specific IMECertain languages (e.g., Arabic, Hindi) use right‑to‑left layout or composition windows that can hide the submit button or cause incorrect cursor placement.Change device language via adb shell setprop persist.sys.language ar &&adb shell setprop persist.sys.country EG &&adb reboot. Test with Google Indic Keyboard or Gboard Arabic layout.
Dark mode forced by battery saverSome OEMs override app theme when battery saver is on, altering contrast and potentially making hint text invisible.Enable battery saver (adb shell cmd power set-power-save true) and verify comment field hint remains legible.
Font scaling beyond 200%Users with severe visual impairment may set font scale to 300% or more; layouts that rely on fixed dp can clip the comment field or overflow the submit button.In developer options, set “Minimum width” to 360dp and “Font scale” to 3.0, then relaunch the app.
Multi‑resolution & foldable devicesOn foldables, the comment UI may appear on the inner screen while the keyboard resides on the outer screen, causing focus loss.Use Android Studio’s foldable emulator (Pixel Fold) and switch between tabletop and book modes while the comment field is focused.
Picture‑in‑picture (PiP) with ongoing comment draftIf the user pushes the app to PiP while typing, the draft may be lost or the input field may remain focused in the background, leading to unexpected behavior.Start a comment, press Home to trigger PiP (if supported), then return to the app and verify draft persistence.
Background restrictions (Android 12+)When the app is placed in standby bucket, jobs that upload comment media may be deferred, causing the UI to show a “sending” spinner indefinitely.Use adb shell cmd app set-standby-bucket rare and attempt to upload an image with comment.
Data Saver modeNetwork library may downgrade image upload quality or block requests altogether, breaking media‑attachment comment flow.Enable Data Saver (Settings → Network & internet → Data Saver) and try to attach a 2 MB photo.
Clipboard changes from external appsA user may copy a password from a password manager, then paste into the comment field inadvertently, leaking sensitive data.Use adb shell service call clipboard 1 i32 0 s16 "secret" to place text in clipboard, then paste into comment field and confirm the app does not log or transmit it.
TalkBack focus order changes after dynamic UI updatesAdding a new comment may insert a view at the top of the list, shifting focus and causing TalkBack to announce the wrong item.Enable TalkBack, add a comment, then swipe forward and listen to ensure the newly added comment is announced correctly.
System UI gestures (navigation bar vs. gesture navigation)On gesture‑navigation devices, the swipe‑up home gesture can be intercepted by the app’s bottom sheet, preventing the keyboard from dismissing.Switch navigation mode via adb shell settings put system navigation_mode 2 (gesture) and test keyboard dismissal with back swipe.
Battery optimization whitelistIf the app is aggressively optimized, background services that debounce duplicate comment submissions may be killed, resulting in multiple network calls.Add app to battery optimization exempt list (adb shell cmd deviceidle tempwhitelist +) and then remove it to see effect.
Secure flag on windowSome apps set WindowManager.LayoutParams.FLAG_SECURE on the comment screen to prevent screenshots; this can interfere with automated testing frameworks that rely on screen capture for assertions.Check if `adb shell dumpsys window windowsgrep FLAG_SECURE shows the flag; if present, verify that Espresso’s onView(...).check(matches(isDisplayed()))` still works (it should, but UIAutomator screenshots will be blank).

Testing these conditions manually is tedious; however, you can automate many of them using adb shell commands combined with Espresso Idling Resources that listen to ConnectivityManager.CONNECTIVITY_ACTION or UI_MODE_NIGHT_MASK. Incorporating them into your CI nightly run ensures that production‑like‑behavior bugs are caught before they reach users.

Checklist for Comments Testing

✅ ItemDescriptionVerification Method
Happy pathBasic submit, emoji, mentions, media, edit, deleteManual + Espresso
Empty inputSubmit blocked, error shownManual + UI test
Max lengthInput trimmed or rejected, no crashManual + property‑based test (e.g., using jqwik)
Network lossGraceful error, retry option, draft persistedadb shell cmd connectivity airplane-mode on/off + Espresso
Server error (5xx/4xx)Error toast, no comment added, optional retryMockWebServer + Espresso
Invalid UTF‑8 / surrogate pairsInput sanitized, no crashInstrumented test with byte array injection
Soft‑keyboard obscuringSubmit button visible or scrolls into viewLandscape rotation + UIAutomator
IME actionCustom IME action triggers submitChange IME via settings + Espresso
Clipboard pastePlain text only, no hidden formattingadb shell service call clipboard + Espresso
Multi‑window / PiPUI functional, no leaksSplit‑screen emulator + Activity lifecycle checks
Font scalingAll text readable, no clippingDeveloper options font scale 0.5–3.0
Dark modeWCAG AA contrast metAccessibility Scanner + manual verification
TalkBack navigationField reachable, actions announcedTalkBack + AccessibilityEvent monitoring
Switch ControlScan can reach submitConnect switch device + UIAutomator
Content descriptionsAll interactive elements describedAccessibility Scanner
Touch target size≥48dpUI Automator measurement
Live region updatesNew comment announced without manual focusTalkBack + Espresso Idling Resource
Input sanitizationNo SQL/XSS injection, file type validationBurp/ZAP + MockWebServer
Permission leakageNo stray files in external storageadb shell ls -sdcard/ after test
Data minimizationOnly required fields in payloadNetwork inspection (Charles/Mitmproxy)
Rate limitingUI shows “too many requests” after rapid submitsLoop submit 100x + backend throttle check
Automated regressionAll matrix cases covered by unit/UI tests./gradlew test connectedAndroidTest
Persona‑driven explorationSUSA run finds at least one bug not in scriptssusatest run --apk … --personas …
Production‑only simulationsNetwork latency, locale IME, battery saver, data saver, etc.adb shell netem, locale change, power save, data saver flags
Regression scriptsGenerated Appium/Playwright scripts from SUSA added to sourceReview generated scripts, add to src/androidTest
ChangelogAny comment‑related fix documentedVerify release notes include comment bug IDs

Key Takeaways

  1. Comments are a high‑risk surface despite their simple appearance. They combine user‑generated input, media uploads, real‑time networking, accessibility concerns, and security‑critical validation. A defect here can lead to data loss, privacy exposure, or a broken core flow.
  1. A thorough test matrix is the foundation. Separate happy paths, error paths, edge cases, accessibility, and security/privacy. Use concrete values (exact character lengths, specific emoji code points, defined network latency values) to make each test case repeatable.
  1. Manual testing remains indispensable for exploratory checks—especially for verifying visual layout under font scaling, dark mode, and various IMEs. Follow the step‑by‑step procedure, record observations, and turn each reproducible issue into an automated test.
  1. Automate at every layer: unit tests for model validation, Espresso for UI interactions, UIAutomator for system‑level behavior (multi‑window, IME, accessibility), Robolectric for fast JVM tests, and MockWebServer for network variability. Leverage Idling Resources to synchronize with asynchronous comment submissions.
  1. Autonomous, persona‑driven exploration catches the gaps that scripted tests overlook. Tools like SUSA simulate curious, impatient, novice, adversarial, elderly, accessibility, and power‑user behaviors, surfacing bugs such as a submit button hidden by a specific IME, TalkBack focus loss after dynamic list updates, or a crash when pasting a massive Unicode string. The generated Appium or Playwright scripts become immediate regression assets.
  1. Production‑only conditions must be exercised before release. Simulate network loss and latency with tc netem, switch locales, enable battery saver or data saver, test on foldable and PiP emulators, and verify that clipboard content does not leak.
  1. Maintain a living checklist that maps each matrix item to a verification method (manual, Espresso, UIAutomator, SUSA, etc.). Update the checklist whenever the comment flow evolves (e.g., adding voice‑to‑text or reaction emojis).
  1. Close the feedback loop: whenever a bug is found in the wild, add a corresponding test case to the matrix, automate it, and verify that the persona‑driven explorer would have caught it. Over time, this reduces the chance of regressions and increases confidence that the comment experience is robust for every class of user.

By combining rigorous matrix‑based testing, layered automation, and exploratory persona‑driven validation, you turn the comment feature from a potential liability into a polished, trustworthy part of your Android app. The investment pays off in fewer post‑release crashes, higher accessibility scores, and stronger user confidence that their voice is heard—and protected.

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free