diff --git a/README.md b/README.md index ce7a35d..49a803e 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,14 @@ async fn test_serial_another() { // Do things asynchronously } ``` -Multiple tests with the `serial` attribute are guaranteed to be executed in serial. Ordering of the tests is not guaranteed however. -Tests without the `serial` attribute may run at any time, including in parallel to tests marked as `serial`. Note that if you're using -an async test reactor attribute (e.g. `tokio::test` or `actix_rt::test`) then they should be listed *before* `serial`, otherwise we +Multiple tests with the `serial` attribute are guaranteed to be executed in serial. Ordering of the tests is not guaranteed however. Other tests with the `parallel` attribute may run at the same time as each other, but not at the same time as a test with `serial`. Tests with neither attribute may run at any time and no guarantees are made about their timing! + +Note that if you're using an async test reactor attribute (e.g. `tokio::test` or `actix_rt::test`) then they should be listed *before* `serial`, otherwise we don't get an async function and things break. There's now an error for this case to improve debugging. For cases like doctests and integration tests where the tests are run as separate processes, we also support `file_serial`, with similar properties but based off file locking. Note that there are no guarantees about one test with `serial` and another with -`file_serial` as they lock using different methods. +`file_serial` as they lock using different methods, and `parallel` doesn't support `file_serial` yet (patches welcomed!). ## Usage We require at least Rust 1.51. Upgrades to this will require at least a minor version bump (while in 0.x versions) and a major version bump post-1.0. diff --git a/serial_test/src/code_lock.rs b/serial_test/src/code_lock.rs index 274d875..24534c4 100644 --- a/serial_test/src/code_lock.rs +++ b/serial_test/src/code_lock.rs @@ -49,8 +49,8 @@ impl Default for UniqueReentrantMutex { } } -/// Sets the maximum amount of time the serial locks will wait to unlock -/// By default, this is set to 60 seconds, which is almost always much longer than is needed +/// Sets the maximum amount of time the serial locks will wait to unlock. +/// By default, this is set to 60 seconds, which is almost always much longer than is needed. /// This is deliberately set high to try and avoid situations where we accidentally hit the limits /// but is set at all so we can timeout rather than hanging forever. /// diff --git a/serial_test/src/lib.rs b/serial_test/src/lib.rs index 932d1e8..78eaa46 100644 --- a/serial_test/src/lib.rs +++ b/serial_test/src/lib.rs @@ -15,10 +15,19 @@ //! fn test_serial_another() { //! // Do things //! } +//! +//! #[test] +//! #[parallel] +//! fn test_parallel_another() { +//! // Do parallel things +//! } //! ```` //! Multiple tests with the [serial](macro@serial) attribute are guaranteed to be executed in serial. Ordering -//! of the tests is not guaranteed however. Tests without the `serial` attribute may run at any time, including -//! in parallel to tests marked as `serial`. Note that if you're using an async test reactor attribute (e.g. +//! of the tests is not guaranteed however. Other tests with the [parallel](macro@parallel) attribute may run +//! at the same time as each other, but not at the same time as a test with [serial](macro@serial). Tests with +//! neither attribute may run at any time and no guarantees are made about their timing! +//! +//! Note that if you're using an async test reactor attribute (e.g. //! `tokio::test` or `actix_rt::test`) then they should be listed *before* `serial`, otherwise we don't get an //! async function and things break. There's now an error for this case to improve debugging. //! diff --git a/serial_test_derive/src/lib.rs b/serial_test_derive/src/lib.rs index f3b5e88..972ff4f 100644 --- a/serial_test_derive/src/lib.rs +++ b/serial_test_derive/src/lib.rs @@ -26,7 +26,10 @@ use std::ops::Deref; /// } /// ```` /// Multiple tests with the [serial](macro@serial) attribute are guaranteed to be executed in serial. Ordering -/// of the tests is not guaranteed however. If you want different subsets of tests to be serialised with each +/// of the tests is not guaranteed however. If you have other tests that can be run in parallel, but would clash +/// if run at the same time as the [serial](macro@serial) tests, you can use the [parallel](macro@parallel) attribute. +/// +/// If you want different subsets of tests to be serialised with each /// other, but not depend on other subsets, you can add an argument to [serial](macro@serial), and all calls /// with identical arguments will be called in serial. e.g. /// ```` @@ -57,13 +60,41 @@ use std::ops::Deref; /// `test_serial_one` and `test_serial_another` will be executed in serial, as will `test_serial_third` and `test_serial_fourth` /// but neither sequence will be blocked by the other /// -/// Nested serialised tests (i.e. a [serial](macro@serial) tagged test calling another) is supported +/// Nested serialised tests (i.e. a [serial](macro@serial) tagged test calling another) are supported #[proc_macro_attribute] #[proc_macro_error] pub fn serial(attr: TokenStream, input: TokenStream) -> TokenStream { local_serial_core(attr.into(), input.into()).into() } +/// Allows for the creation of parallel Rust tests that won't clash with serial tests +/// ```` +/// #[test] +/// #[serial] +/// fn test_serial_one() { +/// // Do things +/// } +/// +/// #[test] +/// #[parallel] +/// fn test_parallel_one() { +/// // Do things +/// } +/// +/// #[test] +/// #[parallel] +/// fn test_parallel_two() { +/// // Do things +/// } +/// ```` +/// Multiple tests with the [parallel](macro@parallel) attribute may run in parallel, but not at the +/// same time as [serial](macro@serial) tests. e.g. in the example code above, `test_parallel_one` +/// and `test_parallel_two` may run at the same time, but `test_serial_one` is guaranteed not to run +/// at the same time as either of them. [parallel](macro@parallel) also takes key arguments for groups +/// of tests as per [serial](macro@serial). +/// +/// Note that this has zero effect on [file_serial](macro@file_serial) tests, as that uses a different +/// serialisation mechanism. #[proc_macro_attribute] #[proc_macro_error] pub fn parallel(attr: TokenStream, input: TokenStream) -> TokenStream {