for integration and doctests instead of having private fields I'd use pub(crate) or
if the above doesn't fit the purpose, I use some helper functions that are enabled for tests only (using #[cfg(test)], although this didn't work for doc tests -- not sure whether it does now or not.)
I was referring to putting a submodule inside of the already existing crate::device module. In case you want to avoid the tests cluttering the device module. IIRC that’s how (at least some of the) tests (even of public API) of types in the standard library are structured.
My problem is about file management. I don't want my tests to be in the device.rs file. Can I put them in a device_tests.rs file and have a device::tests module in it? How can I do that?
You’ll have a choice between keeping device.rs as is or moving its contents to device/mod.rs, whichever you prefer. The first version has both a directory device and a file device.rs in scr. The (device-module specific) test can go into device/test.rs and you need the mod declaration, as @SkiFire13 already explained. Inside of this test module you can refer to Device by either crate::device::Device, or super::Device (both for direct use or in use statements).
The problem is I have one or two tests per .rs files. This would mean I have to have one folder per .rs file. I prefer to have all those tests in one single file and test all modules in them.
Can't I separate the module concept from the file hierarchy?
There’s the path attribute. Though this cannot help you getting all the tests in a single file. In that case, you could consider the last option persented by @qaopm
Maybe a bit annoying, but I don't think it's actually restrictive.
As a start, the module tests can't be declared inside the impl Device {, although this is probably a typo. I'll take it as if you intended it to be outside the impl Device { but inside the mod device {.
Apart from that, here you're actually declaring a module foo::device::tests because they're declared inside the foo.rs file. There's no way to declare an higher-level module from inside a module.
Now that you make me think about it, if op just wants to have its unit tests grouped together it could have them in a tests folder but in separated files and use #[path = "tests/bar.rs"] mod tests; in each module.
Not to suggest that this is in any form a useful idea (it isn’t. Visibility does not depend on impl blocks but is entierly a concept related to modules), but IIRC you can even declare external modules inside of impl blocks if you give them a #[path = "..."].
Edit: No, wait, sorry.. that’s not inside of impl blocks but inside of function definitions (which can themselves be inside of impl blocks)... I got that mixed up.
// device_tests.rs
use super::*;
#[test]
fn virt_to_phys_addr() {
let phys_addr = Device::virt_to_phys_addr(0x80000000);
assert_eq!(phys_addr.addr, 0);
}
// device.rs
#[path = "tests.rs"]
#[cfg(test)]
mod tests;
I suspect the idea of tests folder is even better but the idea is here: Put a mod tests inside another module without relying on hierarchical manipulation on the file system.
I was so devastated. Thanks you all for the solution!