Some people do
#[cfg(test)]
mod tests {
//all tests here
}
While simply putting every test in the end of the file like
#[test]
fn test1() {
}
#[test]
fn test2() {
}
works too and I can even run single tests by cargo.
What is the difference? Why do some people do it the first way?
THE MODULE 1 TEST (MOD 1) Module 1 is a test of your machine control and is conducted at an off-road site called a 'motorcycle manoeuvre area' or MMA for short. With our training you'll be able to practice on the official DSA site prior to taking the test.
Testing your code teaches you how to write good code because you have to fix all of your bad code. When you have to go through and fix your own bugs you learn different ways to solve problems. The number of ways you can break code is immeasurable and that's what makes it so interesting.
The #[cfg(test)] annotation on the tests module tells Rust to compile and run the test code only when you run cargo test , not when you run cargo build .
A primary testing method is Salt Spray testing, which as its name indicates, evaluates how resistant a part or material is to corrosion when exposed to a salt spray for extended periods of time. Effective Salt Spray testing must be performed in a controlled environment, such as a closed salt fog tank.
Note that developer tests do not consider Regression or System Tests. Developers can also write code to automate Regression and/or System Tests, but that would come at a later stage in the development cycle when the application is in a more complete state.
Developer tests are written whilst the developer is writing the actual functionality. This process is tightly integrated so that the developer can work in a flow of writing tests and the logic. There are two widely adopted approaches for writing developer tests: Test Driven Development (TDD)
Test Driven Development (TDD) Behaviour Driven Development (BDD) These different approaches are often the main point of contention amongst developers when setting out a testing strategy. Note that developer tests do not consider Regression or System Tests.
Regression testing is the repetition of previously executed test cases for the purpose of finding defects in software that previously passed the same set of tests. Such tests would commonly be used before shipping code to a new environment or as part of a build process.
You often need to share some code between your tests, for example macros and functions used for building the test cases or to check the result values. And you sometimes have to import whole crates just for your tests.
The #[cfg(test)]
conditional compilation attribute makes it possible to have code not compiled when not testing. This enables faster checks and a faster compilation in the general case. If you include a crate just for the tests, you can import it in those mods and specify the dev dependency in a [dev-dependencies]
section of your Cargo.toml.
Here's an example of such a test mod where some functions are used in several tests: wrap.rs.
I personally create a mod as soon as the tests of a function aren't trivial, even when there's not (yet) any shared help function: the test mod then appears as an easy to notice test block in my code.
Sometimes you go even further by using the "tests" directory solution for your integration tests, which makes it easier to have whole mods shared between your tests. This is often the most practical solution when your tests are more than unit tests (some crates have more tests than tested code).
Read the rust book on test organization to know more.
You don't want your code under test to be able to access any test code. By putting the tests and helper functions in a child module (and not making them pub
), you prevent the code under test to access any test code.
The following sample code will help demonstrate my point:
src/add.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
pub fn compiler_test() {
// Uh oh, below compiles!
#[cfg(test)]
test_add();
// Good, error[E0603]: function `test_add` is private
#[cfg(test)]
tests::test_add();
// ^^^^^^^^ private function
}
#[test]
fn test_add() {
assert_eq!(add(4, 5), 9)
}
#[cfg(test)]
mod tests {
#[test]
fn test_add() {
assert_eq!(super::add(1, 2), 3)
}
}
Note that skipping mod tests
does not prevent you from making use of [dev-dependencies]
, because #[test]
is enough to make compilation conditional on #[cfg(test)]
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With