-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test cleanup: Figure out a better story for string literals. #5745
Comments
Is there any prior art in the Rust ecosystem we can look at here? I'm thinking things like the CLI WP or the testing setups in existing CLI projects, like ripgrep. |
cc @killercup, you may have thoughts on this? |
For one-line files, how do you feel about one-line definitions? #[test]
fn foo() {
project()
.file("foo.rs", "fn foo() {}")
} |
Indeed yeah! If it fits on one line that looks fine to me |
What we do in IntelliJ is that we use an external DSL of sorts to define a directory structure using only a single string literal. In rustfmted Rust this might look like this: fn main() {
let p = build_project(
r#"
//- Cargo.toml
[project]
name = "foo"
version = "0.1.0"
authors = []
[workspace]
members = ["bar"]
//- src/main.rs
fn main() {}
//- bar/Cargo.toml
[project]
name = "bar"
version = "0.1.0"
authors = []
workspace = ".."
//- bar/src/main.rs
"fn main() {}"
"#,
);
} internally, this'll split on There's also an observation that EDIT: version with format doesn't look too ugly: fn main() {
let p = build_project(&format!(
r#"
//- Cargo.toml
[project]
name = "foo"
version = "{version}"
authors = []
[workspace]
members = ["bar"]
//- src/main.rs
fn main() {}
//- bar/Cargo.toml
[project]
name = "bar"
version = "{version}"
authors = []
workspace = ".."
//- bar/src/main.rs
"fn main() {}"
"#,
version = "0.0.1"
));
} |
Thanks @matklad! It's great to have examples from other projects.
Could you expand more from your experience why everything spelt out is usually better? While I agree that some restraint should be applied in not over-generalising, I also think it's important for tests to be readable and reviewable. By the way some degree of "spelt out fully explicitly" has been removed with #5782 landing yesterday. I'd be happy to revert (or forward fix) that change if it is preferred. Open to ideas and suggestions on striking a good balance. |
Sure! First of all I'd like to clarify that I don't have a too strong opinion about this, either approach is good! Here are some rough thoughts about why duplicating test data (as opposed to test code) is, surprisingly, not bad:
The main problem with abstracting test data repetition is that in some tests there are slight variations in the data, and so you'll have to either add a bunch of knobs to the abstraction (which in the limit equals to just writing out everything explicitly) or to use very different style for tests which don't fit the abstraction exactly. EDIT: an example of such abstraction creep is the FWIW, the "test data as a string" approach allows for some deduplication as well: r#"
//- Cargo.toml
[DEFAULT_CARGO_TOML]
//- src/main.rs
fn main() {}
#" |
OTOH, #5782 deletes quite a bunch of code! :) So, what about this?
|
Note https://github.com/rust-lang/cargo/pull/5787/files is a proposal for deleting twice as much code as well, by using a very simple 2 param |
That one feels like it's kind of on the borderline for me :) I think we can save about as many lines by removing That is, I wouldn't aim at reducing the net amount of code, and rather focus on reducing the number of distinct things you need to specify to write a test. Removing a default Cargo.toml completely (together with empty lib.rs preferably) seems like a win. Providing a more ergonomic way to write |
I think there's value in reducing vertical verbosity. The proposal in #5787 is 1 line per basic manifest. If my counting is right in the DSL you describe it would be ~5 lines per manifest ( Another idea I wanted to run by you (and the rest of the cargo team), how would you feel instead about using and being able to manipulate a TOML data type in the tests instead of a string literal? Dedicated tests could be created in the suite to be confident about the string to TOML parsing and consumption, but for the rest of the test suite instead of a bare string a nicely structured and typed piece of data could be used. WDYT? |
The DSL @matklad is mentioning sounds like a great idea to me! I hadn't thought of that before and it sounds like a great way (even if not the exact syntax) to cut down on the wordiness without losing too much information. I agree with @matklad that we don't want to make things too magical, but I agree with @dwijnand that the changes so far I think have been pretty good in that Cargo.toml stuff is largely just noise compared to the rest of the project |
Declare one-line files on one line, in test projects Builds on #5787 Fixes #5745 unless @alexcrichton feels more can be done there.
Excellent @dwijnand! Thank you so much for looking into this! |
Right now the string literals in Cargo's test suite are a bit of a mess. They're intended to be pretty concise definitions of files all inline in the test itself. Unfortunately over time
rustfmt
has made them look pretty ugly and they're not really that ergonomic any more.What use to be:
is largely now reformatted automatically via
rustfmt
toand "ideally" is instead written as:
Unfortunately this means that the "ideal" way we're writing tests is with 4 levels of indentation, quite a lot!
I'm not really sure of a great solution here, but we should find a strategy that works well with rustfmt's default settings and looks pretty good and easy to write at the same time.
The text was updated successfully, but these errors were encountered: