# Macro's Testing Strategy: Local e2e, Integration, and Unit Test Architecture Explained

> Explore Macro's three-layer testing strategy: fast unit tests, cross-crate integration tests, and local e2e tests orchestrated with Docker Compose. Learn how Macro ensures code quality.

- Repository: [Macro/macro](https://github.com/macro-inc/macro)
- Tags: testing
- Published: 2026-08-16

---

**Macro's testing strategy uses a three-layer approach: fast unit tests with `cargo test`, cross-crate integration tests with `cargo nextest`, and full-stack local e2e tests orchestrated via `xtask-local` with Docker Compose services.**

The [macro-inc/macro](https://github.com/macro-inc/macro) codebase implements a disciplined, layered testing architecture that balances developer velocity with production confidence. This article examines how the repository structures its **local end-to-end tests**, **integration tests**, and unit tests, including the exact commands, source files, and safety mechanisms that make this strategy work.

---

## Unit Tests: Fast, Isolated Feedback

Unit tests in Macro follow Rust's standard `#[cfg(test)]` pattern, embedded directly within each crate. These tests validate individual functions and types without external dependencies.

Run unit tests across the workspace:

```bash
just test

```

Many crates also include TypeScript/JavaScript tests under `packages/…/test-utils` for shared front-end logic. This dual-language approach ensures that utility code is verified in both Rust and TypeScript contexts where applicable.

---

## Integration Tests: Cross-Crate Validation

**Integration tests** verify interactions between crates and external services (databases, Kafka, S3). Macro uses **cargo-nextest** as its test runner for this layer, selected via a custom filter.

### Running Integration Tests

```bash
just test-integration

```

This invokes `cargo nextest` with a workspace-level configuration. The CI filter lives in [`tooling/xtask/crates/xtask_nextest_filter/src/test.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_nextest_filter/src/test.rs), where the test suite is identified:

```rust
// tooling/xtask/crates/xtask_nextest_filter/src/test.rs
// Lines 17-20: Integration test selection logic used by CI

```

The filter ensures that integration tests—typically slower and requiring external state—run separately from unit tests, preserving fast feedback loops.

---

## Local End-to-End Tests: Full-Stack Validation

The **local e2e test layer** is Macro's most comprehensive testing tier. It spins up the entire Micro-service architecture—Postgres, Kafka, S3 (via LocalStack), and all application services—within a local Docker environment.

### Core Implementation

The e2e workflow is defined in [`tooling/xtask/crates/xtask_local/src/local/e2e.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/e2e.rs) (lines 15-33), which implements the `xtask-local` binary's e2e command. A wrapper script at [`tooling/scripts/run-local-e2e.sh`](https://github.com/macro-inc/macro/blob/main/tooling/scripts/run-local-e2e.sh) (lines 18-22) handles environment setup:

```bash

# Full local e2e suite (all services + UI tests)

just local-e2e-all

# UI-only e2e tests

just local-e2e-ui

# Specific suite selection

just local-e2e --suite web

```

### CLI Argument Parsing

The `xtask-local` binary parses suite arguments in [`tooling/xtask/crates/xtask_local/src/local/cli.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/cli.rs) (lines 53-56), matching the `LocalE2e` variant to forward tests to the appropriate runner:

- `cargo test` for Rust back-end tests
- `vitest` for front-end tests

---

## E2E Safety Mechanisms and Seed Data

Macro's e2e tests include critical safeguards to prevent accidental data destruction.

### Database URL Validation

Before any seed operation, the code validates that `DATABASE_URL` points to a local instance. This logic resides in [`tooling/seed_cli/src/entity/scenario/mod.rs`](https://github.com/macro-inc/macro/blob/main/tooling/seed_cli/src/entity/scenario/mod.rs) (lines 439-471):

```rust
// Example: Guard that prevents accidental e2e seeding against a non-local DB
fn validate_local_e2e_database_url(database_url: &str) -> anyhow::Result<()> {
    let url = url::Url::parse(database_url)?;
    let host = url.host_str().unwrap_or_default();
    if !(host == "localhost" || host == "127.0.0.1" || host == "postgres") {
        anyhow::bail!(
            "refusing to run local-e2e-smoke seed against DATABASE_URL host={:?}",
            host
        );
    }
    Ok(())
}

```

This function explicitly rejects any host that isn't `localhost`, `127.0.0.1`, or `postgres` (the Docker Compose service name).

### Seed Data Loading

The e2e suite populates the environment with fixture data from `tooling/seed_cli/seed/local_e2e/`:

| File | Purpose |
|------|---------|
| [`manifest.json`](https://github.com/macro-inc/macro/blob/main/manifest.json) | Test scenario definitions |
| [`users.sql`](https://github.com/macro-inc/macro/blob/main/users.sql) / related fixtures | Initial user accounts |
| [`channel_messages.sql`](https://github.com/macro-inc/macro/blob/main/channel_messages.sql) | Sample conversation data |

The seed implementation in [`tooling/seed_cli/src/entity/scenario/mod.rs`](https://github.com/macro-inc/macro/blob/main/tooling/seed_cli/src/entity/scenario/mod.rs) (lines 532-537) logs each step:

```rust
tracing::info!("seeding local e2e smoke documents");
// ... creates users, channels, messages

```

A final "ready" line signals that the environment is prepared for test execution.

---

## Docker Compose Infrastructure

The local e2e environment is defined in [`docker/docker-compose.local-e2e.yml`](https://github.com/macro-inc/macro/blob/main/docker/docker-compose.local-e2e.yml) (lines 6-15), which specifies:

- **Postgres** for relational data
- **LocalStack** for S3-compatible object storage
- **Kafka** for event streaming
- Service-specific overrides for e2e test configurations

This composition mirrors production infrastructure while remaining fully containerized and reproducible on any developer machine.

---

## CI Integration

Macro's continuous integration pipeline leverages the justfile targets for consistent test execution:

| CI Job | Command | Purpose |
|--------|---------|---------|
| Unit + Integration | `just test` | Fast feedback on code changes |
| Full e2e | `just local-e2e-all` | Complete stack validation against temporary Docker environment |

The separation allows PRs to receive rapid unit/integration feedback while full e2e runs provide merge confidence.

---

## Summary

- **Unit tests** (`cargo test`, `just test`) provide millisecond-level feedback on isolated functions.
- **Integration tests** (`cargo nextest`, `just test-integration`) validate cross-crate API contracts with external services.
- **Local e2e tests** (`just local-e2e-*`) exercise the full stack via `xtask-local` with Docker Compose infrastructure.
- **Safety guards** in [`tooling/seed_cli/src/entity/scenario/mod.rs`](https://github.com/macro-inc/macro/blob/main/tooling/seed_cli/src/entity/scenario/mod.rs) prevent accidental production database seeding.
- **Seed data** in `tooling/seed_cli/seed/local_e2e/` ensures reproducible test scenarios.

---

## Frequently Asked Questions

### How do I run only the back-end e2e tests without the UI?

Use `just local-e2e --suite rust` or `cargo test` within the specific crate. The `--suite` argument is parsed in [`tooling/xtask/crates/xtask_local/src/local/cli.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_local/src/local/cli.rs) and forwarded to the Rust test runner.

### What prevents the e2e tests from connecting to my production database?

The `validate_local_e2e_database_url` function in [`tooling/seed_cli/src/entity/scenario/mod.rs`](https://github.com/macro-inc/macro/blob/main/tooling/seed_cli/src/entity/scenario/mod.rs) enforces a whitelist of `localhost`, `127.0.0.1`, and `postgres` hosts. Any other `DATABASE_URL` host triggers an immediate error before any seeding occurs.

### Why does Macro use `cargo nextest` instead of the default test runner?

Nextest provides faster execution through parallelization, clearer output formatting, and programmable test filtering. The custom filter in [`tooling/xtask/crates/xtask_nextest_filter/src/test.rs`](https://github.com/macro-inc/macro/blob/main/tooling/xtask/crates/xtask_nextest_filter/src/test.rs) allows CI to distinguish integration tests from unit tests efficiently.

### Can I run e2e tests without Docker?

No. The local e2e suite depends on [`docker/docker-compose.local-e2e.yml`](https://github.com/macro-inc/macro/blob/main/docker/docker-compose.local-e2e.yml) for Postgres, Kafka, and S3 services. The `xtask-local` binary expects these containers to be available and will fail if the Docker environment is not running.