DEV Community

David Rivera
David Rivera

Posted on

OSD600 Lab 7: Testing

I'll make this one really straightforward:

Over the last couple of months working on the repo context manager project (see), Testing was one of the fundamental things one cannot miss. Specifically, as I was iterating largely and adding features over and over again, it was essential for me to keep track of correctness throughout the main logic. Although not explicitly stated in any of the labs so far, I've been adding tests all along this time.

This dedication to testing was a crucial habit, as it dramatically boosted my confidence while adding features. Having a robust set of tests meant I could refactor or introduce major changes quickly, secure in the knowledge that if I broke something core, the test suite would immediately flag it. For an evolving project, this continuous verification is key to maintaining high code quality and ensuring the main logic remains sound, no matter how fast development moves.

Luckily nowadays in modern programming languages like Rust (in my case) testing functionalities are very straightforward and are already builtin—into the ecosystem by itself.

Rust testing capabilities

Rust's testing is deeply integrated into the language and its build tool, Cargo, making it straightforward and idiomatic. Note that in order to simulate test scenarios and generating dummy files and directories the crate: TempDir had to be utilized.

Unit Tests

Location: Unit tests are typically placed in a separate tests module within the same file as the code they are testing. This allows them to test private functions and internal implementation details.

Syntax They are defined using the #[cfg(test)] attribute on the module and the #[test] attribute on the function itself.

Execution You run them using the command cargo test.

Assertions Tests rely on built-in assertion macros like assert!, assert_eq!, and assert_ne! to check for expected outcomes. For example, assert_eq!(2 + 2, 4);.

Integration Tests

Location: Integration tests are placed in a dedicated tests directory at the root of your project (not inside the src folder). Each file in this directory is treated as an independent crate.

Purpose: These tests only interact with the public interface of your library, simulating how external code would use it.

Execution: They are also run using the cargo test command, automatically found by Cargo in the tests directory.

This is an example of what it could look like:

// In src/lib.rs, inside the module with the function to test
pub fn add_two(a: i32) -> i32 {
    a + 2
}

#[cfg(test)] // This attribute tells Rust to compile this module only when running tests
mod tests {
    use super::*; // Bring the outer items (like add_two) into scope

    #[test] // This attribute marks a function as a test
    fn it_works() {
        // Assertions are the core of tests
        assert_eq!(add_two(2), 4); // Checks if the function's output equals the expected value
    }

    #[test]
    #[should_panic] // This attribute ensures the test passes only if the function panics
    fn handles_bad_input() {
        // Example: a function that panics on zero input
        // some_function(0);
        assert!(true); // Placeholder for a panicking call
    }
}

Enter fullscreen mode Exit fullscreen mode

In summary, Rust provides a powerful, zero-setup testing environment where unit and integration tests are handled seamlessly by Cargo, encouraging developers to write tests alongside their code.

Top comments (0)