Isolating test code

When our tests grow in complexity, there may be additional helper methods that we might create that only gets used within the context of our test code. In such situations, it is beneficial to isolate the test-related code from the actual code. We can do this by encapsulating all of our test-related code inside a module and putting a #[cfg(test)] annotation over it.

The cfg in the #[cfg(...)] attribute is generally used for conditional compilation and not just limited to test code. It can include or exclude code for different architectures or configuration flags. Here, the configuration flag is test. You might remember that the tests in the previous chapter were already using this form. This has the advantage that your test code is only compiled and included in the compiled binary when you run cargo test, and otherwise ignored.

Say you want to programmatically generate test data for your tests, but there's no reason to have that code in the release build. Let's create a project by running cargo new unit_test --lib to demonstrate this. In lib.rs, we have defined some tests and functions:

// unit_test/src/lib.rs

// function we want to test
fn sum(a: i8, b: i8) -> i8 {
a + b
}

#[cfg(test)]
mod tests {
fn sum_inputs_outputs() -> Vec<((i8, i8), i8)> {
vec![((1, 1), 2), ((0, 0), 0), ((2, -2), 0)]
}

#[test]
fn test_sums() {
for (input, output) in sum_inputs_outputs() {
assert_eq!(crate::sum(input.0, input.1), output);
}
}
}

We can run these tests by running cargo test. Let's go through the preceding code. We generate known input and output pairs in the sum_inputs_outputs function, which is used by the test_sums function. The #[test] attribute keeps the test_sums function out of our release compilation. However, sum_inputs_outputs is not marked with #[test], and will get included in compilation if it's declared outside the tests module. By using #[cfg(test)] with a mod tests {} child module and encapsulating all the test code and its related functions inside this module, we get the benefit of keeping both the code and the resulting binary clean of the test code.

We also had our sum function defined as private without the pub visibility modifier, which means that unit tests within modules also allow you to test private functions and methods. Quite convenient!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset