A type constrains what a Rust value can represent and how it can be used. Rust’s basic modeling choices are primitives, structs, enums, and aliases. Primitives cover values such as numbers and characters; structs and enums combine or distinguish data; aliases give existing types another name. section 4.5
Use those constraints when deciding what to test. The compiler checks that expected types match and references are valid: a string cannot be used as an integer. Tests should instead concentrate on program logic, including conversions that can fail, stateful operations, and I/O. Types do not eliminate those edge cases. section 6.4
An atomic integer is a specific type for thread-safe operations on an integer, not another name for a type in general. In a shared test counter, replacing an `i32` with `AtomicI32` does not by itself make a `static mut` declaration acceptable to the compiler. The declaration and initialization strategy matter too. section 6.5
#[cfg(test)]
mod tests {
use lazy_static::lazy_static;
use std::sync::atomic::{AtomicI32, Ordering};
lazy_static! {
static ref COUNT: AtomicI32 = AtomicI32::new(0);
}
#[test]
fn test_count() {
COUNT.fetch_add(1, Ordering::SeqCst);
}
}
This test counter uses `AtomicI32`, `fetch_add`, and `lazy_static` without declaring a mutable static. It illustrates a concrete choice of type and initialization strategy for shared state. section 6.5
















