Rust testing: Difference between revisions
Line 64: | Line 64: | ||
== Integration Tests == | == Integration Tests == | ||
<blockquote> | |||
=== Basics === | |||
<blockquote> | <blockquote> | ||
Each integration test is it's own crate.<br> | Each integration test is it's own crate.<br> | ||
They are written in the <code>tests/</code> directory. | They are written in the <code>tests/</code> directory. | ||
{{ NOTE | | |||
executable crates can't be imported, so they can't have integration tests.<br> | |||
the convention is to keep your <code>main.rs</code> very simple, and test your executable's <code>lib.rs</code> crate. | |||
}} | |||
<syntaxhighlight lang="rust"> | <syntaxhighlight lang="rust"> | ||
Line 78: | Line 85: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Basics --> | |||
=== Setup/Teardown/Testlib === | |||
<blockquote> | |||
Setup/Teardown code is just regular functions.<br> | Setup/Teardown code is just regular functions.<br> | ||
You must add them using a <code>some_module/mod.rs</code> so that it is not run as tests. | You must add them using a <code>some_module/mod.rs</code> so that it is not run as tests. | ||
Line 106: | Line 116: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Setup/Teardown/Testlib --> | |||
</blockquote><!-- Integration Tests --> | </blockquote><!-- Integration Tests --> | ||
Revision as of 00:32, 9 February 2023
Documentation
Running Tests
By default, tests run in parallel
cargo test # run all tests (unit/integration/doc) cargo test tests::add_two_positive_numbers # run specific test cargo test add # run all tests with the word 'add' in their name cargo test --test my_integration_test # run all tests in 'tests/my_integration_tests' cargo test -- --show-output # show printed output (in both passing/failed) cargo test -- --ignored # only run ignored tests
Test Types
Unit Tests
In rust, it's customary to define your tests in the same file as your code.
Define your tests
// src/lib.rs // real code fn add<T>(a: T, b: T) -> T { a + b } // test code #[cfg(test)] // tell rust not to compile unless testing mod tests { use super::*; // include parent module (our src!) #[test] fn add_two_positive_numbers() { let res = add(1, 2); assert_eq!(res, 3); } #[test] fn add_a_postive_and_negative_number() { let res = add(1, -2); assert_eq!(res, -1); } }cargo test # run testsIntegration Tests
Basics
Each integration test is it's own crate.
They are written in thetests/
directory.NOTE:
executable crates can't be imported, so they can't have integration tests.
the convention is to keep yourmain.rs
very simple, and test your executable'slib.rs
crate.// tests/add_integration_tests.rs use my_code::*; #[test] fn add_two_positive_numbers() { assert_eq!(add(1, 3), 4); }Setup/Teardown/Testlib
Setup/Teardown code is just regular functions.
You must add them using asome_module/mod.rs
so that it is not run as tests.my_project/ tests/ common/ mod.rs // <-- test lib code here add_integration_tests.rs// tests/common/mod.rs pub fn setup() { // ... }// tests/add_integration_tests.rs mod common; #[test] fn do_the_thing() { common::setup(); }DocComment Tests
Assertions
Some common assertions.
NOTE:
rust doesn't care what order assertion params are defined in.
there is not a convention for one side with expectaton and the other for actual.assert_eq!(result, expects); // assert equal assert_ne!(result, expects); // assert not equal assert_eq!(result, "reason", expects); // add a message to assertion assert!(result) // assert true assert!(!result) // assert falseYou can assert that code panics by assigning an attribute.
// assert any part of code panics #[test] #[should_panic] fn open_non_existant_file_should_panic() { // ... } // assert panics with message #[test] #[should_panic(expected = "foo is not a number")] fn open_non_existant_file_should_panic() { // ... }Test functions can also use the Result type.
#[test] fn open_non_existant_file_should_panic() -> Result<(), String> { if add(1, 3) == 4 { Ok(()) } else { Err("1 plus 3 should be 4".to_string()) } }
Ignore Tests
skip this test
#[test] #[ignore] fn open_non_existant_file_should_panic() { // ... }