5 ms·
After writing Rust in production for a while, the biggest bugbear I have is the naming/file structure. I end up a lot with this; src/main.rs src/combo
by yarper 10y ago
After writing Rust in production for a while, the biggest bugbear I have is the naming/file structure.
I end up a lot with this;
src/main.rs
src/combobulator/mod.rs
src/combobulator/tests.rs
src/tests.rs
src/somethingelse/tests.rs
src/somethingelse/mod.rs
Because I find tests in the same file a bit confusing. It's really easy with maven-style layouts to know that "only things in main/java or main/scala get compiled and go into the jar". "src/test/*" and "src/main/resources" are for me. The same thing applies for cargo.tomls and resources - there's not really a way to see what goes into the executable from the file structure.
But this isn't the biggest problem with having things called "mod.rs". That would be if I open 5 mod.rs's in a text editor with tabs, I have no idea what goes with what.
I know that tests should go under tests/, but that's specifically for integration tests. Integration tests are an order of magnitude less likely to get written imo, and if they are they'll probably get written as unit tests anyway.
If anyone has any top tips for how to structure larger Rust projects while separating unit tests into different files, please let me know!
- dogamak 10y agoAdditionally tests in "tests/" are compiled to independent binaries on which the test suite is run on separately, which results into verbose and redundant output when ran. Also if you keep your tests under "src/", you can't just stick them wherever you want; you need to have #[cfg(tests)] on every module declaration leading to the test function, otherwise the test is ignored silently. From time to time I find old tests that have not ran once because of a missing attribute somewhere upwards the module hierarchy.
- steveklabnik 10y agoHm, cfg(tests) should only control if they're included in non-test builds; it shouldn't ignore them entirely.
- JoshTriplett 10y agoI prefer to keep tests in a `mod tests { ... }` block at the end of the source file, which provides comparable benefits and separation. I also prefer to use `combobulator.rs` rather than `combobulator/mod.rs`, for multiple reasons including filename ambiguity. In this case, you'd have: src/main.rs src/combobulator.rs src/somethingelse.rs
- kazagistar 10y agoI think this is a very common standard. At least, its what I have seen most often.
- jnordwick 10y agoToo much code in one place. Makes it hard to read the file and difficult to see what is code and what are tests. `wc` can no longer give you a quick approximation of code size either.
- erickt 10y agoIn case you didn't see, I mentioned there is a way to do this right now: https://news.ycombinator.com/item?id=13791945 https://news.ycombinator.com/item?id=13791945
- jnordwick 10y agoSo I can keep a separate src/ and tests/ hierarchy? Why are the rust people so insistent on this even though most seen to want to could their test and src trees.
- deleted 10y ago[deleted]
- jnordwick 10y agoI have no tips to fix. When cargo went gold long ago I complained about this and I was told I'd get used to it. I never have. The test layout is painful and I really hope it gets changed or at least added. I want all my tests for a module in one place. I hope this stops being a problem.
- erickt 10y agoOne approach for this that I haven't really seen get used much that you can use a macro to get around this. In your comboluator.rs, just add this at the bottom of the file: #[cfg(test)] Mod tests { include!("comboluator_tests.rs"); } Then write your tests there. It allows you to write unit tests against private things, but also allows you to decouple the files to keep things cleaner.