Hone logo
Hone
Problems

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:

  1. Calculator Struct: Define a struct named Calculator.
  2. Methods: Implement the following methods for Calculator:
    • add(a: i32, b: i32) -> i32: Returns the sum of a and b.
    • subtract(a: i32, b: i32) -> i32: Returns the difference of a and b (a - b).
    • multiply(a: i32, b: i32) -> i32: Returns the product of a and b.
    • divide(a: i32, b: i32) -> Result<i32, String>: Returns the quotient of a divided by b. This method should return an Err variant with a descriptive String message if b is zero.
  3. 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.

Expected Behavior:

  • The add, subtract, and multiply methods should perform standard integer arithmetic.
  • The divide method should return the correct integer division result for non-zero divisors and an Err for 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 divide method's error message for division by zero must be exactly "Division by zero is not allowed".
  • You should implement the Calculator and its tests within a single Rust file or a standard Rust project structure.

Notes

  • Remember to declare your Calculator struct and its methods.
  • The #[cfg(test)] attribute is crucial for ensuring your test code is only compiled when running tests.
  • The super::* import within the tests module is common practice to bring items from the parent module into scope.
  • Consider how to instantiate your Calculator for testing. If it has no fields, an empty struct literal {} is sufficient.
  • For the divide method's Result, you'll need to check both the Ok and Err variants in your tests.
Loading editor...
rust