-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Tracking issue for eRFC 2318, Custom test frameworks #50297
Comments
On stdout/err capture (after doing some research around the proof-of-concept #50457): The current state is sub-optimal, to say the least. Both Relevant libstd snippetsLines 23 to 27 in 935a2f1
Lines 38 to 42 in 935a2f1
Lines 614 to 711 in 935a2f1
The existing stdout/err capture for the test harness works by setting the thread-local, which, if set, the The reason for this is that any solution that's generic over The way I see it, there are three ways to resolve this quirk:
(
|
TL;DR: To have sane capture behavior for stdout and stderr for |
This would be significantly slower on certain platforms where process creation is slow, notably Windows. Especially when the tests are all very quick this will cause severe regressions in total time. |
Another possibility for process separation of tests is to spawn a process for each unit of parallelism, but each process is reused for multiple tests. Of course, we could also just promote the thread-local replaceable stdout/err to The issue is that stdout is, as far as I can tell, a process-local resource. To capture |
if I want to argue about this do I argue about it here? so like I made but I still want the users to be able to use plain old vanilla rust (disclaimer: I don't fully understand the RFC, but it seems to require either replacing everything, or not having tests) |
@SoniEx2 this RFC is about how we'd like to change the underlying mechanism that is used to arrange testing in Rust so that authors can write new test frameworks (e.g., quickcheck) that have access to the same mechanisms as existing built-in tests ( able to access private functions, can find all tagged functions, etc.). The current proposal is relatively wholesale (you change the test framework for a whole crate), but this is something that may be improved upon. We decided against more sophisticated designs in the initial implementation phase (this is just an "experimental" RFC) so that we don't bite off more than we can chew, but I think down the line we'd want more fine-grained test framework selection too. As for your specific example, you don't actually need custom frameworks for that feature :) It seems like you want to only run a test if hexchat isn't running? To do that, you could either mark the test with |
no you don't understand, they have to run inside hexchat. loaded with dlopen (or equivalent). after plugin registration. |
Hey all, I've come up with a simplified proposal and I have an implementation now (though it needs a little cleaning up before a PR). https://blog.jrenner.net/rust/testing/2018/08/06/custom-test-framework-prop.html Lemme know what you think! |
I've thought some more about stdin/stderr capture. Here's a draft of a system that should be able to "perfectly" capture stdin/stdout, though not without O(1) (once per test suite) overhead:
|
@djrenren finally had a chance to read your proposal. I'm excited by the progress on this, though your write-up did raise some questions for me:
|
I think in most cases the CUT won't need to change itself to integrate with the IDE test runner, so long as the IDE understands the test runner you're working with. As I understand how JetBrains' IntelliJ IDEA integrates with both JUnit and Rust's libtest is that it communicates using the standard API and stdin/out. JUnit's integration is obviously tighter, as IDEA was a Java IDE first, but the integration with libtest tests in Rust is already quite good even without any specific integration required. Obviously the IDE needs to understand how the test runner works or the test runner needs to understand how the IDE works, but under most cases of using a popular test runner, the CUT shouldn't need to change to be tested with in-IDE functionality. |
This comment has been minimized.
This comment has been minimized.
I don't want to get too bikesheddy on how that particular macro would work but basically we'd just produce a single const that had the
I agree
This is still entirely possible under the current design, it just requires the test runner to be designed to be pluggable. |
@SoniEx2 It is for crate authors! 😄 For most crate authors (unless you're authoring test machinery), you'll just import any macros you want for declaring tests or benchmarks, and then you'll pick a test runner. For most cases the built-in one should be fine though. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
For those worried about stdout capture, I've just demonstrated how this proposal can allow for @CAD97's style of multiprocess stdout capturing: This code compiles and runs under my PR: #53410 The output of |
And just for clarity, the example does spawn a process for each test, which is suboptimal on OSes where process creation is slow, e.g. Windows. A real runner would implement a scheme like I described earlier to avoid spawning more processes than necessary. (And actually parallelize the running of tests.) |
Whoops, I'm (very) late to the party. I have read the blog post but not looked at the rustc implementation and I'm concerned with the presence of How will this proposal work with the version of Also it would be best if using a custom test runner didn't require an allocator as that requires quite a bit of boilerplate (e.g. Of course I'm not going to block any PR since this is in eRFC state and the idea is to experiment; cc @Manishearth I thought |
This experiment has been open since 2018. It doesn't look like there's been recent development activity on it. I'm going to close this for now. If someone wants to restart this effort, one start would be a lang MCP for a general mechanism for collecting an array of items of the same type from across the program, based on attributes. That mechanism would be generally useful for various things, including tests, tracing, and other annotations. @davidbarsky expressed some interest in working on that MCP. |
What about replacing stdout / stderr like the built in test framework? Using something like inventory, I've gotten good enough support for collecting an array of items for my own nascent test framework. What I don't have is a good way to prevent parallel tests from combining output. |
Honestly at this point I would strongly argue for my original proposal, which was a more proc-macro-esque API that would require minimal changes to the compiler and farm out all the hard stuff to libraries. The main thing that I feel like the lack of interest in dealing with the large amount of design work to get the eRFC as currently written over the hump is a pretty major signal. Plus we have documented use cases in this thread where it's insufficient. I don't have time to go through this again, but if someone is interested I'm happy to help out. I imagine we would still need an MCP but the actual changes would be largely on the cargo side. |
@joshtriplett @Manishearth I'm interested in restarting this proposal, do you have any advice? |
Not much more than go through the RFC and the current code (and any PRs linked to this issue) and see what's missing. I don't remember the status quo unfortunately. I think there's nothing. If you would like to repropose my original proposal that I mentioned above, I think it can be found in the RFC PR's commit history. |
I think the biggest change in rust testing has been the arrival of nextest
on the scene.
…On Sat, 18 Mar 2023 at 15:11, Manish Goregaokar ***@***.***> wrote:
Not much more than go through the RFC and the current code (and any PRs
linked to this issue) and see what's missing. I don't remember the status
quo unfortunately.
—
Reply to this email directly, view it on GitHub
<#50297 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAGEJCB2MXQY72GF6BS5TCLW4XGAJANCNFSM4E5NDDDA>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
cargo-nextest really doesn't address this issue. It's just a different runner that can execute the same test. But it doesn't allow you to alter the design of the tests themselves, for example by creating test functions at runtime, or deciding at runtime that a particular test function should be skipped. |
Yes, although I think @gilescope is talking about changes to the Rust testing ecosystem generally. |
if this issue is closed, then maybe this (https://doc.rust-lang.org/core/prelude/v1/macro.test_case.html) should no longer be labeled as "nightly" and "experimental"? |
This commit makes `use std:convert::TryInto` conditional via `#[cfg(debug_assertions)]`. This avoids the following build error: ``` $ cargo bench ... error: unused import: `std::convert::TryInto` --> src/cast.rs:1:5 | 1 | use std::convert::TryInto; | ^^^^^^^^^^^^^^^^^^^^^ ``` This commit also opts into the `test` feature (only if the "bench" feature is requested, because benchmarking is only available in the nightly version of the compiler) and declares the `extern crate test` dependency on the compiler-provided `test` crate. This avoids the following build errors: ``` $ cargo bench ... error[E0433]: failed to resolve: use of undeclared crate or module `test` --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^ use of undeclared crate or module `test` ``` ``` $ cargo bench ... error[E0658]: use of unstable library feature 'test' --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^^^^^^^^^^ | = note: see issue #50297 <rust-lang/rust#50297> for more information = help: add `#![feature(test)]` to the crate attributes to enable ``` This commit also makes small tweaks to how `README.md` is included. It seems that this doesn't actually test the examples in the `README.md` file (this commit adds a TODO for this observation), but it does avoid the following build error: ``` $ cargo bench --features=bench ... error: unknown `doc` attribute `include` --> src/lib.rs:14:36 | 14 | #![cfg_attr(feature = "bench", doc(include = "../README.md"))] | ----^^^^^^^^^^^^^^^^^^^^^^^^- help: | use `doc = include_str!` instead: | `#![doc = include_str!("../README.md")]` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82730 <rust-lang/rust#82730> ``` Finally, this commit declares the "bench" feature in `Cargo.toml`. After these changes the following command line succeeds: ``` $ cargo bench --features=bench ... test bits::bench_find_min_version ... bench: 1 ns/iter (+/- 0) test bits::bench_push_splitted_bytes ... bench: 3,862 ns/iter (+/- 58) test optimize::bench_optimize ... bench: 19 ns/iter (+/- 0) ```
This commit makes `use std:convert::TryInto` conditional via `#[cfg(debug_assertions)]`. This avoids the following build error: ``` $ cargo bench ... error: unused import: `std::convert::TryInto` --> src/cast.rs:1:5 | 1 | use std::convert::TryInto; | ^^^^^^^^^^^^^^^^^^^^^ ``` This commit also opts into the `test` feature (only if the "bench" feature is requested, because benchmarking is only available in the nightly version of the compiler) and declares the `extern crate test` dependency on the compiler-provided `test` crate. This avoids the following build errors: ``` $ cargo bench ... error[E0433]: failed to resolve: use of undeclared crate or module `test` --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^ use of undeclared crate or module `test` ``` ``` $ cargo bench ... error[E0658]: use of unstable library feature 'test' --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^^^^^^^^^^ | = note: see issue #50297 <rust-lang/rust#50297> for more information = help: add `#![feature(test)]` to the crate attributes to enable ``` This commit also makes small tweaks to how `README.md` is included. It seems that this doesn't actually test the examples in the `README.md` file (this commit adds a TODO for this observation), but it does avoid the following build error: ``` $ cargo bench --features=bench ... error: unknown `doc` attribute `include` --> src/lib.rs:14:36 | 14 | #![cfg_attr(feature = "bench", doc(include = "../README.md"))] | ----^^^^^^^^^^^^^^^^^^^^^^^^- help: | use `doc = include_str!` instead: | `#![doc = include_str!("../README.md")]` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82730 <rust-lang/rust#82730> ``` Finally, this commit declares the "bench" feature in `Cargo.toml`. After these changes the following command line succeeds: ``` $ cargo bench --features=bench ... test bits::bench_find_min_version ... bench: 1 ns/iter (+/- 0) test bits::bench_push_splitted_bytes ... bench: 3,862 ns/iter (+/- 58) test optimize::bench_optimize ... bench: 19 ns/iter (+/- 0) ```
This commit makes `use std:convert::TryInto` conditional via `#[cfg(debug_assertions)]`. This avoids the following build error: ``` $ cargo bench ... error: unused import: `std::convert::TryInto` --> src/cast.rs:1:5 | 1 | use std::convert::TryInto; | ^^^^^^^^^^^^^^^^^^^^^ ``` This commit also opts into the `test` feature (only if the "bench" feature is requested, because benchmarking is only available in the nightly version of the compiler) and declares the `extern crate test` dependency on the compiler-provided `test` crate. This avoids the following build errors: ``` $ cargo bench ... error[E0433]: failed to resolve: use of undeclared crate or module `test` --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^ use of undeclared crate or module `test` ``` ``` $ cargo bench ... error[E0658]: use of unstable library feature 'test' --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^^^^^^^^^^ | = note: see issue #50297 <rust-lang/rust#50297> for more information = help: add `#![feature(test)]` to the crate attributes to enable ``` This commit also makes small tweaks to how `README.md` is included. It seems that this doesn't actually test the examples in the `README.md` file (this commit adds a TODO for this observation), but it does avoid the following build error: ``` $ cargo bench --features=bench ... error: unknown `doc` attribute `include` --> src/lib.rs:14:36 | 14 | #![cfg_attr(feature = "bench", doc(include = "../README.md"))] | ----^^^^^^^^^^^^^^^^^^^^^^^^- help: | use `doc = include_str!` instead: | `#![doc = include_str!("../README.md")]` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82730 <rust-lang/rust#82730> ``` Finally, this commit declares the "bench" feature in `Cargo.toml`. After these changes the following command line succeeds: ``` $ cargo bench --features=bench ... test bits::bench_find_min_version ... bench: 1 ns/iter (+/- 0) test bits::bench_push_splitted_bytes ... bench: 3,862 ns/iter (+/- 58) test optimize::bench_optimize ... bench: 19 ns/iter (+/- 0) ```
This commit makes `use std:convert::TryInto` conditional via `#[cfg(debug_assertions)]`. This avoids the following build error: ``` $ cargo bench ... error: unused import: `std::convert::TryInto` --> src/cast.rs:1:5 | 1 | use std::convert::TryInto; | ^^^^^^^^^^^^^^^^^^^^^ ``` This commit also opts into the `test` feature (only if the "bench" feature is requested, because benchmarking is only available in the nightly version of the compiler) and declares the `extern crate test` dependency on the compiler-provided `test` crate. This avoids the following build errors: ``` $ cargo bench ... error[E0433]: failed to resolve: use of undeclared crate or module `test` --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^ use of undeclared crate or module `test` ``` ``` $ cargo bench ... error[E0658]: use of unstable library feature 'test' --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^^^^^^^^^^ | = note: see issue #50297 <rust-lang/rust#50297> for more information = help: add `#![feature(test)]` to the crate attributes to enable ``` This commit also makes small tweaks to how `README.md` is included. It seems that this doesn't actually test the examples in the `README.md` file (this commit adds a TODO for this observation), but it does avoid the following build error: ``` $ cargo bench --features=bench ... error: unknown `doc` attribute `include` --> src/lib.rs:14:36 | 14 | #![cfg_attr(feature = "bench", doc(include = "../README.md"))] | ----^^^^^^^^^^^^^^^^^^^^^^^^- help: | use `doc = include_str!` instead: | `#![doc = include_str!("../README.md")]` | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #82730 <rust-lang/rust#82730> ``` Finally, this commit declares the "bench" feature in `Cargo.toml`. After these changes the following command line succeeds: ``` $ cargo bench --features=bench ... test bits::bench_find_min_version ... bench: 1 ns/iter (+/- 0) test bits::bench_push_splitted_bytes ... bench: 3,862 ns/iter (+/- 58) test optimize::bench_optimize ... bench: 19 ns/iter (+/- 0) ```
Benchmarking is only supported by Rust nightly and therefore before this commit it was disabled by default and hidden behind `bench` feature. OTOH, declaring such feature in `Cargo.toml` would have broken `cargo +stable test --all-features`. Therefore the commit switches from using a `bench` *feature* to using a `bench` config. This commit also makes `use std:convert::TryInto` conditional via `#[cfg(debug_assertions)]`. This avoids the following build error: ``` $ RUSTFLAGS='--cfg=bench' cargo +nightly bench --all-features ... error: unused import: `std::convert::TryInto` --> src/cast.rs:1:5 | 1 | use std::convert::TryInto; | ^^^^^^^^^^^^^^^^^^^^^ ``` Additionally, this commit also opts into the `test` feature (only if the "bench" configurtaion is requested, because benchmarking is only available in the nightly version of the compiler) and declares the `extern crate test` dependency on the compiler-provided `test` crate. This avoids the following build errors: ``` $ RUSTFLAGS='--cfg=bench' cargo +nightly bench --all-features ... error[E0433]: failed to resolve: use of undeclared crate or module `test` --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^ use of undeclared crate or module `test` ``` ``` $ RUSTFLAGS='--cfg=bench' cargo +nightly bench --all-features ... error[E0658]: use of unstable library feature 'test' --> src/optimize.rs:710:33 | 710 | fn bench_optimize(bencher: &mut test::Bencher) { | ^^^^^^^^^^^^^ | = note: see issue #50297 <rust-lang/rust#50297> for more information = help: add `#![feature(test)]` to the crate attributes to enable ``` After these changes the following command line succeeds: ``` $ RUSTFLAGS='--cfg=bench' cargo +nightly bench --all-features ... test bits::bench_find_min_version ... bench: 1 ns/iter (+/- 0) test bits::bench_push_splitted_bytes ... bench: 3,862 ns/iter (+/- 58) test optimize::bench_optimize ... bench: 19 ns/iter (+/- 0) ```
Some crates already exploit the |
I was looking at using datatest -- it seems to address my needs to produce test cases from json. However, it requires And this being the tracking RFC for that feature, what does it mean for it to be closed? Is this effectively nightly-only, forever? Will it be removed? Is it destined for the same purgatory as If this is permanently abandoned, it would be good if this issue, and the unstable book recorded that in a clear way. |
I just wanted to link this tracking issue here, as it's somewhat related: |
I followed unstable book of |
This is a tracking issue for the eRFC "Custom test frameworks" (rust-lang/rfcs#2318).
Documentation:
Steps:
Unresolved questions:
Notes:
#[bench]
: [1.38]#[bench]
accepted on stable but not beta #63798 (comment)Implementation history:
The text was updated successfully, but these errors were encountered: