> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/mullvad/mullvadvpn-app/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing Overview

> Overview of testing infrastructure and test types in Mullvad VPN

Mullvad VPN uses a comprehensive testing strategy that includes unit tests, integration tests, end-to-end (e2e) tests, and UI tests across all platforms. This ensures reliability and quality across the desktop, Android, and iOS applications.

## Test Types

### Unit Tests

Unit tests verify individual components and functions in isolation.

#### Rust Unit Tests

Rust unit tests are embedded within the source code using Rust's built-in testing framework.

**Run all Rust unit tests:**

```bash theme={null}
cargo test --workspace
```

**Run tests for a specific crate:**

```bash theme={null}
cargo test -p mullvad-daemon
cargo test -p mullvad-api
cargo test -p talpid-core
```

**Run with test output visible:**

```bash theme={null}
cargo test -- --nocapture
```

Test dependencies are configured in `Cargo.toml` workspaces with common testing libraries like `proptest` for property-based testing and `insta` for snapshot testing.

#### Desktop Unit Tests (JavaScript/TypeScript)

Unit tests for the desktop application use Vitest as the test runner.

**Run desktop unit tests:**

```bash theme={null}
cd desktop/packages/mullvad-vpn
npm test
```

Unit tests are located in `desktop/packages/mullvad-vpn/test/unit/` and test utilities, helpers, and business logic:

* Account validation (`account-number.spec.ts`)
* Date and time helpers (`date-helper.spec.ts`)
* IP address utilities (`ip.spec.ts`)
* Tunnel state management (`tunnel-state.spec.ts`)
* Notification logic (`notification-evaluation.spec.ts`)

Tests use Vitest with the following configuration in `package.json`:

```json theme={null}
"test": "cross-env NODE_ENV=test vitest test/unit"
```

#### Android Unit Tests

Android unit tests use JUnit5 and are located in module-specific `test/` directories.

**Run Android unit tests:**

```bash theme={null}
cd android
./gradlew testDebugUnitTest
```

**Run tests for a specific module:**

```bash theme={null}
./gradlew :app:testDebugUnitTest
./gradlew :lib:billing:testDebugUnitTest
```

Android test configuration in `app/build.gradle.kts`:

```kotlin theme={null}
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

testOptions {
    unitTests.all { test ->
        test.testLogging {
            test.outputs.upToDateWhen { false }
        }
    }
}
```

#### iOS Unit Tests

iOS unit tests use XCTest and are organized into test targets.

**Run iOS tests via Xcode:**

```bash theme={null}
xcodebuild test -project ios/MullvadVPN.xcodeproj -scheme MullvadVPN
```

iOS test modules include:

* `MullvadRESTTests` - API and REST client tests
* `MullvadRustRuntimeTests` - Rust FFI integration tests
* `MullvadPostQuantumTests` - Post-quantum cryptography tests

### Integration Tests

Integration tests verify interactions between components and with external services.

#### Rust Integration Tests

The test workspace (`test/` directory) contains a dedicated testing framework for end-to-end integration tests.

**Test workspace structure:**

* `test-manager` - Client that runs on the host and orchestrates tests
* `test-runner` - Server that runs in guest VMs and provides RPC interface
* `test-rpc` - Shared RPC interface and types
* `connection-checker` - Network connectivity validation
* `socks-server` - SOCKS proxy for testing

**Build the test runner:**

```bash theme={null}
# Linux
./scripts/container-run.sh ./scripts/build/test-runner.sh linux

# macOS
./scripts/build/test-runner.sh macos

# Windows (cross-compile from Linux)
./scripts/container-run.sh ./scripts/build/test-runner.sh windows
```

**Run integration tests:**

```bash theme={null}
cd test
cargo run --bin test-manager run-tests --vm <vm-name> \
    --display \
    --account <account-number> \
    --app-package <version>
```

### End-to-End Tests

End-to-end tests verify complete user workflows and system behavior.

#### Desktop E2E Tests

Desktop e2e tests use Playwright and are written in TypeScript.

**Test categories:**

* **Mocked tests** (`test/e2e/mocked/`) - Run with mocked backend APIs
* **Installed tests** (`test/e2e/installed/`) - Run against installed application

**Run mocked e2e tests:**

```bash theme={null}
cd desktop/packages/mullvad-vpn
npm run e2e
```

**Run without rebuilding:**

```bash theme={null}
npm run e2e:no-build
```

