| name | android-test-structure |
| description | Create androidTest directory structure with base classes and utilities |
| category | android |
| version | 1.0.0 |
| inputs | [object Object], [object Object] |
| outputs | app/src/androidTest/, BaseTest.kt, TestUtils.kt |
| verify | test -d app/src/androidTest |
Android Test Structure
Creates androidTest directory structure with base test class and utilities for Espresso testing.
Prerequisites
- Android project with Gradle
- Espresso dependencies added (run
android-espresso-dependenciesfirst) - Package name known
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
| project_path | Yes | . | Android project root |
| package_name | Yes | - | App package (e.g., com.example.app) |
Process
Step 1: Create Directory Structure
# Get package path from package name (com.example.app -> com/example/app)
PACKAGE_PATH=$(echo "${PACKAGE_NAME}" | tr '.' '/')
# Create androidTest directories
mkdir -p "app/src/androidTest/kotlin/${PACKAGE_PATH}/base"
mkdir -p "app/src/androidTest/kotlin/${PACKAGE_PATH}/utils"
mkdir -p "app/src/androidTest/kotlin/${PACKAGE_PATH}/screens"
Step 2: Create BaseTest.kt
Create app/src/androidTest/kotlin/${PACKAGE_PATH}/base/BaseTest.kt:
package ${PACKAGE_NAME}.base
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.rules.ActivityScenarioRule
import org.junit.After
import org.junit.Before
import org.junit.Rule
/**
* Base class for all instrumented tests.
* Provides common setup, teardown, and utilities.
*/
abstract class BaseTest {
protected val context: Context = ApplicationProvider.getApplicationContext()
@Before
open fun setUp() {
// Common setup for all tests
// Override in subclasses for specific setup
}
@After
open fun tearDown() {
// Common cleanup
// Override in subclasses for specific cleanup
}
/**
* Wait for idle state before proceeding
*/
protected fun waitForIdle() {
androidx.test.espresso.Espresso.onIdle()
}
}
Step 3: Create TestUtils.kt
Create app/src/androidTest/kotlin/${PACKAGE_PATH}/utils/TestUtils.kt:
package ${PACKAGE_NAME}.utils
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.UiController
import androidx.test.espresso.ViewAction
import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom
import org.hamcrest.Matcher
object TestUtils {
/**
* Custom action to get RecyclerView item count
*/
fun getRecyclerViewItemCount(recyclerView: RecyclerView): Int {
return recyclerView.adapter?.itemCount ?: 0
}
/**
* Wait for a condition with timeout
*/
fun waitForCondition(
timeoutMs: Long = 5000,
condition: () -> Boolean
): Boolean {
val startTime = System.currentTimeMillis()
while (System.currentTimeMillis() - startTime < timeoutMs) {
if (condition()) return true
Thread.sleep(100)
}
return false
}
/**
* Custom ViewAction to perform click on specific position
*/
fun clickOnViewChild(viewId: Int): ViewAction {
return object : ViewAction {
override fun getConstraints(): Matcher<View>? {
return null
}
override fun getDescription(): String {
return "Click on a child view with specified id."
}
override fun perform(uiController: UiController, view: View) {
val v = view.findViewById<View>(viewId)
v.performClick()
}
}
}
}
Step 4: Create README for Tests
Create app/src/androidTest/README.md:
# Android E2E Tests
This directory contains end-to-end UI tests using Espresso.
## Structure
- `base/` - Base classes for all tests
- `utils/` - Test utilities and helpers
- `screens/` - Screen-specific test classes
## Running Tests
```bash
# All tests
./gradlew connectedAndroidTest
# Specific test class
./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.app.screens.MainActivityTest
Writing Tests
- Extend
BaseTestfor common setup - Use utilities from
TestUtils - Follow AAA pattern: Arrange, Act, Assert
## Verification
**MANDATORY:** Run these commands:
```bash
# Verify directory structure exists
test -d app/src/androidTest && echo "✓ androidTest directory created"
# Verify base classes exist
test -f app/src/androidTest/kotlin/*/base/BaseTest.kt && echo "✓ BaseTest.kt created"
# Verify utils exist
test -f app/src/androidTest/kotlin/*/utils/TestUtils.kt && echo "✓ TestUtils.kt created"
Expected output:
- ✓ androidTest directory created
- ✓ BaseTest.kt created
- ✓ TestUtils.kt created
Outputs
| Output | Location | Description |
|---|---|---|
| Directory structure | app/src/androidTest/ | Test source directory |
| BaseTest class | base/BaseTest.kt | Common test setup |
| Test utilities | utils/TestUtils.kt | Helper functions |
| README | README.md | Test documentation |
Troubleshooting
"Package path incorrect"
Cause: Package name format wrong Fix: Use format: com.example.app (not path format)
"Directory already exists"
Cause: androidTest directory already created Fix: Merge with existing structure, don't overwrite
Completion Criteria
-
app/src/androidTest/directory exists -
base/BaseTest.ktexists -
utils/TestUtils.ktexists -
screens/directory exists - README.md created