# Testing Guide - StreamPlayer This document explains how to run and maintain tests for the StreamPlayer application. ## Test Structure The project has two types of tests: 1. **Unit Tests** (`app/src/test/`) - Run on the JVM (no device/emulator needed) - Test business logic in isolation - Located in: `app/src/test/java/com/streamplayer/` 2. **Integration Tests** (`app/src/androidTest/`) - Run on Android device/emulator - Test UI interactions and component integration - Located in: `app/src/androidTest/java/com/streamplayer/` ## Running Tests ### Unit Tests Run all unit tests: ```bash ./gradlew test ``` Run specific test class: ```bash ./gradlew test --tests StreamUrlResolverTest ``` Run with coverage report: ```bash ./gradlew test jacocoTestReport ``` ### Integration Tests Run all integration tests: ```bash ./gradlew connectedAndroidTest ``` Run specific test class: ```bash ./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.streamplayer.PlayerIntegrationTest ``` ### All Tests Run both unit and integration tests: ```bash ./gradlew test connectedAndroidTest ``` ## Test Files ### Unit Tests 1. **StreamUrlResolverTest.java** - Tests for `parseVersionCode()` and `deriveGroupName()` methods - Tests JSON parsing with Gson - Tests various edge cases and error conditions 2. **EventRepositoryTest.java** - Tests for EventItem model - Tests Gson serialization/deserialization - Tests filtering, sorting, and grouping operations ### Integration Tests 1. **PlayerIntegrationTest.java** - Tests channel playback flow - Tests navigation between activities - Tests error handling during playback 2. **UpdateFlowIntegrationTest.java** - Tests update check flow - Tests update download and installation - Tests error handling during updates ## Test Coverage The tests aim to cover: - ✅ All public methods in critical classes - ✅ Happy path scenarios - ✅ Error conditions and edge cases - ✅ JSON serialization/deserialization - ✅ UI navigation flows - ✅ Integration between components ## Dependencies ### Testing Libraries - **JUnit 4**: Unit testing framework - **Mockito**: Mocking framework for unit tests - **Espresso**: UI testing framework - **UiAutomator**: Cross-app UI testing - **Robolectric**: Android unit testing on JVM ### Added Dependencies The following dependencies have been added to `build.gradle`: ```gradle // Unit testing testImplementation 'junit:junit:4.13.2' testImplementation 'org.mockito:mockito-core:5.7.0' testImplementation 'org.mockito:mockito-inline:5.2.0' testImplementation 'androidx.arch.core:core-testing:2.2.0' testImplementation 'org.robolectric:robolectric:4.11.1' // Integration testing androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1' androidTestImplementation 'androidx.test.espresso:espresso-intents:3.5.1' androidTestImplementation 'androidx.test:runner:1.5.2' androidTestImplementation 'androidx.test:rules:1.5.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' ``` ## Best Practices 1. **Test Naming**: Use descriptive names that explain what is being tested - Good: `testParseVersionCode_withValidInput_returnsCorrectCode()` - Bad: `test1()` 2. **Test Structure**: Follow AAA pattern (Arrange, Act, Assert) - Arrange: Set up test data and conditions - Act: Perform the action being tested - Assert: Verify the expected results 3. **Test Independence**: Each test should be independent and not rely on other tests 4. **Test Data**: Use meaningful test data that covers edge cases 5. **Mocking**: Mock external dependencies (network, database, etc.) 6. **Coverage**: Aim for high code coverage but focus on testing behavior, not implementation ## Continuous Integration Tests should be run automatically on: - Every pull request - Before releases - Nightly builds ## Troubleshooting ### Unit Tests 1. **Mockito Issues**: If you get "Mockito cannot mock this class", check: - Add `@RunWith(MockitoJUnitRunner.class)` to test class - Ensure `mockito-inline` dependency is included 2. **Robolectric Issues**: If tests fail with Robolectric: - Check SDK version compatibility - Add `@Config` annotation with correct SDK version ### Integration Tests 1. **Emulator Issues**: - Ensure emulator is running or device is connected - Check that developer options and USB debugging are enabled 2. **Timing Issues**: Add proper waits and delays: ```java Thread.sleep(1000); // Simple delay device.wait(Until.hasObject(By.pkg("com.streamplayer")), 5000); ``` 3. **Permission Issues**: Add necessary permissions to test manifest ## Future Improvements 1. Add more unit tests for other classes 2. Implement test doubles for network layer 3. Add performance tests 4. Add screenshot tests for UI regression testing 5. Implement mutation testing to verify test quality 6. Add integration tests for error scenarios 7. Implement automated test reporting ## Firebase Configuration To use Firebase services (Crashlytics, Analytics, Performance): 1. Download `google-services.json` from Firebase Console 2. Place it in `app/` directory (replace the example file) 3. Firebase plugins are already configured in `build.gradle` ## LeakCanary LeakCanary is included for debug builds to detect memory leaks: ```gradle debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12' ``` Check logcat for leak analysis results when testing on device/emulator. ## ProGuard/R8 ProGuard rules have been updated to keep test-related classes: - Keep ExoPlayer classes - Keep OkHttp classes - Keep Gson model classes - Keep test classes and methods ## Resources - [Android Testing Documentation](https://developer.android.com/training/testing) - [JUnit 4 Documentation](https://junit.org/junit4/) - [Mockito Documentation](https://site.mockito.org/) - [Espresso Documentation](https://developer.android.com/training/testing/espresso)