**Run installed app tests:**

```bash theme={null}
npm run e2e:sequential
```

**Update test snapshots:**

```bash theme={null}
npm run e2e:update-snapshots
```

Playwright configuration is in `playwright.config.ts` and `test/e2e/installed/playwright.config.ts`.

#### Android E2E Tests

Android e2e tests are instrumented tests that run on real devices or emulators.

**Run Android e2e tests:**

```bash theme={null}
cd android
./gradlew :test:e2e:connectedDebugAndroidTest \
    -Pmullvad.test.e2e.prod.accountNumber.valid=<account> \
    -Pmullvad.test.e2e.prod.accountNumber.invalid=<invalid-account>
```

Android e2e tests require:

* Valid Mullvad account number for authentication tests
* Invalid account number for negative test cases
* Access to Mullvad public infrastructure and APIs

Test artifacts are stored in `/sdcard/Download/test-attachments` on the test device.

### UI/Graphical Tests

UI tests verify visual and interactive elements of the application.

#### Desktop UI Tests

Desktop UI tests are written in TypeScript using Playwright and located in `desktop/packages/mullvad-vpn/test/e2e/`.

**Key test areas:**

* Login flows (`login.spec.ts`)
* Account expiry (`account-expiry.spec.ts`)
* Connection states (`main.spec.ts`)
* Settings screens (`settings.spec.ts`)
* Location selection (`select-location/`)
* Notifications (`notifications.spec.ts`)
* Split tunneling (`split-tunneling.spec.ts`)

**Build test executable:**

```bash theme={null}
cd desktop/packages/mullvad-vpn
npm run build-test-executable
```

UI tests can be invoked from Rust integration tests:

```rust theme={null}
test_manager::tests::ui::run_test(&rpc, &["gui-test.spec"]).await.unwrap()
```

## Test Infrastructure

### Test Manager Framework

The test-manager provides a framework for writing integration tests:

```rust theme={null}
#[test_function]
pub async fn test(
    rpc: ServiceClient,
    mut mullvad_client: mullvad_management_interface::MullvadProxyClient,
) -> Result<(), Error> {
    // Test implementation
    Ok(())
}
```

Test modules in `test-manager/src/tests/`:

* `account.rs` - Account management tests
* `config.rs` - Configuration tests
* `dns.rs` - DNS functionality tests
* `tunnel.rs` - VPN tunnel tests
* `tunnel_state.rs` - Tunnel state management
* `access_methods.rs` - API access method tests
* `audits/` - Security audit verification tests

### CI/CD Testing

Tests run automatically in GitHub Actions:

**Desktop tests:**

```bash theme={null}
cd desktop && npm run test --workspaces --if-present
```

**Android tests:**

```bash theme={null}
./gradlew testDebugUnitTest
./gradlew connectedDebugAndroidTest
```

**Rust tests:**

```bash theme={null}
cargo test --workspace
```

## Running All Tests

To run all tests across the project:

```bash theme={null}
# Rust tests
cargo test --workspace

# Desktop tests
cd desktop
npm run test --workspaces --if-present

# Desktop e2e tests
cd packages/mullvad-vpn
npm run e2e

# Android tests
cd ../../android
./gradlew testDebugUnitTest
```

## Test Configuration

### Workspace Configuration

The root `Cargo.toml` defines workspace-wide test dependencies:

```toml theme={null}
[workspace.dependencies]
insta = { version = "1.42", features = ["yaml"] }
proptest = "1.9"
```

### Linting and Code Quality

Tests must pass the same linting rules as production code:

```bash theme={null}
# Rust
cargo clippy --all-targets --all-features

# Desktop
cd desktop && npm run lint

# Android
cd android && ./gradlew lint
```

## Best Practices

1. **Write tests alongside code** - Unit tests should be close to the code they test
2. **Use descriptive test names** - Test names should clearly indicate what is being tested
3. **Test edge cases** - Include tests for error conditions and boundary cases
4. **Keep tests fast** - Unit tests should run quickly; save longer tests for integration
5. **Mock external dependencies** - Use mocked backends for faster and more reliable tests
6. **Use test fixtures** - Share common test setup code across tests
7. **Test public interfaces** - Focus on testing public APIs rather than internal implementation

## Related Documentation

* [Platform-Specific Testing](/development/platform-specific-testing)
* [Architecture Overview](/development/architecture-overview)
* [Build Instructions](/development/building)
