Testing¶
How do you define an Android testing strategy?¶
View Answer
Testing strategy should allocate confidence where risk is highest while keeping the feedback loop fast enough that engineers still trust and use it.
In interviews, cover:
-
bias toward unit and small integration tests for logic, and use slower UI or end-to-end tests only where they buy unique confidence
-
tie coverage depth to risk: payments, auth, migrations, and upgrade flows deserve heavier protection than low-impact UI copy
-
define what each layer is responsible for so teams do not duplicate the same assertion in five different suites
-
watch maintenance cost because too many brittle tests create a false sense of safety and slow delivery
-
review incidents and escaped defects to rebalance the strategy over time instead of defending the pyramid dogmatically
Strong answer tip:
- A strong answer makes the strategy feel economic: what is cheap confidence, what is expensive confidence, and where is each worth paying for?
What is the test pyramid and why does it matter?¶
View Answer
Testing strategy should allocate confidence where risk is highest while keeping the feedback loop fast enough that engineers still trust and use it.
In interviews, cover:
-
bias toward unit and small integration tests for logic, and use slower UI or end-to-end tests only where they buy unique confidence
-
tie coverage depth to risk: payments, auth, migrations, and upgrade flows deserve heavier protection than low-impact UI copy
-
define what each layer is responsible for so teams do not duplicate the same assertion in five different suites
-
watch maintenance cost because too many brittle tests create a false sense of safety and slow delivery
-
review incidents and escaped defects to rebalance the strategy over time instead of defending the pyramid dogmatically
Strong answer tip:
- A strong answer makes the strategy feel economic: what is cheap confidence, what is expensive confidence, and where is each worth paying for?
What is the difference between unit and integration tests?¶
View Answer
Testing strategy should allocate confidence where risk is highest while keeping the feedback loop fast enough that engineers still trust and use it.
In interviews, cover:
-
bias toward unit and small integration tests for logic, and use slower UI or end-to-end tests only where they buy unique confidence
-
tie coverage depth to risk: payments, auth, migrations, and upgrade flows deserve heavier protection than low-impact UI copy
-
define what each layer is responsible for so teams do not duplicate the same assertion in five different suites
-
watch maintenance cost because too many brittle tests create a false sense of safety and slow delivery
-
review incidents and escaped defects to rebalance the strategy over time instead of defending the pyramid dogmatically
Strong answer tip:
- A strong answer makes the strategy feel economic: what is cheap confidence, what is expensive confidence, and where is each worth paying for?
How do you unit test a ViewModel?¶
View Answer
Application-layer tests are best when architecture exposes clear seams, deterministic dependencies, and observable outputs instead of framework-heavy hidden behavior.
In interviews, cover:
-
test ViewModels through state transitions and emitted effects, not through Android lifecycle machinery
-
use fakes or test doubles at repository and data-source boundaries so failure paths and caching rules can be exercised deterministically
-
inject clocks, dispatchers, network clients, and stores so logic can be tested without sleeping or global state
-
assert business rules and branching decisions, not the private implementation details used to reach them
-
for repositories with multiple sources, verify precedence, merge logic, and stale-data handling explicitly
Strong answer tip:
- Good testing answers emphasize design-for-testability: clear boundaries make simpler tests possible.
How should use cases be tested?¶
View Answer
Application-layer tests are best when architecture exposes clear seams, deterministic dependencies, and observable outputs instead of framework-heavy hidden behavior.
In interviews, cover:
-
test ViewModels through state transitions and emitted effects, not through Android lifecycle machinery
-
use fakes or test doubles at repository and data-source boundaries so failure paths and caching rules can be exercised deterministically
-
inject clocks, dispatchers, network clients, and stores so logic can be tested without sleeping or global state
-
assert business rules and branching decisions, not the private implementation details used to reach them
-
for repositories with multiple sources, verify precedence, merge logic, and stale-data handling explicitly
Strong answer tip:
- Good testing answers emphasize design-for-testability: clear boundaries make simpler tests possible.
How do you test repository logic with multiple data sources?¶
View Answer
Application-layer tests are best when architecture exposes clear seams, deterministic dependencies, and observable outputs instead of framework-heavy hidden behavior.
In interviews, cover:
-
test ViewModels through state transitions and emitted effects, not through Android lifecycle machinery
-
use fakes or test doubles at repository and data-source boundaries so failure paths and caching rules can be exercised deterministically
-
inject clocks, dispatchers, network clients, and stores so logic can be tested without sleeping or global state
-
assert business rules and branching decisions, not the private implementation details used to reach them
-
for repositories with multiple sources, verify precedence, merge logic, and stale-data handling explicitly
Strong answer tip:
- Good testing answers emphasize design-for-testability: clear boundaries make simpler tests possible.
How do you test remote and local data sources?¶
View Answer
Application-layer tests are best when architecture exposes clear seams, deterministic dependencies, and observable outputs instead of framework-heavy hidden behavior.
In interviews, cover:
-
test ViewModels through state transitions and emitted effects, not through Android lifecycle machinery
-
use fakes or test doubles at repository and data-source boundaries so failure paths and caching rules can be exercised deterministically
-
inject clocks, dispatchers, network clients, and stores so logic can be tested without sleeping or global state
-
assert business rules and branching decisions, not the private implementation details used to reach them
-
for repositories with multiple sources, verify precedence, merge logic, and stale-data handling explicitly
Strong answer tip:
- Good testing answers emphasize design-for-testability: clear boundaries make simpler tests possible.
When should you add integration tests?¶
View Answer
Testing strategy should allocate confidence where risk is highest while keeping the feedback loop fast enough that engineers still trust and use it.
In interviews, cover:
-
bias toward unit and small integration tests for logic, and use slower UI or end-to-end tests only where they buy unique confidence
-
tie coverage depth to risk: payments, auth, migrations, and upgrade flows deserve heavier protection than low-impact UI copy
-
define what each layer is responsible for so teams do not duplicate the same assertion in five different suites
-
watch maintenance cost because too many brittle tests create a false sense of safety and slow delivery
-
review incidents and escaped defects to rebalance the strategy over time instead of defending the pyramid dogmatically
Strong answer tip:
- A strong answer makes the strategy feel economic: what is cheap confidence, what is expensive confidence, and where is each worth paying for?
How do Compose UI tests differ from View UI tests?¶
View Answer
UI and instrumentation tests should validate behavior that lower layers cannot prove, while keeping selectors and synchronization stable enough for long-term trust.
In interviews, cover:
-
prefer user-visible semantics or stable accessibility labels over brittle implementation selectors
-
Compose tests and View-system tests differ mainly in how they surface tree state and synchronization, not in the goal of validating user behavior
-
use Espresso or instrumentation where real platform integration matters, such as permissions, intents, or WebView/system interaction
-
introduce idling resources or explicit synchronization only when true async boundaries exist; over-synchronization hides design issues
-
structure instrumentation modules so they are isolated, shardable, and cheap to run selectively in CI
Strong answer tip:
- Interviewers like hearing how you keep UI tests stable over time, not just that you know how to write them.
Why are semantics important in Compose tests?¶
View Answer
UI and instrumentation tests should validate behavior that lower layers cannot prove, while keeping selectors and synchronization stable enough for long-term trust.
In interviews, cover:
-
prefer user-visible semantics or stable accessibility labels over brittle implementation selectors
-
Compose tests and View-system tests differ mainly in how they surface tree state and synchronization, not in the goal of validating user behavior
-
use Espresso or instrumentation where real platform integration matters, such as permissions, intents, or WebView/system interaction
-
introduce idling resources or explicit synchronization only when true async boundaries exist; over-synchronization hides design issues
-
structure instrumentation modules so they are isolated, shardable, and cheap to run selectively in CI
Strong answer tip:
- Interviewers like hearing how you keep UI tests stable over time, not just that you know how to write them.
When do you still use Espresso?¶
View Answer
UI and instrumentation tests should validate behavior that lower layers cannot prove, while keeping selectors and synchronization stable enough for long-term trust.
In interviews, cover:
-
prefer user-visible semantics or stable accessibility labels over brittle implementation selectors
-
Compose tests and View-system tests differ mainly in how they surface tree state and synchronization, not in the goal of validating user behavior
-
use Espresso or instrumentation where real platform integration matters, such as permissions, intents, or WebView/system interaction
-
introduce idling resources or explicit synchronization only when true async boundaries exist; over-synchronization hides design issues
-
structure instrumentation modules so they are isolated, shardable, and cheap to run selectively in CI
Strong answer tip:
- Interviewers like hearing how you keep UI tests stable over time, not just that you know how to write them.
What are idling resources and when are they needed?¶
View Answer
UI and instrumentation tests should validate behavior that lower layers cannot prove, while keeping selectors and synchronization stable enough for long-term trust.
In interviews, cover:
-
prefer user-visible semantics or stable accessibility labels over brittle implementation selectors
-
Compose tests and View-system tests differ mainly in how they surface tree state and synchronization, not in the goal of validating user behavior
-
use Espresso or instrumentation where real platform integration matters, such as permissions, intents, or WebView/system interaction
-
introduce idling resources or explicit synchronization only when true async boundaries exist; over-synchronization hides design issues
-
structure instrumentation modules so they are isolated, shardable, and cheap to run selectively in CI
Strong answer tip:
- Interviewers like hearing how you keep UI tests stable over time, not just that you know how to write them.
When should you use mocks vs fakes?¶
View Answer
Test doubles should make important behavior easier to observe without freezing tests to incidental implementation details.
In interviews, cover:
-
use mocks to verify specific collaboration when call shape matters, but prefer fakes when behavior and state transitions are more important
-
keep stubs simple and spies rare; once the test is asserting too many interactions, it is often coupled to implementation
-
MockWebServer is valuable because it exercises real serialization, interceptors, retries, and error handling without unstable external dependencies
-
contract tests reduce drift by forcing client and provider expectations to stay synchronized as APIs evolve
-
audit mock usage regularly because excessive mocking often signals boundaries that are too granular or poorly designed
Strong answer tip:
- A strong answer explains why a fake can survive refactors better than a heavily interaction-based mock.
What is the difference between stubs and spies?¶
View Answer
Test doubles should make important behavior easier to observe without freezing tests to incidental implementation details.
In interviews, cover:
-
use mocks to verify specific collaboration when call shape matters, but prefer fakes when behavior and state transitions are more important
-
keep stubs simple and spies rare; once the test is asserting too many interactions, it is often coupled to implementation
-
MockWebServer is valuable because it exercises real serialization, interceptors, retries, and error handling without unstable external dependencies
-
contract tests reduce drift by forcing client and provider expectations to stay synchronized as APIs evolve
-
audit mock usage regularly because excessive mocking often signals boundaries that are too granular or poorly designed
Strong answer tip:
- A strong answer explains why a fake can survive refactors better than a heavily interaction-based mock.
How do you test coroutines deterministically?¶
View Answer
Asynchronous tests should control time and scheduling explicitly so failures are deterministic and meaningful rather than timing-dependent.
In interviews, cover:
-
use test dispatchers and virtual time to advance work instantly instead of sleeping the thread
-
verify Flow and StateFlow through collected emissions and state transitions, especially loading, success, and error boundaries
-
treat one-off SharedFlow events carefully so the test proves exactly-once delivery expectations rather than incidental collection order
-
inject clocks and schedulers so timeout, debounce, retry, and expiry logic can be tested without wall-clock dependence
-
cancel collectors and scopes cleanly in tests to avoid hidden leaks and cross-test interference
Strong answer tip:
- One of the strongest signals here is knowing why
Thread.sleep()is a smell in coroutine tests.
Why is virtual time important for async tests?¶
View Answer
Asynchronous tests should control time and scheduling explicitly so failures are deterministic and meaningful rather than timing-dependent.
In interviews, cover:
-
use test dispatchers and virtual time to advance work instantly instead of sleeping the thread
-
verify Flow and StateFlow through collected emissions and state transitions, especially loading, success, and error boundaries
-
treat one-off SharedFlow events carefully so the test proves exactly-once delivery expectations rather than incidental collection order
-
inject clocks and schedulers so timeout, debounce, retry, and expiry logic can be tested without wall-clock dependence
-
cancel collectors and scopes cleanly in tests to avoid hidden leaks and cross-test interference
Strong answer tip:
- One of the strongest signals here is knowing why
Thread.sleep()is a smell in coroutine tests.
How do you test Flow emissions?¶
View Answer
Asynchronous tests should control time and scheduling explicitly so failures are deterministic and meaningful rather than timing-dependent.
In interviews, cover:
-
use test dispatchers and virtual time to advance work instantly instead of sleeping the thread
-
verify Flow and StateFlow through collected emissions and state transitions, especially loading, success, and error boundaries
-
treat one-off SharedFlow events carefully so the test proves exactly-once delivery expectations rather than incidental collection order
-
inject clocks and schedulers so timeout, debounce, retry, and expiry logic can be tested without wall-clock dependence
-
cancel collectors and scopes cleanly in tests to avoid hidden leaks and cross-test interference
Strong answer tip:
- One of the strongest signals here is knowing why
Thread.sleep()is a smell in coroutine tests.
How do you test StateFlow UI state?¶
View Answer
Asynchronous tests should control time and scheduling explicitly so failures are deterministic and meaningful rather than timing-dependent.
In interviews, cover:
-
use test dispatchers and virtual time to advance work instantly instead of sleeping the thread
-
verify Flow and StateFlow through collected emissions and state transitions, especially loading, success, and error boundaries
-
treat one-off SharedFlow events carefully so the test proves exactly-once delivery expectations rather than incidental collection order
-
inject clocks and schedulers so timeout, debounce, retry, and expiry logic can be tested without wall-clock dependence
-
cancel collectors and scopes cleanly in tests to avoid hidden leaks and cross-test interference
Strong answer tip:
- One of the strongest signals here is knowing why
Thread.sleep()is a smell in coroutine tests.
How do you test one-off SharedFlow events?¶
View Answer
Asynchronous tests should control time and scheduling explicitly so failures are deterministic and meaningful rather than timing-dependent.
In interviews, cover:
-
use test dispatchers and virtual time to advance work instantly instead of sleeping the thread
-
verify Flow and StateFlow through collected emissions and state transitions, especially loading, success, and error boundaries
-
treat one-off SharedFlow events carefully so the test proves exactly-once delivery expectations rather than incidental collection order
-
inject clocks and schedulers so timeout, debounce, retry, and expiry logic can be tested without wall-clock dependence
-
cancel collectors and scopes cleanly in tests to avoid hidden leaks and cross-test interference
Strong answer tip:
- One of the strongest signals here is knowing why
Thread.sleep()is a smell in coroutine tests.
Why use MockWebServer for networking tests?¶
View Answer
Test doubles should make important behavior easier to observe without freezing tests to incidental implementation details.
In interviews, cover:
-
use mocks to verify specific collaboration when call shape matters, but prefer fakes when behavior and state transitions are more important
-
keep stubs simple and spies rare; once the test is asserting too many interactions, it is often coupled to implementation
-
MockWebServer is valuable because it exercises real serialization, interceptors, retries, and error handling without unstable external dependencies
-
contract tests reduce drift by forcing client and provider expectations to stay synchronized as APIs evolve
-
audit mock usage regularly because excessive mocking often signals boundaries that are too granular or poorly designed
Strong answer tip:
- A strong answer explains why a fake can survive refactors better than a heavily interaction-based mock.
How do you keep API tests resilient to server changes?¶
View Answer
Test doubles should make important behavior easier to observe without freezing tests to incidental implementation details.
In interviews, cover:
-
use mocks to verify specific collaboration when call shape matters, but prefer fakes when behavior and state transitions are more important
-
keep stubs simple and spies rare; once the test is asserting too many interactions, it is often coupled to implementation
-
MockWebServer is valuable because it exercises real serialization, interceptors, retries, and error handling without unstable external dependencies
-
contract tests reduce drift by forcing client and provider expectations to stay synchronized as APIs evolve
-
audit mock usage regularly because excessive mocking often signals boundaries that are too granular or poorly designed
Strong answer tip:
- A strong answer explains why a fake can survive refactors better than a heavily interaction-based mock.
How do you test Room with in-memory databases?¶
View Answer
Persistence tests should prove both correctness and upgrade safety, because storage bugs often surface only after real users carry old state into new binaries.
In interviews, cover:
-
use in-memory Room databases for fast repository and DAO validation when persistence fidelity beyond process lifetime is unnecessary
-
write migration tests from real historical schemas so destructive upgrade mistakes are caught before release
-
verify data preservation, default values, index creation, and backfill logic, not just that the migration technically runs
-
exercise realistic edge rows such as nullables, old enums, and partially populated legacy data
-
keep migration ownership explicit because schema changes often outlive the engineer who made them
Strong answer tip:
- Mention that migration tests are insurance against the worst kind of bug: one that only appears on upgrade in production.
Why are Room migration tests critical?¶
View Answer
Persistence tests should prove both correctness and upgrade safety, because storage bugs often surface only after real users carry old state into new binaries.
In interviews, cover:
-
use in-memory Room databases for fast repository and DAO validation when persistence fidelity beyond process lifetime is unnecessary
-
write migration tests from real historical schemas so destructive upgrade mistakes are caught before release
-
verify data preservation, default values, index creation, and backfill logic, not just that the migration technically runs
-
exercise realistic edge rows such as nullables, old enums, and partially populated legacy data
-
keep migration ownership explicit because schema changes often outlive the engineer who made them
Strong answer tip:
- Mention that migration tests are insurance against the worst kind of bug: one that only appears on upgrade in production.
What makes Android architecture testable?¶
View Answer
Application-layer tests are best when architecture exposes clear seams, deterministic dependencies, and observable outputs instead of framework-heavy hidden behavior.
In interviews, cover:
-
test ViewModels through state transitions and emitted effects, not through Android lifecycle machinery
-
use fakes or test doubles at repository and data-source boundaries so failure paths and caching rules can be exercised deterministically
-
inject clocks, dispatchers, network clients, and stores so logic can be tested without sleeping or global state
-
assert business rules and branching decisions, not the private implementation details used to reach them
-
for repositories with multiple sources, verify precedence, merge logic, and stale-data handling explicitly
Strong answer tip:
- Good testing answers emphasize design-for-testability: clear boundaries make simpler tests possible.
How does DI improve testability?¶
View Answer
Application-layer tests are best when architecture exposes clear seams, deterministic dependencies, and observable outputs instead of framework-heavy hidden behavior.
In interviews, cover:
-
test ViewModels through state transitions and emitted effects, not through Android lifecycle machinery
-
use fakes or test doubles at repository and data-source boundaries so failure paths and caching rules can be exercised deterministically
-
inject clocks, dispatchers, network clients, and stores so logic can be tested without sleeping or global state
-
assert business rules and branching decisions, not the private implementation details used to reach them
-
for repositories with multiple sources, verify precedence, merge logic, and stale-data handling explicitly
Strong answer tip:
- Good testing answers emphasize design-for-testability: clear boundaries make simpler tests possible.
What causes flaky tests?¶
View Answer
Flaky tests are a trust problem before they are a tooling problem; once engineers stop believing failures, the suite stops protecting releases.
In interviews, cover:
-
look first for uncontrolled time, shared state, network dependence, and environment variance rather than masking flakiness with retries
-
make tests hermetic by controlling inputs, clocks, storage, and network boundaries wherever practical
-
stabilize UI tests through deterministic selectors, explicit synchronization, and fewer cross-layer assumptions
-
treat environment setup as productized infrastructure with versioned emulator images, seed data, and ownership
-
use retries sparingly and only as incident containment while the root cause is actively being removed
Strong answer tip:
- A mature answer says retries can reduce noise temporarily, but they should never become the long-term strategy.
How do you stabilize flaky UI tests?¶
View Answer
Flaky tests are a trust problem before they are a tooling problem; once engineers stop believing failures, the suite stops protecting releases.
In interviews, cover:
-
look first for uncontrolled time, shared state, network dependence, and environment variance rather than masking flakiness with retries
-
make tests hermetic by controlling inputs, clocks, storage, and network boundaries wherever practical
-
stabilize UI tests through deterministic selectors, explicit synchronization, and fewer cross-layer assumptions
-
treat environment setup as productized infrastructure with versioned emulator images, seed data, and ownership
-
use retries sparingly and only as incident containment while the root cause is actively being removed
Strong answer tip:
- A mature answer says retries can reduce noise temporarily, but they should never become the long-term strategy.
When should you add benchmark tests?¶
View Answer
Specialized test types matter when correctness alone is not enough and you need confidence in performance, visual stability, or assertion quality.
In interviews, cover:
-
benchmark and Macrobenchmark tests validate startup, scrolling, and frame timing regressions that functional tests cannot see
-
snapshot or golden tests are helpful for stable visual surfaces, but require disciplined review of intentional changes
-
visual regression testing works best when rendering is deterministic and the tolerance policy is explicit
-
mutation testing is useful as a spot check on whether unit tests actually detect behavior changes rather than merely executing code paths
-
run these suites where the signal justifies the cost; they are powerful but not cheap
Strong answer tip:
- Strong candidates explain where these tests fit in the release process rather than presenting them as universal defaults.
What does Macrobenchmark validate?¶
View Answer
Specialized test types matter when correctness alone is not enough and you need confidence in performance, visual stability, or assertion quality.
In interviews, cover:
-
benchmark and Macrobenchmark tests validate startup, scrolling, and frame timing regressions that functional tests cannot see
-
snapshot or golden tests are helpful for stable visual surfaces, but require disciplined review of intentional changes
-
visual regression testing works best when rendering is deterministic and the tolerance policy is explicit
-
mutation testing is useful as a spot check on whether unit tests actually detect behavior changes rather than merely executing code paths
-
run these suites where the signal justifies the cost; they are powerful but not cheap
Strong answer tip:
- Strong candidates explain where these tests fit in the release process rather than presenting them as universal defaults.
What are snapshot or golden tests?¶
View Answer
Specialized test types matter when correctness alone is not enough and you need confidence in performance, visual stability, or assertion quality.
In interviews, cover:
-
benchmark and Macrobenchmark tests validate startup, scrolling, and frame timing regressions that functional tests cannot see
-
snapshot or golden tests are helpful for stable visual surfaces, but require disciplined review of intentional changes
-
visual regression testing works best when rendering is deterministic and the tolerance policy is explicit
-
mutation testing is useful as a spot check on whether unit tests actually detect behavior changes rather than merely executing code paths
-
run these suites where the signal justifies the cost; they are powerful but not cheap
Strong answer tip:
- Strong candidates explain where these tests fit in the release process rather than presenting them as universal defaults.
How do visual regression tests fit release safety?¶
View Answer
Specialized test types matter when correctness alone is not enough and you need confidence in performance, visual stability, or assertion quality.
In interviews, cover:
-
benchmark and Macrobenchmark tests validate startup, scrolling, and frame timing regressions that functional tests cannot see
-
snapshot or golden tests are helpful for stable visual surfaces, but require disciplined review of intentional changes
-
visual regression testing works best when rendering is deterministic and the tolerance policy is explicit
-
mutation testing is useful as a spot check on whether unit tests actually detect behavior changes rather than merely executing code paths
-
run these suites where the signal justifies the cost; they are powerful but not cheap
Strong answer tip:
- Strong candidates explain where these tests fit in the release process rather than presenting them as universal defaults.
What is consumer-driven contract testing?¶
View Answer
Test doubles should make important behavior easier to observe without freezing tests to incidental implementation details.
In interviews, cover:
-
use mocks to verify specific collaboration when call shape matters, but prefer fakes when behavior and state transitions are more important
-
keep stubs simple and spies rare; once the test is asserting too many interactions, it is often coupled to implementation
-
MockWebServer is valuable because it exercises real serialization, interceptors, retries, and error handling without unstable external dependencies
-
contract tests reduce drift by forcing client and provider expectations to stay synchronized as APIs evolve
-
audit mock usage regularly because excessive mocking often signals boundaries that are too granular or poorly designed
Strong answer tip:
- A strong answer explains why a fake can survive refactors better than a heavily interaction-based mock.
What are good use cases for end-to-end tests?¶
View Answer
Testing strategy should allocate confidence where risk is highest while keeping the feedback loop fast enough that engineers still trust and use it.
In interviews, cover:
-
bias toward unit and small integration tests for logic, and use slower UI or end-to-end tests only where they buy unique confidence
-
tie coverage depth to risk: payments, auth, migrations, and upgrade flows deserve heavier protection than low-impact UI copy
-
define what each layer is responsible for so teams do not duplicate the same assertion in five different suites
-
watch maintenance cost because too many brittle tests create a false sense of safety and slow delivery
-
review incidents and escaped defects to rebalance the strategy over time instead of defending the pyramid dogmatically
Strong answer tip:
- A strong answer makes the strategy feel economic: what is cheap confidence, what is expensive confidence, and where is each worth paying for?
How should tests gate production releases?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
How do you design a fast CI test pipeline?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
When should you shard test suites?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
What metrics should test reports include?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
How do quality gates prevent regressions?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
Where does mutation testing fit in Android?¶
View Answer
Specialized test types matter when correctness alone is not enough and you need confidence in performance, visual stability, or assertion quality.
In interviews, cover:
-
benchmark and Macrobenchmark tests validate startup, scrolling, and frame timing regressions that functional tests cannot see
-
snapshot or golden tests are helpful for stable visual surfaces, but require disciplined review of intentional changes
-
visual regression testing works best when rendering is deterministic and the tolerance policy is explicit
-
mutation testing is useful as a spot check on whether unit tests actually detect behavior changes rather than merely executing code paths
-
run these suites where the signal justifies the cost; they are powerful but not cheap
Strong answer tip:
- Strong candidates explain where these tests fit in the release process rather than presenting them as universal defaults.
What are hermetic tests and why are they valuable?¶
View Answer
Flaky tests are a trust problem before they are a tooling problem; once engineers stop believing failures, the suite stops protecting releases.
In interviews, cover:
-
look first for uncontrolled time, shared state, network dependence, and environment variance rather than masking flakiness with retries
-
make tests hermetic by controlling inputs, clocks, storage, and network boundaries wherever practical
-
stabilize UI tests through deterministic selectors, explicit synchronization, and fewer cross-layer assumptions
-
treat environment setup as productized infrastructure with versioned emulator images, seed data, and ownership
-
use retries sparingly and only as incident containment while the root cause is actively being removed
Strong answer tip:
- A mature answer says retries can reduce noise temporarily, but they should never become the long-term strategy.
Why use test data builders?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
How does clock abstraction improve test reliability?¶
View Answer
Asynchronous tests should control time and scheduling explicitly so failures are deterministic and meaningful rather than timing-dependent.
In interviews, cover:
-
use test dispatchers and virtual time to advance work instantly instead of sleeping the thread
-
verify Flow and StateFlow through collected emissions and state transitions, especially loading, success, and error boundaries
-
treat one-off SharedFlow events carefully so the test proves exactly-once delivery expectations rather than incidental collection order
-
inject clocks and schedulers so timeout, debounce, retry, and expiry logic can be tested without wall-clock dependence
-
cancel collectors and scopes cleanly in tests to avoid hidden leaks and cross-test interference
Strong answer tip:
- One of the strongest signals here is knowing why
Thread.sleep()is a smell in coroutine tests.
Should flaky tests be fixed with retries?¶
View Answer
Flaky tests are a trust problem before they are a tooling problem; once engineers stop believing failures, the suite stops protecting releases.
In interviews, cover:
-
look first for uncontrolled time, shared state, network dependence, and environment variance rather than masking flakiness with retries
-
make tests hermetic by controlling inputs, clocks, storage, and network boundaries wherever practical
-
stabilize UI tests through deterministic selectors, explicit synchronization, and fewer cross-layer assumptions
-
treat environment setup as productized infrastructure with versioned emulator images, seed data, and ownership
-
use retries sparingly and only as incident containment while the root cause is actively being removed
Strong answer tip:
- A mature answer says retries can reduce noise temporarily, but they should never become the long-term strategy.
How do you structure instrumentation test modules?¶
View Answer
UI and instrumentation tests should validate behavior that lower layers cannot prove, while keeping selectors and synchronization stable enough for long-term trust.
In interviews, cover:
-
prefer user-visible semantics or stable accessibility labels over brittle implementation selectors
-
Compose tests and View-system tests differ mainly in how they surface tree state and synchronization, not in the goal of validating user behavior
-
use Espresso or instrumentation where real platform integration matters, such as permissions, intents, or WebView/system interaction
-
introduce idling resources or explicit synchronization only when true async boundaries exist; over-synchronization hides design issues
-
structure instrumentation modules so they are isolated, shardable, and cheap to run selectively in CI
Strong answer tip:
- Interviewers like hearing how you keep UI tests stable over time, not just that you know how to write them.
How do you manage test environments across teams?¶
View Answer
Flaky tests are a trust problem before they are a tooling problem; once engineers stop believing failures, the suite stops protecting releases.
In interviews, cover:
-
look first for uncontrolled time, shared state, network dependence, and environment variance rather than masking flakiness with retries
-
make tests hermetic by controlling inputs, clocks, storage, and network boundaries wherever practical
-
stabilize UI tests through deterministic selectors, explicit synchronization, and fewer cross-layer assumptions
-
treat environment setup as productized infrastructure with versioned emulator images, seed data, and ownership
-
use retries sparingly and only as incident containment while the root cause is actively being removed
Strong answer tip:
- A mature answer says retries can reduce noise temporarily, but they should never become the long-term strategy.
How do contracts reduce mock drift?¶
View Answer
Test doubles should make important behavior easier to observe without freezing tests to incidental implementation details.
In interviews, cover:
-
use mocks to verify specific collaboration when call shape matters, but prefer fakes when behavior and state transitions are more important
-
keep stubs simple and spies rare; once the test is asserting too many interactions, it is often coupled to implementation
-
MockWebServer is valuable because it exercises real serialization, interceptors, retries, and error handling without unstable external dependencies
-
contract tests reduce drift by forcing client and provider expectations to stay synchronized as APIs evolve
-
audit mock usage regularly because excessive mocking often signals boundaries that are too granular or poorly designed
Strong answer tip:
- A strong answer explains why a fake can survive refactors better than a heavily interaction-based mock.
How should QA and dev collaborate on automation?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
What is risk-based testing?¶
View Answer
Testing strategy should allocate confidence where risk is highest while keeping the feedback loop fast enough that engineers still trust and use it.
In interviews, cover:
-
bias toward unit and small integration tests for logic, and use slower UI or end-to-end tests only where they buy unique confidence
-
tie coverage depth to risk: payments, auth, migrations, and upgrade flows deserve heavier protection than low-impact UI copy
-
define what each layer is responsible for so teams do not duplicate the same assertion in five different suites
-
watch maintenance cost because too many brittle tests create a false sense of safety and slow delivery
-
review incidents and escaped defects to rebalance the strategy over time instead of defending the pyramid dogmatically
Strong answer tip:
- A strong answer makes the strategy feel economic: what is cheap confidence, what is expensive confidence, and where is each worth paying for?
How do you turn incidents into regression tests?¶
View Answer
Release-oriented testing should turn test results into actionable delivery decisions instead of a giant undifferentiated wall of pass/fail output.
In interviews, cover:
-
design CI stages so fast signal arrives first and large suites are sharded or run selectively when risk warrants it
-
report metrics that drive action: flaky rate, suite duration, top failure causes, coverage gaps, and escaped defects
-
convert incidents into targeted regression tests close to the layer where the issue should have been caught
-
partner QA and developers on strategy, environment realism, and ownership rather than treating automation as one sideβs responsibility
-
use test data builders or factory patterns to keep scenario setup readable and maintainable as the domain evolves
Strong answer tip:
- A good answer makes testing feel like an operational feedback system, not just a pile of test frameworks.
How do you manage long-term test maintenance cost?¶
View Answer
Testing strategy should allocate confidence where risk is highest while keeping the feedback loop fast enough that engineers still trust and use it.
In interviews, cover:
-
bias toward unit and small integration tests for logic, and use slower UI or end-to-end tests only where they buy unique confidence
-
tie coverage depth to risk: payments, auth, migrations, and upgrade flows deserve heavier protection than low-impact UI copy
-
define what each layer is responsible for so teams do not duplicate the same assertion in five different suites
-
watch maintenance cost because too many brittle tests create a false sense of safety and slow delivery
-
review incidents and escaped defects to rebalance the strategy over time instead of defending the pyramid dogmatically
Strong answer tip:
- A strong answer makes the strategy feel economic: what is cheap confidence, what is expensive confidence, and where is each worth paying for?