Dark Mode Testing Checklist (2026)

Dark Mode Testing Checklist (2026)

April 08, 2026 · 18 min read · Testing Checklists

Dark Mode Testing Checklist (2026)

A practical, item‑by‑item guide for verifying that an application behaves correctly when the system or app‑level theme switches to dark mode. This checklist groups more than thirty concrete verification points into happy‑path, error/edge, accessibility, security/privacy, performance, and release‑readiness buckets. Each item includes a clear pass criterion, a real‑world example, and notes on how manual or automated techniques (including autonomous exploration) can cover it in a single pass.

Dark Mode Testing Checklist (2026): Happy Path

System‑level vs App‑level Theme Switching

When the operating system toggles between light and dark themes, the app must react without a restart. Verify that:

  1. Theme propagation – All UI components (activity/fragment, view hierarchy, web view, custom canvas) receive the new theme values within 200 ms of the system broadcast.
  2. Persisted preference – If the app stores a user‑chosen override (e.g., “Always dark”), the stored value survives process kill and device reboot.
  3. Consistent fallback – When a resource lacks a dark‑mode qualifier, the app falls back to the light version *only* after explicitly checking for the qualifier; missing fallbacks produce hard‑coded colors that break contrast.

*Example*: A messaging app uses ?attr/colorSurface for card backgrounds. In dark mode the attribute resolves to #121212. If a developer hard‑coded #FFFFFF in a layout, cards appear as white blocks on a dark background, failing the moment after a theme switch.

Core UI Elements

Check every visible element for correct color assignment:

Element TypeLight‑mode ReferenceDark‑mode ReferencePass Criterion
Background#FAFAFA#121212No hard‑coded hex; uses theme attribute or resource qualifier
Primary text#212121#E0E0E0Contrast ratio ≥ 4.5:1 against background
Secondary text#757575#B0B0B0Contrast ratio ≥ 3:1 against background
Icons (stroke)#424242#FFFFFFUses ?tint or vector asset with dark‑mode variant
Dividers#E0E0E0#2F2F2F1 dp height, visible but not overpowering

