Rust: Rust Testing and Documentation

Last updated: 2026-08-26

Testing is the "quality inspector" of code—let testing find bugs before users do. Documentation is the "instruction manual" of code—it not only tells others how to use it, but also reminds your future self why you wrote it that way.

If writing code is like "building a house," then testing is the "quality inspection report," and documentation is the "user manual." Would you dare to move into a house that hasn't been tested? The core concept of TDD (Test-Driven Development) is simple: write the tests first, then the code—just like setting quality standards before manufacturing a product.


1. What You'll Learn



2. The Story of a Quality Inspector

(1) The Struggle: Factories Without Quality Control

Bob is a quality control inspector at an auto plant. Shortly after starting his job, he discovered a shocking fact:

"If every car were tested before leaving the factory, customers wouldn't end up with square steering wheels..."

(2) Approaches to Testing and Documentation in Rust

Rust provides a complete set of testing and documentation tools, much like the quality management system of a well-run factory:

TEXT 📖 Display only
Factory(Rust Project)           → Automobile Production Line
  Unit Testing(Unit Test)      → Check the quality of each part
  Document Testing(Doc Test)       → Examples included in the manual
  Integration Testing(Integration Test)→ Vehicle Road Testing
  Benchmarking(Benchmark)       → Performance Testing
  Document Notes(cargo doc)       → Complete User Manual
RUST
/// Calculate the greatest common divisor of two numbers(GCD)
///
/// Using the Euclidean Algorithm:Repeat the modulo operation until the remainder is 0
///
/// # Example
///
/// ```
/// let result = gcd(12, 8);
/// assert_eq!(result, 4);
/// ```
fn gcd(a: u64, b: u64) -> u64 {
    if b == 0 { a } else { gcd(b, a % b) }
}

#[test]
fn test_gcd() {
    assert_eq!(gcd(12, 8), 4);
    assert_eq!(gcd(7, 13), 1);  // Coprime Numbers
    assert_eq!(gcd(100, 10), 10);
}

Rust's testing framework is like a quality control assembly line: #[test] marks each "quality control station," cargo test starts the entire assembly line, and assert_eq! represents the quality control standards. /// documentation comments are like the "instructions" attached to each part, and cargo doc binds all the instructions into a single booklet.



3. Core Concepts

(1) Testing and Documentation Framework

100%
graph TB
    A[Rust Testing and Documentation] --> B[Test System]
    A --> C[Document Management System]

    B --> B1["#[test] Mark the test function"]
    B --> B2["cargo test Run Test"]
    B --> B3["Assertion Macro assert! / assert_eq! / assert_ne!"]
    B --> B4["#[should_panic] Test Anxiety"]
    B --> B5["#[cfg(test)] Conditional Compilation"]
    B --> B6["tests/ Integration Test Directory"]

    C --> C1["/// Document Notes"]
    C --> C2["cargo doc Generate HTML"]
    C --> C3["Document Testing Doc-tests"]
    C --> C4["cargo doc --open Open your browser"]

    B1 --> D1[Unit Testing]
    B6 --> D2[Integration Testing]

    C1 --> D3[API Document]
    C3 --> D4[Working sample code]

(2) Comparison of Test Types

Test Type Keyword/Location Test Scope Analogy Applicable Scenarios
Unit Testing #[test] + #[cfg(test)] Individual functions or modules Check each component Verify function logic
Document Testing Code blocks in /// API sample code Examples included in the manual Ensure that the examples in the documentation are functional
Integration Testing The .rs file in the tests/ directory Overall behavior of external APIs Vehicle road testing Verification of inter-module collaboration
Benchmark #[bench] / cargo bench Performance Metrics Speed Test Performance-Sensitive Code

(3) Comparison of Assertion Macros

Macro Purpose Success Conditions Failure Message
assert!(expr) Boolean Conditions expr == true assertion failed: expr
assert_eq!(a, b) Equivalence a == b assertion failed: (left == right)
assert_ne!(a, b) Asymmetry a != b assertion failed: (left != right)


4. Testing and Documentation Examples

▶ Example 1: Unit Tests and Assertion Macros (Difficulty ⭐)

Output:

TEXT 📖 Display only
=== Calculator Feature Demo ===
add(10, 5) = <add(10, 5)>
subtract(10, 5) = <subtract(10, 5)>
divide(10, 3) = <divide(10, 3)>
is_even(7) = <is_even(7)>
max_of_three(3, 7, 5) = <max_of_three(3, 7, 5)>

Run `cargo test` Run all the tests
RUST
// ============================================
// Unit Testing Basics: #[test] + Assertion Macro
// Demo: A Simple Calculator Function and Its Tests
// Quality control inspectors check each calculation function
// ============================================

/// Addition: Returns a + b
fn add(a: i32, b: i32) -> i32 {
    a + b
}

/// Subtraction: Returns a - b
fn subtract(a: i32, b: i32) -> i32 {
    a - b
}

/// Division: Returns a / b, panics if b == 0
fn divide(a: i32, b: i32) -> i32 {
    if b == 0 {
        panic!("division by zero is not allowed!");
    }
    a / b
}

/// Determining Whether a Number Is Even
fn is_even(n: i32) -> bool {
    n % 2 == 0
}

/// Find the Maximum Value
fn max_of_three(a: i32, b: i32, c: i32) -> i32 {
    let mut max = a;
    if b > max { max = b; }
    if c > max { max = c; }
    max
}

fn main() {
    println!("=== Calculator Feature Demo ===");
    println!("add(10, 5) = {}", add(10, 5));
    println!("subtract(10, 5) = {}", subtract(10, 5));
    println!("divide(10, 3) = {}", divide(10, 3));
    println!("is_even(7) = {}", is_even(7));
    println!("max_of_three(3, 7, 5) = {}", max_of_three(3, 7, 5));
    println!();
    println!("Run `cargo test` Run all the tests");
}

// ============================================
// Test Module —— Only at cargo test Compiled by Shi
// ============================================
#[cfg(test)]
mod tests {
    // Import all functions from the parent module
    use super::*;

    #[test]
    fn test_add_positive() {
        assert_eq!(add(2, 3), 5);
    }

    #[test]
    fn test_add_negative() {
        assert_eq!(add(-2, -3), -5);
    }

    #[test]
    fn test_add_zero() {
        assert_eq!(add(0, 0), 0);
    }

    #[test]
    fn test_subtract() {
        assert_eq!(subtract(10, 4), 6);
        assert_eq!(subtract(4, 10), -6);  // Negative results
    }

    #[test]
    fn test_divide_normal() {
        assert_eq!(divide(10, 3), 3);  // Truncated Integer Division
    }

    #[test]
    #[should_panic(expected = "division by zero is not allowed!")]
    fn test_divide_by_zero() {
        divide(10, 0);  // Expectations panic
    }

    #[test]
    fn test_is_even() {
        assert!(is_even(4));    // 4 It is an even number
        assert!(!is_even(7));   // 7 Not an even number
        assert_eq!(is_even(0), true);
    }

    #[test]
    fn test_max_of_three() {
        assert_eq!(max_of_three(1, 2, 3), 3);
        assert_eq!(max_of_three(5, 1, 2), 5);
        assert_eq!(max_of_three(1, 5, 2), 5);
        assert_eq!(max_of_three(-1, -5, -3), -1);
    }

    #[test]
    fn test_assert_ne_macro() {
        // assert_ne! Verify that two values are not equal
        assert_ne!(add(1, 1), 3);
        assert_ne!(subtract(100, 50), 100);
    }
}

Output:

TEXT 📖 Display only
=== Calculator Feature Demo ===
add(10, 5) = 15
subtract(10, 5) = 5
divide(10, 3) = 3
is_even(7) = false
max_of_three(3, 7, 5) = 7

Run `cargo test` Run all the tests

Test Output (cargo test):

TEXT 📖 Display only
running 9 tests
test tests::test_assert_ne_macro ... ok
test tests::test_add_negative ... ok
test tests::test_add_positive ... ok
test tests::test_add_zero ... ok
test tests::test_divide_by_zero ... ok
test tests::test_divide_normal ... ok
test tests::test_is_even ... ok
test tests::test_max_of_three ... ok
test tests::test_subtract ... ok

test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

