I have a test that initializes a variable before diving into the detail of the test, and I want to make a second test with the same variable, and not duplicate the initialization code:
#[test]
fn test_one() {
let root = Path::new("data/");
// the rest of the test
}
#[test]
fn test_two() {
let root = Path::new("data/");
// the rest of the test
}
I don't think static
or const
would do it because the size would not be known up front, though PathBuf.from(path)
might make that OK, except that initialization expressions for static/const vars cannot be too complex.
I've seen lazy_static, but have not seen any examples of its use in tests. This after seeing the compiler error with "an extern crate loading macros must be at the crate root", which online searching tells me is something about being outside main()
, but tests don't have main
functions.
In Java, I would define the variable then initialize it in a setup()
method, but I can't see examples of that online for Rust.
At its simplest, a test in Rust is a function that's annotated with the test attribute. Attributes are metadata about pieces of Rust code; one example is the derive attribute we used with structs in Chapter 5. To change a function into a test function, add #[test] on the line before fn .
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 .
In Rust global variables are declared with the static keyword. In C there is a difference between static variables (with translation unit scope) and non-static global variables (with truly global scope).
Foremost, remember that Rust tests are run in parallel. This means that any shared setup needs to be thread-safe.
and not duplicate the initialization code
You do it the same way you avoid duplicating any other code: create a function, create a type, create traits, etc.:
use std::path::PathBuf;
fn root() -> PathBuf {
PathBuf::from("data/")
}
#[test]
fn test_one() {
let root = root();
// the rest of the test
}
#[test]
fn test_two() {
let root = root();
// the rest of the test
}
In Java I would define the variable, then initialize it in a
setup()
method
Instead, make a struct called Setup
containing all those variables and construct it as the first thing in each test:
use std::path::{Path, PathBuf};
struct Setup {
root: PathBuf,
}
impl Setup {
fn new() -> Self {
Self {
root: PathBuf::from("data/"),
}
}
}
#[test]
fn test_one() {
let setup = Setup::new();
let root: &Path = &setup.root;
// the rest of the test
}
#[test]
fn test_two() {
let setup = Setup::new();
let root: &Path = &setup.root;
// the rest of the test
}
but have not seen any examples of [lazy-static] use in tests
That's because there is no different way to use it in tests, it's just code:
#[macro_use]
extern crate lazy_static;
use std::path::Path;
lazy_static! {
static ref ROOT: &'static Path = Path::new("data/");
}
#[test]
fn test_one() {
let root = *ROOT;
// the rest of the test
}
#[test]
fn test_two() {
let root = *ROOT;
// the rest of the test
}
See also:
Very specifically for your case, it's very rare that you need exactly a Path
, since a string slice implements AsRef<Path>
. Said another way, most places that accept a Path
accept a &str
:
static ROOT: &str = "data/";
#[test]
fn test_one() {
let root = ROOT;
// the rest of the test
}
#[test]
fn test_two() {
let root = ROOT;
// the rest of the 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