Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions .github/workflows/ui-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: UI Tests CI

on:
push:
branches: [ master ]
paths-ignore: [ '**.md', '**.MD' ]
pull_request:
branches: [ master ]
paths-ignore: [ '**.md', '**.MD' ]
workflow_dispatch:

env:
CI: true

jobs:
ui-test:
runs-on: ubuntu-latest
timeout-minutes: 60

strategy:
matrix:
api-level: [29]
target: [google_apis]

steps:
- uses: actions/checkout@v6

- name: Set up JDK
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: '21'

- name: Cache gradle, wrapper and buildSrc
uses: actions/cache@v5
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-${{ github.job }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.kt') }}
restore-keys: |
${{ runner.os }}-${{ github.job }}-

- name: Make gradlew executable
run: chmod +x ./gradlew

- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: AVD cache
uses: actions/cache@v5
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ matrix.api-level }}-${{ matrix.target }}

- name: Create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
target: ${{ matrix.target }}
arch: x86_64
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "Generated AVD snapshot for caching."

- name: Run instrumented tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
target: ${{ matrix.target }}
arch: x86_64
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: ./gradlew connectedAndroidTest --stacktrace

- name: Upload test reports
if: always()
uses: actions/upload-artifact@v6
with:
name: test-reports-${{ matrix.api-level }}
path: |
app/build/reports/androidTests/connected/
feature-*/build/reports/androidTests/connected/
retention-days: 14

- name: Upload test results
if: always()
uses: actions/upload-artifact@v6
with:
name: test-results-${{ matrix.api-level }}
path: |
app/build/outputs/androidTest-results/
feature-*/build/outputs/androidTest-results/
retention-days: 14
165 changes: 165 additions & 0 deletions UI_TESTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# UI Tests Documentation

This document describes the comprehensive UI tests added to the MVI Coroutines Flow Android application.

## Overview

The UI tests are built using:
- **AndroidJUnit4** for test execution
- **Espresso** for UI interactions and assertions
- **ActivityScenarioRule** for activity lifecycle management
- **Intent testing** for navigation verification

## Test Structure

### App Module Tests (`app/src/androidTest/`)

1. **MainActivityUITest** (ExampleInstrumentedTest.kt)
- Tests user list display via RecyclerView
- Tests SwipeRefreshLayout pull-to-refresh functionality
- Tests menu navigation to Add and Search activities
- Tests error states and retry functionality

2. **NavigationUITest**
- Tests Intent-based navigation from MainActivity to AddActivity
- Tests Intent-based navigation from MainActivity to SearchActivity
- Uses Espresso Intents for verification

3. **AddActivityUITest**
- Tests form field display and input handling
- Tests form validation for email, first name, last name
- Tests add button functionality and validation errors

4. **SearchActivityUITest**
- Tests SearchView display and interaction
- Tests search input and submission
- Tests search results RecyclerView display

5. **IntegrationUITest**
- Tests complete end-to-end user flows
- Tests navigation between multiple activities
- Tests form filling and search workflows
- Tests swipe-to-refresh integration

### Feature Module Tests

1. **feature-main** (`feature-main/src/androidTest/`)
- **MainActivityUITest**: Module-specific tests for MainActivity

2. **feature-add** (`feature-add/src/androidTest/`)
- **AddActivityUITest**: Module-specific tests for AddActivity form functionality

3. **feature-search** (`feature-search/src/androidTest/`)
- **SearchActivityUITest**: Module-specific tests for SearchActivity search functionality

## Test Coverage

### UI Components Tested
- βœ… RecyclerView with user list
- βœ… SwipeRefreshLayout
- βœ… TextInputLayout form fields
- βœ… SearchView in ActionBar
- βœ… Material buttons and progress indicators
- βœ… Error states and retry buttons
- βœ… Navigation drawer/menu

### User Interactions Tested
- βœ… Pull-to-refresh gestures
- βœ… Text input and form validation
- βœ… Menu navigation
- βœ… Search input and submission
- βœ… Button clicks and form submission
- βœ… Back navigation
- βœ… Intent-based navigation between activities

### Error Scenarios Tested
- βœ… Form validation errors (invalid email, empty fields)
- βœ… Network error states with retry functionality
- βœ… Loading states and progress indicators

## Running the Tests

### Prerequisites
- Android device or emulator connected
- App built in debug mode

### Command Line Execution

```bash
# Run all UI tests
./gradlew connectedAndroidTest

# Run specific module tests
./gradlew app:connectedAndroidTest
./gradlew feature-main:connectedAndroidTest
./gradlew feature-add:connectedAndroidTest
./gradlew feature-search:connectedAndroidTest

# Run specific test class
./gradlew app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.hoc.flowmvi.MainActivityUITest

# Run with coverage
./gradlew app:connectedAndroidTest koverGenerateXmlReport
```