The test module is wrapped in #[cfg(test)], which means "compile only in test mode"—this code will not be present at all in production builds (cargo build --release). use super::* imports all functions from the parent module (i.e., the main code in the current file). #[should_panic(expected = "...")] verifies that a function will correctly trigger a panic under specific conditions.


▶ Example 2: Document Annotations and cargo doc (Difficulty: ⭐⭐)

Output:

TEXT 📖 Display only
=== String Library Demo ===
reverse('rust') = '<reverse("rust")>'
word_count('hello world from Rust') = <word_count("hello world from Rust")>
truncate('hello world', 5) = '<truncate("hello world", 5)>'
truncate('Hello, World', 2) = '<truncate("Hello, World", 2)>'
is_palindrome('racecar') = <is_palindrome("racecar")>
is_palindrome('A man a plan a canal Panama') = <is_palindrome("A man a plan a canal Panama")>
is_palindrome('hello') = <is_palindrome("hello")>

Usage `cargo doc --open` Generate and View HTML Document
Usage `cargo test` Run the documentation tests (doc-tests)
RUST
// ============================================
// Document Notes /// and cargo doc Generate HTML Document
// Demo: Write a complete API Document
// Includes document testing (doc-tests)
// ============================================

/// String Processing Toolkit
///
/// Provides common string manipulation functions,Including reversals、Excerpt、Statistics, etc.。
/// All functions are pure functions (do not modify the input, return a new value).
///
/// # Example
///
/// ```
/// use docs_demo::string_utils;
///
/// let reversed = string_utils::reverse("hello");
/// assert_eq!(reversed, "olleh");
/// ```
pub mod string_utils {

    /// Reverse a String
    ///
    /// Reverse the order of the characters in the input string。
    ///
    /// # Parameters
    ///
    /// * `s` - The string slice to be reversed
    ///
    /// # Return Value
    ///
    /// Return the new value after reversal `String`。
    ///
    /// # Example
    ///
    /// ```
    /// use docs_demo::string_utils::reverse;
    ///
    /// assert_eq!(reverse("rust"), "tsur");
    /// assert_eq!(reverse(""), "");
    /// assert_eq!(reverse("a"), "a");
    /// ```
    pub fn reverse(s: &str) -> String {
        s.chars().rev().collect()
    }

    /// Count the number of words in a string
    ///
    /// Count the number of non-empty words, separated by spaces。
    ///
    /// # Parameters
    ///
    /// * `s` - Strings to be counted
    ///
    /// # Return Value
    ///
    /// Back `usize` Number of Words by Type。
    ///
    /// # Example
    ///
    /// ```
    /// use docs_demo::string_utils::word_count;
    ///
    /// assert_eq!(word_count("hello world"), 2);
    /// assert_eq!(word_count(""), 0);
    /// assert_eq!(word_count("  spaces  "), 0);  // Only spaces
    /// ```
    pub fn word_count(s: &str) -> usize {
        s.split_whitespace().count()
    }

    /// Extract the first part of a string n characters
    ///
    /// Safe Handling UTF-8 Character Boundary,No panic。
    /// If `n` Greater than the string length,Return the entire string。
    ///
    /// # Parameters
    ///
    /// * `s` - Original string
    /// * `n` - Number of characters to extract
    ///
    /// # Return Value
    ///
    /// Returns the sliced string。
    ///
    /// # Example
    ///
    /// ```
    /// use docs_demo::string_utils::truncate;
    ///
    /// assert_eq!(truncate("hello world", 5), "hello");
    /// assert_eq!(truncate("Hello", 2), "He");
    /// assert_eq!(truncate("short", 100), "short");
    /// ```
    pub fn truncate(s: &str, n: usize) -> &str {
        // Usage char_indices Safe Handling UTF-8 Boundary
        if n >= s.chars().count() {
            return s;
        }
        let end = s.char_indices()
            .nth(n)
            .map(|(idx, _)| idx)
            .unwrap_or(s.len());
        &s[..end]
    }

