Testing Strategy & Automation
Relevant source files
The following files were used as context for generating this wiki page:
The putio-ios project employs a multi-tiered testing strategy designed to ensure application stability, verify API integrations, and maintain localization accuracy. The strategy encompasses unit tests for business logic, end-to-end (E2E) UI automation using mocked network responses, and manual verification protocols for sensitive flows such as authentication and persistence.
Sources: CLAUDE.md:65-72, CONTRIBUTING.md:54-65
Core Testing Tiers
The project categorizes its automated verification into three primary execution paths, each accessible via make commands:
| Command | Purpose | Scope |
|---|---|---|
make verify | Fast unit testing | Logic, model parsing, localization, and Realm migrations. |
make e2e-simulator | Integration testing | Mocked XCUITest flows against a local fixture-backed server. |
make run-simulator | Sanity testing | Manual/Interactive runs with real signed keychain persistence. |
Sources: CLAUDE.md:21-24, CONTRIBUTING.md:54-65
Unit Testing & Logic Verification
Unit tests live under the PutioTests directory and focus on isolated components. Key areas of focus include:
- ViewModel Logic: Validating state transitions and data bucketing (e.g.,
HistoryViewModelTests). - Localization: Ensuring UI elements use correct localized strings (e.g.,
NavigationLocalizationTests). - Persistence: Testing Realm migrations and Keychain access (e.g.,
PutioKeychainTests).
Sources: CLAUDE.md:10, PutioTests/HistoryViewModelTests.swift:14-25, PutioTests/NavigationLocalizationTests.swift:6-18
E2E UI Automation
E2E tests utilize the XCTest framework and XCUIApplication to simulate user interactions. To ensure reliability and speed, these tests run against a mocked API layer.
Mocked API Architecture
The project uses a custom URLProtocol to intercept network requests to api.put.io and serve local JSON fixtures. This allows testing complex flows like video playback resume without requiring a live internet connection or a real account.
The diagram shows how the UI test process interacts with the app process, which intercepts SDK calls using a mock protocol to return local fixtures.
Sources: PutioUITests/PlaybackSmokeUITests.swift:4-10, Putio/Common/API/PutioE2EMockURLProtocol.swift:7-13, Putio/Common/API/PutioSDK.swift:15-22
Test Environment Configuration
The application detects if it is running within a test environment to adjust its behavior, such as bypassing standard SDK configuration or resetting state for E2E runs.
Environment Variables
E2E and UI tests are controlled via specific environment variables passed during application launch:
| Variable | Description | Impact |
|---|---|---|
PUTIO_E2E_MOCK_API | Set to "1" | Enables PutioE2EMockURLProtocol to intercept API calls. |
PUTIO_E2E_ACCESS_TOKEN | String token | Injects a hardcoded token to bypass the login screen. |
PUTIO_E2E_RESET_STATE | Set to "1" | Triggers clearing of Keychain, UserDefaults, and Realm on launch. |
Sources: Putio/AppDelegate.swift:30-40, Putio/Common/API/PutioE2EMockURLProtocol.swift:8-10, PutioUITests/PlaybackSmokeUITests.swift:6-8
State Reset Logic
For E2E tests, the AppDelegate includes a prepareForE2ETestsIfNeeded function. When PUTIO_E2E_RESET_STATE is enabled, the app performs a clean wipe of local data to ensure a deterministic starting point.
This sequence details the teardown of local persistence layers performed before an E2E test run starts.
Sources: Putio/AppDelegate.swift:81-93
Regression Hotspots
The testing strategy emphasizes specific "hotspots" that require mandatory verification before PR submission:
- Authentication & Persistence: Verified by
PutioTests/PutioRealmTests.swiftandPutioTests/ErrorPresentationTests.swift. - Localization:
NavigationLocalizationTests.swiftensures file actions and navigation labels remain consistent across updates. - Playback Flow:
PlaybackSmokeUITests.swiftverifies the resume dialog and video player initialization.
Sources: CLAUDE.md:74-81, PutioUITests/PlaybackSmokeUITests.swift:4-10
Continuous Integration (CI)
The project uses GitHub Actions for automated verification.
- Manual Trigger:
E2E Simulatorworkflow can be triggered manually for PRs or SDK changes. - Automated Gate:
make verifyserves as the primary repository gate that must pass before any code handoff.
Sources: CONTRIBUTING.md:58-61, README.md:12-16
The combination of fixture-backed E2E tests and targeted unit testing allows the project to maintain high confidence in its legacy UIKit and storyboard codebase while iterating on new features.
Sources: CONTRIBUTING.md:92-95