Write the test
In front end development, third-party JEST libraries are often used for unit testing, but rust has built in testable functionality for developers
How to Write tests
Testing in any language involves the following three steps:
- Prepare the required data or status.
- Call the code you want to test.
- The assertion runs as expected.
Test the composition of the function
Add #[test] to the top line of the fn keyword to turn the function into a test function, and then run the test using cargo test:
#[test]
fn it_works() {
assert_eq!(2 + 2.4);
}
Copy the code
In the tests, if panic! Causes the test to fail:
#[test]
fn another() {
panic!("Something went wrong.")}Copy the code
assert! Check if the result is true:
#[test]
fn is_true() {
let is_eq = 2 > 1;
assert!(is_eq);
}
Copy the code
assert_eq! Check if the two data are the same:
#[test]
fn is_eq() {
// assert_eq! And assert_ne! Macros use == and! Respectively. = operator to determine,
// And use the debugging output format {:? } Print out the parameter values.
This means that their parameters must implement both PartialEq and Debug traits.
#[derive(Debug, PartialEq)]
struct Rect {
width: u32,
height: u32,}let rect1 = Rect {
width: 150,
height: 100};letrect2 = Rect { .. rect1 };assert_eq!(rect1, rect2);
}
Copy the code
assert_ne! Check if the two data are different:
#[test]
fn is_ne() {
fn add(a: i32, b: i32) - >i32 {
a + b
}
assert_ne!(add(1.2), 4)}Copy the code
Add a custom error message:
#[test]
fn custom_error() {
let a = 1;
let b = 2;
// All arguments to the assertion function after the necessary arguments are passed to format! Macro for printing
assert!(a > b, "{} should be greater than {}", a, b);
assert_eq!(a, a, "{} should equal", a);
assert_ne!(a, b, "{} should not equal {}", a, b);
}
Copy the code
Mark the should_panic attribute on the function to assert that the exception should be raised:
#[test]
#[should_panic]
fn should_error() {
panic!("There should be a mistake.")}Copy the code
Make sure the exception thrown is expected and not an exception in another location:
#[test]
#[should_panic(expected = "Less than")]
fn should_error() {
let a = 1;
let b = 2;
if a > b {
panic!("A greater than b")}else {
panic!("A less than b") // Expected 'less than' in this panic! The text in the}}Copy the code
Write tests using Result<T, E>, which can be used instead of the Assert series of tests that pass when the function returns Ok:
#[test]
fn use_result() - >Result< (),String> {
let a = 1;
let b = 1;
if a == b {
Result: :Ok(()) // The argument to Ok needs to be an empty tuple
} else {
Result: :Err(format!("{} != {}", a, b))
}
}
Copy the code
Control how tests are run
Parameters for running tests:
cargo test --help
Copy the code
Controls how tests are run by separating command arguments with — :
cargo test -- --help
Copy the code
Cargo enables parallel testing by default to reduce test time. This means that multiple tests cannot depend on one another. You can use parameters to control the specific number of threads:
cargo test -- --test-threads=1
Copy the code
We can’t see println! In the code when the test passes. If Rust does not capture the annotation output, use the parameter to control Rust from capturing the annotation output:
cargo test -- --nocapture
Copy the code
You can reduce test time by running only part of the test cases, such as testing all test cases that match the string is_ :
cargo test is_
Copy the code
Run a single test:
cargo test it_works
Copy the code
Note: You cannot run multiple tests:
cargo test it_works is_eq
Copy the code
To omit certain tests by specifying them explicitly:
#[test]
#[ignore]
fn should_ignore() {
panic!("This error will not be thrown because the should_ignore test will not be run.")}Copy the code
If you want to run only these ignored tests:
cargo test -- --ignored
Copy the code
Test organization structure
Unit testing
Unit tests are generally written in the same file as the business code, but are identified by creating a new test module:
pub fn add(a: i32, b: i32) - >i32 {
a + b
}
// Modules marked as tests will be removed after cargo Build
// In addition, we do not need to tag integration tests with #[CFG (test)] because integration tests are placed in a separate directory and rust does not process them when building.
// CFG: configuration, which is processed only in test mode
#[cfg(test)]
mod testaaa {
use super::add;
#[test]
pub fn test_add() {
assert_eq!(add(1.2), 3)}}Copy the code
Integration testing
Integration tests are located entirely outside the SRC directory in the Tests folder:
mkdir tests
Copy the code
Test an external package adder:
use adder::add_one;
#[test]
fn test_add() {
assert_eq!(add_one(1), 2)}Copy the code
Cargo tests (including unit tests, integration tests, document tests)
cargo test
Copy the code
Run only an integration test:
cargo test --test[Integration test file name]Copy the code
Integration test common functions need to be placed in the tests/common/mod.rs file, otherwise they will be identified as integration test cases by Rust elsewhere:
mod common; // References use public packages
#[test]
fn test_add() {
// Use the setup function in the public package
common::setup();
assert_eq!(add_one(1), 2)}Copy the code