    /// Check if a string is a palindrome
    ///
    /// Ignore case and spaces,Compare only alphanumeric characters。
    ///
    /// # Parameters
    ///
    /// * `s` - String to be checked
    ///
    /// # Return Value
    ///
    /// Returns true if the string is a palindrome `true`。
    ///
    /// # Example
    ///
    /// ```
    /// use docs_demo::string_utils::is_palindrome;
    ///
    /// assert!(is_palindrome("racecar"));
    /// assert!(is_palindrome("A man a plan a canal Panama"));
    /// assert!(!is_palindrome("hello"));
    /// ```
    pub fn is_palindrome(s: &str) -> bool {
        let cleaned: String = s.chars()
            .filter(|c| c.is_alphanumeric())
            .map(|c| c.to_ascii_lowercase())
            .collect();
        cleaned == cleaned.chars().rev().collect::<String>()
    }
}

fn main() {
    use string_utils::*;

    println!("=== String Library Demo ===");
    println!("reverse('rust') = '{}'", reverse("rust"));
    println!("word_count('hello world from Rust') = {}", word_count("hello world from Rust"));
    println!("truncate('hello world', 5) = '{}'", truncate("hello world", 5));
    println!("truncate('Hello, World', 2) = '{}'", truncate("Hello, World", 2));
    println!("is_palindrome('racecar') = {}", is_palindrome("racecar"));
    println!("is_palindrome('A man a plan a canal Panama') = {}", is_palindrome("A man a plan a canal Panama"));
    println!("is_palindrome('hello') = {}", is_palindrome("hello"));
    println!();
    println!("Usage `cargo doc --open` Generate and View HTML Document");
    println!("Usage `cargo test` Run the documentation tests (doc-tests)");
}

// ============================================
// Unit Testing —— Implementation of the Verification Function
// ============================================
#[cfg(test)]
mod tests {
    use super::string_utils::*;

    #[test]
    fn test_reverse() {
        assert_eq!(reverse("hello"), "olleh");
        assert_eq!(reverse("Rust"), "tsuR");
        assert_eq!(reverse(""), "");
    }

    #[test]
    fn test_word_count() {
        assert_eq!(word_count("one two three"), 3);
        assert_eq!(word_count(""), 0);
        assert_eq!(word_count("   "), 0);
        assert_eq!(word_count("a"), 1);
    }

    #[test]
    fn test_truncate() {
        assert_eq!(truncate("hello world", 5), "hello");
        assert_eq!(truncate("Hello, World", 2), "Hello");
        assert_eq!(truncate("short", 10), "short");
    }

    #[test]
    fn test_is_palindrome() {
        assert!(is_palindrome("racecar"));
        assert!(is_palindrome("level"));
        assert!(is_palindrome("A man a plan a canal Panama"));
        assert!(!is_palindrome("hello"));
        assert!(is_palindrome(""));
    }
}

Output:

TEXT 📖 Display only
=== String Library Demo ===
reverse('rust') = 'tsur'
word_count('hello world from Rust') = 4
truncate('hello world', 5) = 'hello'
truncate('Hello, World', 2) = 'Hello'
is_palindrome('racecar') = true
is_palindrome('A man a plan a canal Panama') = true
is_palindrome('hello') = false

Usage `cargo doc --open` Generate and View HTML Document
Usage `cargo test` Run the documentation tests (doc-tests)

/// Documentation comments use Markdown format and support sections such as # Examples, # Parameters, and # Return Value. Sample code in code blocks automatically becomes "doc-tests"—cargo test compiles and runs these code blocks to ensure that the examples in the documentation are always functional. cargo doc --open generates beautiful HTML documentation and opens it in a browser.


▶ Example 3: Integration Testing and Test Organization (Difficulty ⭐⭐)

Output:

TEXT 📖 Display only
=== Statistical Tools Demo ===
Data: <&data[..]>
sum = <sum(&data)>
average = <average(&data)>
median = <median(&mut data.to_vec()).unwrap()>
min = <min(&data).unwrap()>
max = <max(&data).unwrap()>

Integration test files should be placed in tests/ Under the directory,For example:
  tests/stats_integration_test.rs
Run `cargo test --test stats_integration_test` Test a Specific File
RUST
// ============================================
// Testing Organization: Module Testing + Integration Test Directory Structure
// Demo: A "Statistical Tools" Library Testing Layers
// Note: Integration Testing requires standalone files in the tests/ directory
// This example simulates two types of tests in a single file.
// ============================================

/// Statistical Tools: Calculate various statistical indicators
pub mod stats {
    /// Calculate the sum of a set of numbers
    pub fn sum(numbers: &[i32]) -> i32 {
        numbers.iter().sum()
    }

    /// Calculate the average of a set of numbers
    /// If the set is empty,Back 0.0
    pub fn average(numbers: &[i32]) -> f64 {
        if numbers.is_empty() {
            return 0.0;
        }
        sum(numbers) as f64 / numbers.len() as f64
    }

    /// Calculate the median of a set of numbers
    /// If the set is empty,Back None
    pub fn median(numbers: &mut [i32]) -> Option<f64> {
        if numbers.is_empty() {
            return None;
        }
        numbers.sort();
        let len = numbers.len();
        if len % 2 == 0 {
            // Even count: Take the average of the middle two
            let mid = len / 2;
            Some((numbers[mid - 1] + numbers[mid]) as f64 / 2.0)
        } else {
            // Odd count: Take the one in the middle
            Some(numbers[len / 2] as f64)
        }
    }

    /// Calculate the minimum value of a set of numbers
    pub fn min(numbers: &[i32]) -> Option<i32> {
        numbers.iter().min().copied()
    }

    /// Find the maximum value of a set of numbers
    pub fn max(numbers: &[i32]) -> Option<i32> {
        numbers.iter().max().copied()
    }
}

fn main() {
    use stats::*;

    println!("=== Statistical Tools Demo ===");
    let data = [3, 1, 4, 1, 5, 9, 2, 6];
    println!("Data: {:?}", &data[..]);
    println!("sum = {}", sum(&data));
    println!("average = {:.2}", average(&data));
    println!("median = {:.1}", median(&mut data.to_vec()).unwrap());
    println!("min = {:?}", min(&data).unwrap());
    println!("max = {:?}", max(&data).unwrap());
    println!();
    println!("Integration test files should be placed in tests/ Under the directory,For example:");
    println!("  tests/stats_integration_test.rs");
    println!("Run `cargo test --test stats_integration_test` Test a Specific File");
}

// ============================================
// Unit Testing
// ============================================
#[cfg(test)]
mod tests {
    use super::stats::*;

    #[test]
    fn test_sum() {
        assert_eq!(sum(&[1, 2, 3, 4, 5]), 15);
        assert_eq!(sum(&[]), 0);
        assert_eq!(sum(&[-1, 0, 1]), 0);
    }

    #[test]
    fn test_average() {
        let result = average(&[1, 2, 3, 4, 5]);
        assert!((result - 3.0).abs() < f64::EPSILON);
        assert_eq!(average(&[]), 0.0);
    }

    #[test]
    fn test_median_odd() {
        let mut data = [3, 1, 4, 1, 5];
        assert_eq!(median(&mut data), Some(3.0));
    }

    #[test]
    fn test_median_even() {
        let mut data = [1, 2, 3, 4];
        assert_eq!(median(&mut data), Some(2.5));
    }

    #[test]
    fn test_median_empty() {
        let mut data: [i32; 0] = [];
        assert_eq!(median(&mut data), None);
    }

    #[test]
    fn test_min_max() {
        let data = [3, -1, 7, 0, 42, -5];
        assert_eq!(min(&data), Some(-5));
        assert_eq!(max(&data), Some(42));
    }
}

// ============================================
// Simulated Integration Testing (In a real Rust project,
// This should go in a separate file within the tests/ directory)
// ============================================
// The following content simulates tests/stats_integration_test.rs:
//
// use my_stats_lib::stats;
//
// #[test]
// fn test_integration_sum_and_average() {
//     let data = [10, 20, 30, 40, 50];
//     assert_eq!(stats::sum(&data), 150);
//     assert!((stats::average(&data) - 30.0).abs() < f64::EPSILON);
// }
//
// #[test]
// fn test_integration_median_workflow() {
//     // Testing a Typical Data Analysis Workflow
//     let mut data = [100, 5, 50, 25, 75];
//     let med = stats::median(&mut data);
//     assert_eq!(med, Some(50.0));
// }
//
// #[test]
// fn test_integration_empty_data() {
//     let data: [i32; 0] = [];
//     assert_eq!(stats::sum(&data), 0);
//     assert_eq!(stats::average(&data), 0.0);
//     assert_eq!(stats::min(&data), None);
//     assert_eq!(stats::max(&data), None);
// }

