Mastering Unit Tests in Rust
Writing reliable software hinges on thoroughly testing your code. This challenge will guide you through the process of creating robust unit tests in Rust. You'll learn how to define test functions, assert expected outcomes, and handle common testing scenarios, ultimately building confidence in the correctness of your Rust programs.
Problem Description
Your task is to implement a simple Calculator struct in Rust and write comprehensive unit tests for its methods. The Calculator should support basic arithmetic operations: addition, subtraction, multiplication, and division.
Key Requirements:
CalculatorStruct: Define a struct namedCalculator.- Methods: Implement the following methods for
Calculator:add(a: i32, b: i32) -> i32: Returns the sum ofaandb.subtract(a: i32, b: i32) -> i32: Returns the difference ofaandb(a - b).multiply(a: i32, b: i32) -> i32: Returns the product ofaandb.divide(a: i32, b: i32) -> Result<i32, String>: Returns the quotient ofadivided byb. This method should return anErrvariant with a descriptiveStringmessage ifbis zero.
- Unit Tests: Create a separate module for your tests using
#[cfg(test)] mod tests { ... }.- Write at least two unit tests for each method (
add,subtract,multiply,divide). - Tests should cover typical scenarios, including positive and negative numbers.
- For
divide, ensure you have tests for both successful division and division by zero. - Use Rust's built-in assertion macros (e.g.,
assert_eq!,assert!) to verify the correctness of your methods.
- Write at least two unit tests for each method (
Expected Behavior:
- The
add,subtract, andmultiplymethods should perform standard integer arithmetic. - The
dividemethod should return the correct integer division result for non-zero divisors and anErrfor a zero divisor.
Examples
Example 1: Addition
// In your tests module:
#[test]
fn test_add_positive() {
let calculator = Calculator {}; // Assuming Calculator is a unit struct or has a default implementation
assert_eq!(calculator.add(5, 3), 8);
}
Example 2: Subtraction
// In your tests module:
#[test]
fn test_subtract_negative_result() {
let calculator = Calculator {};
assert_eq!(calculator.subtract(3, 5), -2);
}
Example 3: Multiplication
// In your tests module:
#[test]
fn test_multiply_by_zero() {
let calculator = Calculator {};
assert_eq!(calculator.multiply(10, 0), 0);
}
Example 4: Division (Successful)
// In your tests module:
#[test]
fn test_divide_successful() {
let calculator = Calculator {};
assert_eq!(calculator.divide(10, 2), Ok(5));
}
Example 5: Division (By Zero)
// In your tests module:
#[test]
fn test_divide_by_zero() {
let calculator = Calculator {};
assert_eq!(calculator.divide(10, 0), Err("Division by zero is not allowed".to_string()));
}
Constraints
- The input numbers for all operations will be within the range of
i32. - The
dividemethod's error message for division by zero must be exactly"Division by zero is not allowed". - You should implement the
Calculatorand its tests within a single Rust file or a standard Rust project structure.
Notes
- Remember to declare your
Calculatorstruct and its methods. - The
#[cfg(test)]attribute is crucial for ensuring your test code is only compiled when running tests. - The
super::*import within thetestsmodule is common practice to bring items from the parent module into scope. - Consider how to instantiate your
Calculatorfor testing. If it has no fields, an empty struct literal{}is sufficient. - For the
dividemethod'sResult, you'll need to check both theOkandErrvariants in your tests.