*Example*: A settings screen uses a SwitchCompat whose thumb color is defined via ?attr/colorControlActivated. In dark mode the thumb becomes a bright cyan (#00E5FF). Verify that the thumb remains distinguishable from the track (#424242) and does not bleed into adjacent items.

Navigation and Transitions

Dark mode must not break navigation patterns:

*Example*: An e‑commerce app uses a shared‑element transition from a product list to a detail page. If the shared element’s background is not updated before the transition starts, a white rectangle briefly appears over the dark detail screen, which is perceptible as a flicker.

Forms and Input Controls

Every editable field must retain legibility and correct state indication:

*Example*: A login screen shows a floating label that turns red when validation fails. In dark mode the label color must shift from the light‑mode red (#B00020) to the dark‑mode red (#CF6679). If the app forgets to update the label’s textColor state, the error message appears as a dark gray that users may miss.

Media Playback and Overlays

Video players, image galleries, and overlay dialogs must adapt:

*Example*: A news app displays a video with subtitles. In dark mode the subtitle background is #99000000. If the background is omitted, white text on a bright frame becomes washed out, while on a dark frame it is legible but lacks the required contrast ratio of 4.5:1 for normal text.

Dark Mode Testing Checklist (2026): Error and Edge Cases

Empty and Loading States

Empty lists, loading spinners, and error pages often receive less attention in dark mode.

*Example*: A settings screen shows an empty state with a robot illustration and the text “No preferences saved”. If the illustration is a static white SVG, it appears as a ghostly shape on the dark surface, reducing recognizability.

Dynamic Content and Theming

Content fetched from a server may carry its own color information (e.g., HTML emails, markdown rendered in a WebView).

*Example*: A chat app renders incoming messages with a light‑gray bubble (#E0E0E0). In dark mode the bubble should switch to a dark surface (#2F2F2F). If the app forgets to update the background drawable, the message appears as a light rectangle, making it hard to differentiate from the sender’s bubble.

Edge‑case UI States

Certain UI states only appear under specific interactions (long press, swipe, rotation).

*Example*: A photo editor shows a toolbar that appears only in landscape. The toolbar’s background is defined in layout-land/toolbar.xml without a -night variant. When the user rotates to landscape while dark mode is active, the toolbar stays light, causing a sudden flash.

Animations and Motion Effects

Animations can inadvertently expose the wrong theme during intermediate frames.

*Example*: A splash screen uses a Lottie animation with a white logo. In dark mode the logo should be tinted to #FFFFFF via lottieView.setValueCallback(...). Forgetting to apply the tint results in a white logo on a white background (if the splash background is also white) or a low‑contrast logo on a dark background.

Dark Mode Testing Checklist (2026): Accessibility

WCAG Contrast Ratios

Automated contrast checkers (axe-core, Google’s Accessibility Scanner) should be run on every screen in both themes.

*Pass criterion*: No violations reported by the chosen tool under either theme.

*Example*: A settings toggle’s thumb is #FFFFFF on a track #424242. Contrast = 5.2:1 → passes. If the thumb were #CCCCCC, contrast drops to 2.8:1 → fails.

Screen Reader Compatibility

TalkBack (Android) and VoiceOver (iOS) must announce state changes correctly when the theme switches.

*Example*: A form field shows an error icon (red circle) and an error message. The TalkBack label for the field should be “Password, invalid, enter at least eight characters”. If the label only says “Password, invalid” without describing the visual cue, users who cannot perceive color miss the severity.

Focus Order and Visibility

Keyboard or switch‑device navigation must retain a visible focus indicator.

*Example*: A custom chip component draws its background as a rounded rect but omits the focus outline. When navigating with a D‑pad, the chip does not show any visual change, causing users to lose track of focus.

Touch Target Size

Dark mode does not change the physical size of touch targets, but low‑contrast targets can be harder to locate.

*Example*: A floating action button with a 1‑dp white border on a dark surface (#121212) yields a contrast of ~15:1 → passes. If the border were #424242, contrast drops to ~3.5:1, still acceptable but borderline; consider increasing the border width or using a brighter tint.

Reduced Motion and Animation Preferences

Users who have enabled “Remove animations” or “Reduce motion” should not be bombarded with motion that can trigger discomfort.

*Example*: A toggle switch uses a wiggle animation to indicate an error. When “Reduce motion” is on, the wiggle is disabled, leaving only the color change. If the color change is insufficient (low contrast), users may miss the error. Ensure the error state also changes the thumb’s opacity or adds an icon.

Dark Mode Testing Checklist (2026): Performance and Resource Usage

GPU Overdraw

Dark themes often reduce overdraw because dark backgrounds absorb less light, but overdraw can still occur due to multiple translucent layers.

*Example*: A news feed uses a card with a semi‑transparent overlay (#66000000) for a gradient title background. In dark mode the overlay is still semi‑transparent black, causing the card to be drawn three times (background, overlay, text). If the overlay is unnecessary, removing it reduces overdraw from 2.5× to 1.5×.

Battery Impact

On OLED screens, dark pixels consume significantly less power. Measure the actual power draw to confirm the benefit.

*Example*: A video streaming app shows a bright thumbnail grid. Switching to dark mode reduces the average power draw from 320 mA to 260 mA during idle scrolling, a ~19 % saving that translates to longer battery life.

Memory Consumption

Dark‑mode resources (e.g., -night drawables) should not cause duplication that bloats APK size.

*Example*: An app ships a 2048 × 2048 px background for both light and dark themes, differing only by a color overlay. By using a single base image and applying a color filter (ColorFilter) at runtime, the APK size drops by 1.4 MB.

Frame‑rate Stability During Theme Switch

Switching themes at runtime should not cause a noticeable jank.

*Example*: A settings screen loads a large XML preference file when the theme changes, causing a 45 ms frame drop and a perceptible stutter. Moving the file parse to an AsyncTask eliminates the jank.

Dark Mode Testing Checklist (2026): Security and Privacy

Screenshot Obfuscation

Some apps hide sensitive data in screenshots (e.g., banking apps) by overlaying a tint. The overlay must work in both themes.

*Example*: A payment app overlays a black rectangle with 60 % opacity over the CVV field. In light mode the overlay makes the field unreadable. In dark mode the same overlay yields a dark gray over a dark background, still obscuring but slightly less; increase opacity to 80 % for dark mode or use a contrasting color (#FFFFFF with 30 % opacity).

Theme‑based Side‑Channel Leaks

An attacker could infer the current theme via timing or power analysis, potentially revealing UI state.

*Example*: An app loads a high‑resolution hero image (hero_light.png or hero_dark.png) based on the theme. An attacker monitoring memory allocation spikes could infer the theme. Switching to a single asset with a ColorFilter removes the timing variance.

Credential Field Visibility

Password fields must not reveal characters via accidental contrast tricks.

*Example*: A login screen shows the password as black dots (•••••). In dark mode the dots are rendered as white circles (◯◯◯◯◯). If the dot drawable is not swapped, the white circles may blend into a light‑colored background behind the field (if the background is incorrectly light), making the password guessable.

Dark Mode Testing Checklist (2026): Release Readiness

Continuous Integration (CI) Integration

Automated checks should run on every pull request to catch regressions early.

*Example*: A CI pipeline runs ./gradlew connectedAndroidTest which executes a set of UI tests that capture screenshots of the login, home, and settings screens in both light and dark modes, then runs diffy to compare against approved baselines. Any new screen that lacks a -night variant triggers a failure because the diff exceeds 0.02 RMSE.

Baseline Screenshot Management

Maintaining a reliable baseline is essential for detecting unintentional changes.

*Example*: The home screen contains a “Last updated: xx:xx” timestamp. Before comparison, a mask rectangle is placed over the timestamp area, ensuring that changes in the timestamp do not cause false positives.

Regression Script Generation

Leverage the exploratory data captured by autonomous testing tools to generate repeatable scripts.

*Example*: After a SUSA run, the agent produces a file dark_mode_flow.json. A small Node script reads each step, generates a Playwright test that: 1) navigates to the URL, 2) forces dark mode, 3) checks window.getComputedStyle(element).getPropertyValue('background-color') matches the expected dark‑mode token, and 4) repeats for light mode.

Cross‑device Matrix

Dark mode rendering can differ across manufacturers due to theme overlays or OLED vs LCD panels.

*Example*: On a Samsung device, the system UI applies a dark overlay with a slight blue tint (#1A237E) to status bar icons. An app that uses ?attr/colorOnSurface for status bar icons receives the correct tint (#FFFFFF) after the override, ensuring consistency.

Release Notes and Documentation

Communicate dark‑mode support clearly to users and internal stakeholders.

*Example*: The release notes for v3.2 read: “Dark mode has been extended to the chat composer, settings, and payment flow. Contrast ratios have been audited and meet WCAG AA standards. A new system‑follow option lets the app automatically match the OS theme.”

Leveraging Autonomous Exploration for Dark Mode

How an Autonomous Agent Covers Most of the Checklist

Platforms like SUSA (SUSATest) explore an app without pre‑written scripts by simulating a variety of user personas. When configured to test both light and dark themes, the agent implicitly validates many checklist items.

Checklist AreaWhat the Agent DoesHow It Maps to Manual Checks
Happy path UINavigates every reachable screen, taps all visible buttons, inputs text into every EditText, scrolls lists, opens drawersVerifies theme propagation, correct color assignments, and navigation transitions
Error/edge casesTriggers empty states by clearing data, forces network errors, rotates device, long‑presses on items, opens contextual action barsChecks empty‑state illustrations, spinner colors, rotation layouts, long‑press highlights
AccessibilityEnables TalkBack persona, varies font size, enables “reduce motion”, and records spoken feedbackValidates screen‑reader labels, focus order, contrast (via built‑in axe plugin), motion‑reduced behavior
PerformanceMeasures frame timestamps, logs GPU overdraw via shell command adb shell dumpsys gfxinfo , records battery drain with adb shell dumpsys batterystatsConfirms jank‑free theme switches, acceptable overdraw, battery savings
Security/privacyAttempts screenshots (if FLAG_SECURE not set), inspects overlay opacity, monitors memory allocations for theme‑specific assetsDetects insecure screenshots, insufficient overlay, theme‑based side‑channel leaks
Release readinessGenerates Appium/Playwright scripts from the explored flow, writes baseline screenshots to a folder, runs diff against previous commitProvides CI‑ready regression assets, baseline management, cross‑device script portability

Configuring Personas for Dark Mode

SUSA ships with built‑in personas (curious, impatient, novice, adversarial, elderly, accessibility, power user, etc.). To stress‑test dark mode, enable the following combinations:

The agent’s configuration file (susatest-config.yaml) can include:


test_sessions:
  - name: dark_mode_accessibility
    theme: dark
    personas:
      - accessibility
      - elderly
    metrics:
      - contrast
      - talkback_feedback
      - frame_time
  - name: dark_mode_adversarial
    theme: dark
    personas:
      - adversarial
    actions:
      - long_press
      - rapid_tap
      - rotate_device

Interpreting Results

After a run, SUSA outputs a JSON report with sections for each persona. Key fields to inspect for dark‑mode compliance:

A typical pass criterion for a release build is:

If any of these fail, the report highlights the exact screens and actions responsible, allowing developers to fix the specific issue before merging.

Practical Checklist Summary

Below is a condensed, copy‑paste‑ready checklist that you can paste into a ticket or a Wiki page. Each item includes a Pass/Fail column for quick marking during test sessions.

#AreaTest DescriptionPass CriteriaExample Failure
1Theme PropagationVerify UI updates within 200 ms after system theme toggle.No stale colors after toggle.Settings screen stays light after switching to dark.
2Resource QualifiersAll colors, drawables, and animations have -night variants or use theme attributes.No hard‑coded #RRGGBB in layout/xml.Button background uses #FFFFFF everywhere.
3Contrast – TextNormal text ≥ 4.5:1, large text ≥ 3:1 against immediate background.Measured via axe-core or Android Accessibility Scanner.Hint text #9E9E9E on #121212 = 3.2:1 (fail).
4Contrast – IconsIcon stroke ≥ 3:1 against background.Icons visible in both themes.Mail icon (#757575) on dark surface = 2.1:1 (fail).
5Navigation BarSelected item uses semi‑transparent overlay; icons/text adapt.Selected item distinguishable; no flicker.Selected tab stays same opacity as unselected.
6Drawer ScrimScrim color #66000000 in dark, #66FFFFFF in light.Correct opacity and hue.Scrim remains light in dark mode.
7Input HintHint uses ?attr/colorHint with appropriate opacity.Hint readable, not too faint.Hint #FFFFFF at 100 % on dark surface = low contrast.
8Error UnderlineError color switches from light‑mode red (#B00020) to dark‑mode red (#CF6679).Error clearly visible.Error stays #B00020 on dark surface → barely visible.
9Spinner/ProgressUses ?inner uses ?attr/colorControlActivated`.Color changes with theme.Spinner stays light‑blue (#2196F3) in dark.
10Empty State IllustrationVector assets tinted or have dark variant.No white ghosts on dark surface.White robot illustration on dark bg → low recognizability.
11Contextual Action BarBackground ?attr/colorSurface; text/icons ?attr/colorOnSurface.Action bar legible.Action bar stays light (#FAFAFA) in dark.
12Long‑press HighlightHighlight uses ?attr/colorControlHighlight.Highlight visible.

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