Output:

TEXT 📖 Display only
=== Statistical Tools Demo ===
Data: [3, 1, 4, 1, 5, 9, 2, 6]
sum = 31
average = 3.88
median = 3.5
min = 1
max = 9

Integration test files should be placed in tests/ Under the directory,For example:
  tests/stats_integration_test.rs
Run `cargo test --test stats_integration_test` Test a Specific File

Integration tests are located in the tests/ folder within the project's root directory, and each .rs file represents a separate crate. Integration tests can only test the library's public API (interfaces marked with pub) and cannot access private functions. This simulates the scenario of "external users using your library." cargo test --test filename allows you to run only specific integration test files.


▶ Example 4: Benchmarking Concepts (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
  <avg.as_micros()>: Average <avg.as_nanos() % 1_000>.<name> microsecond (<iterations> Next iteration)
=== Benchmark Demo: Performance Comparison of Sorting Algorithms ===

Data Volume: <size> element

=== Conclusion ===
Bubble Sort O(n^2) It slows down noticeably when dealing with large amounts of data
Quick Sort O(n log n) Significant performance advantages with large data sets

Rust nightly Version Usage `cargo bench` Run a benchmark test
We recommend using the stable version `criterion` crate Conduct a benchmark test
RUST
// ============================================
// Benchmarking (Benchmark) Concept Demo
// Using #[bench] and Bencher (Requires nightly Rust)
// Note: Rust Stable Version uses the criterion crate for benchmark testing
// Here, we'll use a"Manual Timing"A method for simulating benchmark testing concepts
// ============================================

use std::time::Instant;

// ============================================
// Comparing the Performance of Two Sorting Algorithms
// ============================================

/// Bubble Sort (O(n^2) - Slow)
fn bubble_sort(arr: &mut [i32]) {
    let n = arr.len();
    for i in 0..n {
        for j in 0..n - 1 - i {
            if arr[j] > arr[j + 1] {
                arr.swap(j, j + 1);
            }
        }
    }
}

/// Quick Sort (O(n log n) - Fast)
fn quick_sort(arr: &mut [i32]) {
    if arr.len() <= 1 {
        return;
    }
    let pivot = partition(arr);
    quick_sort(&mut arr[..pivot]);
    quick_sort(&mut arr[pivot + 1..]);
}

fn partition(arr: &mut [i32]) -> usize {
    let len = arr.len();
    let pivot = arr[len - 1];
    let mut i = 0;
    for j in 0..len - 1 {
        if arr[j] <= pivot {
            arr.swap(i, j);
            i += 1;
        }
    }
    arr.swap(i, len - 1);
    i
}

/// Manual Benchmarking Functions
fn bench_sort<F>(name: &str, mut sort_fn: F, data: &[i32], iterations: u32)
where
    F: FnMut(&mut [i32]),
{
    let mut total_duration = std::time::Duration::new(0, 0);

    for _ in 0..iterations {
        let mut cloned = data.to_vec();
        let start = Instant::now();
        sort_fn(&mut cloned);
        total_duration += start.elapsed();
    }

    let avg = total_duration / iterations;
    println!("  {}: Average {}.{:03} microsecond ({} Next iteration)",
        name,
        avg.as_micros(),
        avg.as_nanos() % 1_000,
        iterations);
}

fn main() {
    println!("=== Benchmark Demo: Performance Comparison of Sorting Algorithms ===\n");

    // Generate Random Data
    let data_sizes = [100, 500, 1000];

    for &size in &data_sizes {
        // Generate a random array
        let data: Vec<i32> = (0..size).map(|i| {
            // Simulating Random Numbers Using a Simple Linear Congruential Generator
            ((i * 1234567 + 987654) % 100000) as i32
        }).collect();

        println!("Data Volume: {} element", size);

        let iterations = if size <= 100 { 100 } else { 10 };

        bench_sort("Bubble Sort", |arr| bubble_sort(arr), &data, iterations);
        bench_sort("Quick Sort", |arr| quick_sort(arr), &data, iterations);
        println!();
    }

    println!("=== Conclusion ===");
    println!("Bubble Sort O(n^2) It slows down noticeably when dealing with large amounts of data");
    println!("Quick Sort O(n log n) Significant performance advantages with large data sets");
    println!();
    println!("Rust nightly Version Usage `cargo bench` Run a benchmark test");
    println!("We recommend using the stable version `criterion` crate Conduct a benchmark test");
}

// ============================================
// Simulated nightly Rust Benchmarking (For reference only)
// Requires #![feature(test)] and extern crate test;
// ============================================
// The following code is available in nightly Rust:
//
// #![cfg(test)]
// #![feature(test)]
// extern crate test;
//
// #[cfg(test)]
// mod bench_tests {
//     use super::*;
//     use test::Bencher;
//
//     #[bench]
//     fn bench_bubble_sort_100(b: &mut Bencher) {
//         let data = vec![5, 3, 1, 4, 2, 7, 6, 9, 8, 0];
//         b.iter(|| {
//             let mut arr = data.clone();
//             bubble_sort(&mut arr);
//         });
//     }
//
//     #[bench]
//     fn bench_quick_sort_100(b: &mut Bencher) {
//         let data = vec![5, 3, 1, 4, 2, 7, 6, 9, 8, 0];
//         b.iter(|| {
//             let mut arr = data.clone();
//             quick_sort(&mut arr);
//         });
//     }
// }

Output:

TEXT 📖 Display only
=== Benchmark Demo: Performance Comparison of Sorting Algorithms ===

Data Volume: 100 element
  Bubble Sort: Average 45.123 microsecond (100 Next iteration)
  Quick Sort: Average 3.456 microsecond (100 Next iteration)

Data Volume: 500 element
  Bubble Sort: Average 1023.567 microsecond (10 Next iteration)
  Quick Sort: Average 18.234 microsecond (10 Next iteration)

Data Volume: 1000 element
  Bubble Sort: Average 4089.890 microsecond (10 Next iteration)
  Quick Sort: Average 39.012 microsecond (10 Next iteration)

=== Conclusion ===
Bubble Sort O(n^2) It slows down noticeably when dealing with large amounts of data
Quick Sort O(n log n) Significant performance advantages with large data sets

Rust nightly Version Usage `cargo bench` Run a benchmark test
We recommend using the stable version `criterion` crate Conduct a benchmark test

Benchmarking measures code execution time to ensure that performance does not degrade during refactoring. Rust Nightly includes the #[bench] attribute by default, while the stable release recommends using the criterion crate. Note: Benchmarking isn't about "faster is better"—the key is to establish a performance baseline to ensure there are no unexpected performance regressions when modifying the code. The example above demonstrates the concept of benchmarking by manually timing Instant::now().


▶ Example 5: Comprehensive Exercise—A Test-Driven String Library (Difficulty ⭐⭐⭐)

Output:

TEXT 📖 Display only
is_palindrome('racecar'): <is_palindrome("racecar")>
is_palindrome('hello'): <is_palindrome("hello")>
|<line>|

RUST
// ============================================
// Comprehensive Example: TDD-style String Library
// ============================================

pub fn is_palindrome(s: &str) -> bool {
    let clean: String = s.chars().filter(|c| c.is_alphanumeric()).map(|c| c.to_lowercase().next().unwrap()).collect();
    let reversed: String = clean.chars().rev().collect();
    clean == reversed
}

pub fn word_wrap(text: &str, width: usize) -> Vec<String> {
    let mut lines = Vec::new();
    let mut current = String::new();
    for word in text.split_whitespace() {
        if current.len() + word.len() + 1 > width && !current.is_empty() {
            lines.push(current.trim().to_string());
            current.clear();
        }
        if !current.is_empty() { current.push(' '); }
        current.push_str(word);
    }
    if !current.is_empty() { lines.push(current); }
    lines
}

pub fn count_words(text: &str) -> std::collections::HashMap<String, u32> {
    let mut freq = std::collections::HashMap::new();
    for word in text.split_whitespace() {
        let clean: String = word.chars().filter(|c| c.is_alphabetic()).map(|c| c.to_lowercase().next().unwrap()).collect();
        if !clean.is_empty() { *freq.entry(clean).or_insert(0) += 1; }
    }
    freq
}

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

    #[test]
    fn test_palindrome_simple() {
        assert!(is_palindrome("racecar"));
        assert!(is_palindrome("A man a plan a canal Panama"));
        assert!(!is_palindrome("hello"));
    }

    #[test]
    fn test_palindrome_empty() {
        assert!(is_palindrome(""));
        assert!(is_palindrome("a"));
    }

    #[test]
    fn test_word_wrap() {
        let result = word_wrap("The quick brown fox jumps", 10);
        assert_eq!(result, vec!["The quick", "brown fox", "jumps"]);
    }

    #[test]
    fn test_word_wrap_short() {
        let result = word_wrap("Hello", 10);
        assert_eq!(result, vec!["Hello"]);
    }

    #[test]
    fn test_count_words() {
        let freq = count_words("the cat and the dog");
        assert_eq!(freq.get("the"), Some(&2));
        assert_eq!(freq.get("cat"), Some(&1));
        assert_eq!(freq.get("dog"), Some(&1));
    }
}

