Skip to main content
Testing is crucial for maintaining code quality and preventing regressions. This guide covers testing practices for both Flutter and Rust components.

Testing Philosophy

AppFlowy follows a comprehensive testing strategy:

Unit Tests

Test individual functions and classes in isolation

Widget Tests

Test Flutter widgets and UI components

Integration Tests

Test complete user flows and features

Rust Tests

Test Rust backend logic and modules

Flutter Testing

Unit Tests

Unit tests verify individual functions and business logic:

Widget Tests

Widget tests verify UI components:

BLoC Tests

Test state management with BLoCs:

Integration Tests

Integration tests verify complete user flows:

Running Flutter Tests

1

Run all tests

2

Run specific test file

3

Run tests with coverage

View coverage report:
4

Run integration tests

Using cargo-make for Dart Tests

AppFlowy provides convenient cargo-make tasks:

Rust Testing

Unit Tests

Rust unit tests are written inline with the code:

Async Tests

Test async functions with tokio::test:

Integration Tests

Integration tests are in the tests/ directory:

Running Rust Tests

1

Run all tests

2

Run specific module tests

3

Run tests with output

4

Run single test

Using cargo-make for Rust Tests

Test Backend

AppFlowy provides a test backend for Flutter tests:
1

Build test backend

This builds the Rust backend with test-specific configuration.
2

Run tests

The test backend is automatically loaded when running Dart tests.
The test backend is built as a dynamic library (cdylib) for easier loading in tests.

Mocking and Test Doubles

Dart Mocking

Use mockito for creating mocks:

Rust Mocking

Use traits for dependency injection:

Test Coverage

Flutter Coverage

1

Generate coverage

2

View HTML report

Rust Coverage

1

Install grcov

2

Run tests with coverage

3

View report

CI/CD Testing

AppFlowy runs automated tests on all pull requests:

GitHub Actions Workflow

Required Checks

All PRs must pass:
  • ✅ Dart unit tests
  • ✅ Rust unit tests
  • ✅ Integration tests
  • ✅ Code formatting
  • ✅ Linting
PRs with failing tests will not be merged.

Best Practices

Write Tests First

Consider TDD: write tests before implementing features

Test Behavior

Test what the code does, not how it does it

Keep Tests Fast

Fast tests = frequent testing = better quality

Isolate Tests

Each test should be independent and repeatable

Use Descriptive Names

Test names should explain what is being tested

Arrange-Act-Assert

Structure tests clearly: setup, execute, verify

Test Structure

Follow the AAA pattern:

Troubleshooting

Flutter Tests Fail

Rust Tests Fail

Next Steps

Contributing

Contribute your changes with tests

Code Style

Follow coding conventions

Building

Build AppFlowy from source

Architecture

Understand the architecture