### Android Studio Execution

1. Right-click on test class or method
2. Select "Run 'TestName'"
3. View results in Test Results panel

## Test Dependencies

The following dependencies were added to support comprehensive UI testing:

```kotlin
// Core testing framework
androidTestImplementation(libs.androidx.test.junit.ktx)
androidTestImplementation(libs.androidx.test.core.ktx)
androidTestImplementation(libs.androidx.test.rules)

// Espresso UI testing
androidTestImplementation(libs.androidx.test.espresso.core)
androidTestImplementation(libs.androidx.test.espresso.contrib)
androidTestImplementation(libs.androidx.test.espresso.intents)
```

## Test Best Practices

1. **Page Object Pattern**: Consider implementing page objects for complex screens
2. **Test Data**: Use consistent test data across tests
3. **Isolation**: Each test should be independent and not rely on others
4. **Assertions**: Use specific assertions rather than generic ones
5. **Timing**: Use Espresso's built-in waiting mechanisms instead of Thread.sleep()

## Known Limitations

1. **Network Dependencies**: Some tests may require network mocking for consistent results
2. **State Management**: Tests assume certain initial states of the app
3. **Device Dependencies**: Some gestures may behave differently on different devices
4. **Build Configuration**: Tests require the app to be in a testable state (debug build)

## Future Enhancements

1. **Network Mocking**: Add OkHttp MockWebServer for network request testing
2. **Test Data Factory**: Implement test data builders for consistent test data
3. **Screenshot Testing**: Add screenshot comparison testing
4. **Performance Testing**: Add UI performance benchmarking
5. **Accessibility Testing**: Add accessibility verification tests
6. **Cross-platform Testing**: Extend tests for different device configurations

## Troubleshooting

### Common Issues

1. **Resource ID not found**: Ensure the correct module context and R.id references
2. **Activity not found**: Verify activity is exported and properly configured
3. **Test timeouts**: Increase timeout values for slow operations
4. **Flaky tests**: Add proper waits and state verification

### Debug Tips

1. Enable verbose logging with `adb logcat`
2. Use Espresso's layout hierarchy dumps
3. Add screenshot capture on test failure
4. Use debugging mode to step through test execution
57 changes: 57 additions & 0 deletions UI_TESTS_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# UI Tests Summary

This directory contains comprehensive UI tests for the MVI Coroutines Flow Android application.

## Quick Start

1. **Connect an Android device or start an emulator**
2. **Run all tests**:
```bash
./run_ui_tests.sh --all
```

3. **Run specific module tests**:
```bash
./run_ui_tests.sh --app # App module only
./run_ui_tests.sh --features # Feature modules only
```

4. **Generate coverage report**:
```bash
./run_ui_tests.sh --coverage
```

## Test Files Overview

### App Module (`app/src/androidTest/`)
- **MainActivityUITest** - Core app functionality
- **NavigationUITest** - Inter-activity navigation
- **AddActivityUITest** - User creation form
- **SearchActivityUITest** - Search functionality
- **IntegrationUITest** - End-to-end workflows

### Feature Modules
- **feature-main** - MainActivity specific tests
- **feature-add** - AddActivity specific tests
- **feature-search** - SearchActivity specific tests

## Coverage

βœ… **UI Components**: RecyclerView, SwipeRefreshLayout, SearchView, Forms
βœ… **User Interactions**: Touch, swipe, text input, navigation
βœ… **Validation**: Form validation, error states
βœ… **Navigation**: Intent verification, back navigation
βœ… **Integration**: End-to-end user workflows

## Documentation

- **[UI_TESTS.md](UI_TESTS.md)** - Detailed documentation
- **[run_ui_tests.sh](run_ui_tests.sh)** - Test runner script

## Dependencies Added

- `androidx-test-espresso-contrib` - RecyclerView testing
- `androidx-test-espresso-intents` - Intent verification
- `androidx-test-rules` - Additional test rules

The tests provide comprehensive validation of the MVI architecture app's UI functionality and user interactions.
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.junit.ktx)
androidTestImplementation(libs.androidx.test.core.ktx)
androidTestImplementation(libs.androidx.test.rules)
androidTestImplementation(libs.androidx.test.espresso.core)
androidTestImplementation(libs.androidx.test.espresso.contrib)
androidTestImplementation(libs.androidx.test.espresso.intents)

addUnitTest(project = project)
testImplementation(projects.testUtils)
Expand Down
Loading
Loading