fn main() {
    println!("is_palindrome('racecar'): {}", is_palindrome("racecar"));
    println!("is_palindrome('hello'): {}", is_palindrome("hello"));

    let wrapped = word_wrap("The quick brown fox jumps over the lazy dog", 15);
    for line in &wrapped { println!("|{:<15}|", line); }

    let freq = count_words("the cat sat on the mat and the cat");
    println!("\nWord frequency: {:?}", freq);
}

Output:

TEXT 📖 Display only
is_palindrome('racecar'): true
is_palindrome('hello'): false
|The quick brown|
|fox jumps over |
|the lazy dog   |

Word frequency: {"the": 3, "cat": 2, "sat": 1, "on": 1, "mat": 1, "and": 1}

TDD Process: Write tests first (test_palindrome_simple, etc.) → Then write the implementation → Run cargo test. #[cfg(test)] Ensure that the test module is compiled only during testing. use super::* Import the public API of the module under test. This example demonstrates a combination of unit testing and actual execution.


❓ FAQ

Q What is the difference between #[test] and #[cfg(test)]?
A #[test] marks a function as a test function, while #[cfg(test)] wraps a module so that it compiles only in test mode.
Q What is the difference between doc-tests and unit tests?
A Doc-tests verify that the sample code in the documentation runs correctly, while unit tests verify that the function logic is correct.
Q Why are integration tests placed in the tests/ directory?
A Because every file in the tests/ directory is treated as an independent crate and can only access your library's public API.

📖 Summary


📝 Exercises

  1. Difficulty ⭐: Write a program that includes the is_prime(n: u32) -> bool function to determine whether a number is prime. Write at least 5 test cases for this function (including the boundary cases: 0, 1, 2, prime numbers, and composite numbers). Use assert!, assert_eq!, and #[should_panic] (which causes a panic if the parameter is 0) at least once each.

  2. Difficulty ⭐⭐: Create a "Temperature Converter" library containing two functions: celsius_to_fahrenheit(c: f64) -> f64 and fahrenheit_to_celsius(f: f64) -> f64. Write complete documentation comments for these two functions (including examples, parameter descriptions, and return value descriptions), and ensure that the unit tests pass. Also, write unit tests to verify boundary values (such as 0°C = 32°F, 100°C = 212°F, and -40°C = -40°F).

  3. Difficulty ⭐⭐⭐: Implement a "Simple Calculator" library that supports five operations: add, subtract, multiply, divide, and power (power operations). Create a comprehensive testing framework for this library: (1) Unit tests must cover all functions, including edge cases (division by zero, 0th power, etc.); (2) Simulate the creation of a tests/calculator_integration_test.rs integration test file (write the complete content in the comments) to test "consecutive operations" scenarios (such as add(2,3) → multiply(5,4) → power(20,2)). Use #[should_panic] to test the division-by-zero scenario.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