Test Organization

Back

Loading concept...

πŸ§ͺ Rust Test Organization: Building Your Quality Control Factory

The Story: Your Code Factory Needs Inspectors!

Imagine you’re running a toy factory. You make toys, but before shipping them to kids, you need to check they work properly!

  • Unit tests = Checking each part (like testing if a wheel spins)
  • Integration tests = Checking the whole toy works together (like testing if the car actually drives)

Rust gives you a super organized system to run all these checks. Let’s explore it!


🏭 Integration Tests: Testing the Whole Factory

What Are Integration Tests?

Unit tests check tiny pieces inside your code. But integration tests check if everything works together from the outside.

Think of it like this:

  • Unit test = Testing if the engine starts βœ…
  • Integration test = Testing if the whole car drives βœ…

Integration tests treat your code like a stranger would - they only use what’s publicly available.

Why Separate Them?

Because integration tests are special:

  • They live outside your src folder
  • Each file becomes its own separate test program
  • They can only use your public functions

πŸ“ The tests Directory: Where Big Tests Live

Setting Up Your Test Folder

my_project/
β”œβ”€β”€ Cargo.toml
β”œβ”€β”€ src/
β”‚   └── lib.rs      πŸ‘ˆ Your library code
└── tests/          πŸ‘ˆ Integration tests live here!
    β”œβ”€β”€ test_math.rs
    └── test_strings.rs

Your First Integration Test

Create a file tests/integration_test.rs:

use my_project;  // Import your crate

#[test]
fn it_adds_two() {
    assert_eq!(my_project::add(2, 2), 4);
}

Key Points:

  • Each file in tests/ is a separate crate
  • You must use your library like any external user would
  • Run with: cargo test

Organizing Helper Code

What if tests need to share helper functions?

tests/
β”œβ”€β”€ common/
β”‚   └── mod.rs    πŸ‘ˆ Shared helpers here
β”œβ”€β”€ test_add.rs
└── test_multiply.rs

In tests/common/mod.rs:

pub fn setup() {
    // Shared setup code
}

In your test file:

mod common;

#[test]
fn test_with_setup() {
    common::setup();
    // Your test code
}

Why a subfolder? Files directly in tests/ become test crates. Files in subfolders don’t!


πŸ“– Documentation Tests: Teaching and Testing Together!

The Magic of Doc Tests

Rust has a superpower: code examples in your documentation actually run as tests!

/// Adds two numbers together.
///
/// # Examples
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

When you run cargo test, Rust:

  1. Finds code blocks in your docs
  2. Runs them as tests
  3. Makes sure your examples actually work!

Why Doc Tests Are Brilliant

Problem Without Doc Tests Solution With Doc Tests
Examples get outdated They fail if broken!
Nobody trusts the docs Examples are verified
Extra work to maintain Tests = Documentation

Hiding Setup Code

Sometimes you need extra code, but don’t want to show it:

/// Returns a greeting.
///
/// ```
/// # use my_crate::greet;  // Hidden line!
/// let msg = greet("World");
/// assert_eq!(msg, "Hello, World!");
/// ```
pub fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

Lines starting with # run but don’t appear in docs!


πŸ—‚οΈ Test Organization: The Master Plan

Where Tests Live

graph TD A["Your Rust Project"] --> B["Unit Tests"] A --> C["Integration Tests"] A --> D["Doc Tests"] B --> E["Inside src/ files"] B --> F["#[cfg#40;test#41;] modules"] C --> G["tests/ directory"] C --> H["Each file = separate crate"] D --> I["In /// comments"] D --> J["Code blocks run as tests"]

The Three Test Types

Type Location Purpose
Unit src/*.rs Test private internals
Integration tests/*.rs Test public API
Doc /// comments Verify examples work

Unit Test Module Pattern

// In src/lib.rs or any src file

pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add() {
        assert_eq!(add(1, 1), 2);
    }
}

The #[cfg(test)] means this code only compiles during testing - not in your final program!


πŸ™ˆ Ignoring Tests: β€œNot Today, Test!”

When to Ignore

Sometimes tests:

  • Take too long ⏰
  • Need special setup πŸ”§
  • Are temporarily broken πŸ› οΈ

The #[ignore] Attribute

#[test]
fn quick_test() {
    assert!(true);  // Runs normally
}

#[test]
#[ignore]
fn slow_test() {
    // Takes 10 minutes - skip by default!
    std::thread::sleep(
        std::time::Duration::from_secs(600)
    );
}

Running Ignored Tests

# Run only ignored tests
cargo test -- --ignored

# Run ALL tests (including ignored)
cargo test -- --include-ignored

Adding a Reason

#[test]
#[ignore = "requires database connection"]
fn test_database() {
    // Only run when DB is available
}

🎯 Running Specific Tests: Laser Focus!

Run Tests by Name

# Run tests containing "add"
cargo test add

# Run exact test name
cargo test test_addition

# Run tests in specific module
cargo test math::

Examples in Action

#[test]
fn test_addition() { }

#[test]
fn test_addition_negative() { }

#[test]
fn test_subtraction() { }
cargo test addition
# Runs: test_addition, test_addition_negative
# Skips: test_subtraction

Filter by Test Location

# Only unit tests
cargo test --lib

# Only integration tests
cargo test --test integration_test

# Only doc tests
cargo test --doc

Show All Output

# See println! output even for passing tests
cargo test -- --show-output

# Run tests one at a time (not parallel)
cargo test -- --test-threads=1

πŸŽ“ Your Complete Testing Toolkit

graph TD A["cargo test"] --> B{What to run?} B --> C["Everything"] B --> D["--lib: Unit tests only"] B --> E["--doc: Doc tests only"] B --> F["--test NAME: Specific integration test"] B --> G["FILTER: Tests matching pattern"] C --> H{Options} H --> I["--ignored: Only ignored"] H --> J["--include-ignored: All"] H --> K["--show-output: See prints"] H --> L["--test-threads=1: Sequential"]

πŸš€ Quick Reference

Command What It Does
cargo test Run all tests
cargo test NAME Run tests matching NAME
cargo test --lib Only unit tests
cargo test --doc Only doc tests
cargo test --test FILE Specific integration test
cargo test -- --ignored Only ignored tests
cargo test -- --show-output Show all output

🎯 Remember This!

  1. Integration tests = External tests in tests/ folder
  2. Doc tests = Code in comments that actually runs
  3. #[ignore] = Skip slow/special tests by default
  4. Filter tests = Use cargo test NAME to run specific ones
  5. Shared helpers = Put in tests/common/mod.rs

You now have the complete testing toolkit for Rust! Your code factory has professional-grade quality control. Go build amazing things with confidence! πŸ¦€βœ¨

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.