rstest-0.17.0/.cargo_vcs_info.json0000644000000001440000000000100124440ustar { "git": { "sha1": "7ac624c3a54de3d7a1506441863562371c5a2359" }, "path_in_vcs": "rstest" }rstest-0.17.0/Cargo.toml0000644000000036250000000000100104510ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "rstest" version = "0.17.0" authors = ["Michele d'Amico "] description = """ Rust fixture based test framework. It use procedural macro to implement fixtures and table based tests. """ homepage = "https://github.com/la10736/rstest" readme = "README.md" keywords = [ "test", "fixture", ] categories = ["development-tools::testing"] license = "MIT/Apache-2.0" repository = "https://github.com/la10736/rstest" [lib] [dependencies.futures] version = "0.3.21" optional = true [dependencies.futures-timer] version = "3.0.2" optional = true [dependencies.rstest_macros] version = "0.17.0" default-features = false [dev-dependencies.actix-rt] version = "2.7.0" [dev-dependencies.async-std] version = "1.12.0" features = ["attributes"] [dev-dependencies.lazy_static] version = "1.4.0" [dev-dependencies.mytest] version = "0.16.0" default-features = false package = "rstest" [dev-dependencies.pretty_assertions] version = "1.2.1" [dev-dependencies.rstest_reuse] version = "0.5.0" [dev-dependencies.rstest_test] version = "0.11.0" [dev-dependencies.temp_testdir] version = "0.2.3" [dev-dependencies.tokio] version = "1.19.2" features = [ "rt", "macros", ] [dev-dependencies.unindent] version = "0.2.1" [build-dependencies.rustc_version] version = "0.4.0" [features] async-timeout = [ "dep:futures", "dep:futures-timer", "rstest_macros/async-timeout", ] default = ["async-timeout"] rstest-0.17.0/Cargo.toml.orig000064400000000000000000000024161046102023000141270ustar 00000000000000[package] authors = ["Michele d'Amico "] categories = ["development-tools::testing"] description = """ Rust fixture based test framework. It use procedural macro to implement fixtures and table based tests. """ edition = "2018" homepage = "https://github.com/la10736/rstest" keywords = ["test", "fixture"] license = "MIT/Apache-2.0" name = "rstest" readme = "README.md" repository = "https://github.com/la10736/rstest" version = "0.17.0" [features] async-timeout = ["dep:futures", "dep:futures-timer", "rstest_macros/async-timeout"] default = ["async-timeout"] [lib] [dependencies] futures = {version = "0.3.21", optional = true} futures-timer = {version = "3.0.2", optional = true} rstest_macros = {version = "0.17.0", path = "../rstest_macros", default-features = false} [dev-dependencies] actix-rt = "2.7.0" async-std = {version = "1.12.0", features = ["attributes"]} lazy_static = "1.4.0" mytest = {package = "rstest", version = "0.16.0", default-features = false} pretty_assertions = "1.2.1" rstest_reuse = {version = "0.5.0", path = "../rstest_reuse"} rstest_test = {version = "0.11.0", path = "../rstest_test"} temp_testdir = "0.2.3" tokio = {version = "1.19.2", features = ["rt", "macros"]} unindent = "0.2.1" [build-dependencies] rustc_version = "0.4.0" rstest-0.17.0/README.md000064400000000000000000000315161046102023000125220ustar 00000000000000[![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] [![Status][test-action-image]][test-action-link] [![Apache 2.0 Licensed][license-apache-image]][license-apache-link] [![MIT Licensed][license-mit-image]][license-mit-link] # Fixture-based test framework for Rust ## Introduction `rstest` uses procedural macros to help you on writing fixtures and table-based tests. To use it, add the following lines to your `Cargo.toml` file: ``` [dev-dependencies] rstest = "0.17.0" ``` ### Fixture The core idea is that you can inject your test dependencies by passing them as test arguments. In the following example, a `fixture` is defined and then used in two tests, simply providing it as an argument: ```rust use rstest::*; #[fixture] pub fn fixture() -> u32 { 42 } #[rstest] fn should_success(fixture: u32) {     assert_eq!(fixture, 42); } #[rstest] fn should_fail(fixture: u32) {     assert_ne!(fixture, 42); } ``` ### Parametrize You can also inject values in some other ways. For instance, you can create a set of tests by simply providing the injected values for each case: `rstest` will generate an independent test for each case. ```rust use rstest::rstest; #[rstest] #[case(0, 0)] #[case(1, 1)] #[case(2, 1)] #[case(3, 2)] #[case(4, 3)] fn fibonacci_test(#[case] input: u32, #[case] expected: u32) { assert_eq!(expected, fibonacci(input)) } ``` Running `cargo test` in this case executes five tests: ```bash running 5 tests test fibonacci_test::case_1 ... ok test fibonacci_test::case_2 ... ok test fibonacci_test::case_3 ... ok test fibonacci_test::case_4 ... ok test fibonacci_test::case_5 ... ok test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` If you need to just providing a bunch of values for which you need to run your test, you can use `#[values(list, of, values)]` argument attribute: ```rust use rstest::rstest; #[rstest] fn should_be_invalid( #[values(None, Some(""), Some(" "))] value: Option<&str> ) { assert!(!valid(value)) } ``` Or create a _matrix_ test by using _list of values_ for some variables that will generate the cartesian product of all the values. #### Use Parametrize definition in more tests If you need to use a test list for more than one test you can use [`rstest_reuse`][reuse-crate-link] crate. With this helper crate you can define a template and use it everywhere . ```rust use rstest::rstest; use rstest_reuse::{self, *}; #[template] #[rstest] #[case(2, 2)] #[case(4/2, 2)] fn two_simple_cases(#[case] a: u32, #[case] b: u32) {} #[apply(two_simple_cases)] fn it_works(#[case] a: u32, #[case] b: u32) { assert!(a == b); } ``` See [`rstest_reuse`][reuse-crate-link] for more dettails. ### Magic Conversion If you need a value where its type implement `FromStr()` trait you can use a literal string to build it: ```rust # use rstest::rstest; # use std::net::SocketAddr; #[rstest] #[case("1.2.3.4:8080", 8080)] #[case("127.0.0.1:9000", 9000)] fn check_port(#[case] addr: SocketAddr, #[case] expected: u16) { assert_eq!(expected, addr.port()); } ``` You can use this feature also in value list and in fixture default value. ### Async `rstest` provides out of the box `async` support. Just mark your test function as `async` and it'll use `#[async-std::test]` to annotate it. This feature can be really useful to build async parametric tests using a tidy syntax: ```rust use rstest::*; #[rstest] #[case(5, 2, 3)] #[should_panic] #[case(42, 40, 1)] async fn my_async_test(#[case] expected: u32, #[case] a: u32, #[case] b: u32) { assert_eq!(expected, async_sum(a, b).await); } ``` Currently only `async-std` is supported out of the box. But if you need to use another runtime that provide it's own test attribute (i.e. `tokio::test` or `actix_rt::test`) you can use it in your `async` test like described in [Inject Test Attribute](#inject-test-attribute). To use this feature, you need to enable `attributes` in the `async-std` features list in your `Cargo.toml`: ```toml async-std = { version = "1.5", features = ["attributes"] } ``` If your test input is an async value (fixture or test parameter) you can use `#[future]` attribute to remove `impl Future` boilerplate and just use `T`: ```rust use rstest::*; #[fixture] async fn base() -> u32 { 42 } #[rstest] #[case(21, async { 2 })] #[case(6, async { 7 })] async fn my_async_test(#[future] base: u32, #[case] expected: u32, #[future] #[case] div: u32) { assert_eq!(expected, base.await / div.await); } ``` As you noted you should `.await` all _future_ values and this some times can be really boring. In this case you can use `#[timeout(awt)]` to _awaiting_ an input or annotating your function with `#[awt]` attributes to globally `.await` all your _future_ inputs. Previous code can be simplified like follow: ```rust use rstest::*; # #[fixture] # async fn base() -> u32 { 42 } #[rstest] #[case(21, async { 2 })] #[case(6, async { 7 })] #[awt] async fn global(#[future] base: u32, #[case] expected: u32, #[future] #[case] div: u32) { assert_eq!(expected, base / div); } #[rstest] #[case(21, async { 2 })] #[case(6, async { 7 })] async fn single(#[future] base: u32, #[case] expected: u32, #[future(awt)] #[case] div: u32) { assert_eq!(expected, base.await / div); } ``` ### Test `#[timeout()]` You can define an execution timeout for your tests with `#[timeout()]` attribute. Timeouts works both for sync and async tests and is runtime agnostic. `#[timeout()]` take an expression that should return a `std::time::Duration`. Follow a simple async example: ```rust use rstest::*; use std::time::Duration; async fn delayed_sum(a: u32, b: u32,delay: Duration) -> u32 { async_std::task::sleep(delay).await; a + b } #[rstest] #[timeout(Duration::from_millis(80))] async fn single_pass() { assert_eq!(4, delayed_sum(2, 2, ms(10)).await); } ``` In this case test pass because the delay is just 10 milliseconds and timeout is 80 milliseconds. You can use `timeout` attribute like any other attibute in your tests and you can override a group timeout with a case specific one. In the follow example we have 3 tests where first and third use 100 millis but the second one use 10 millis. Another valuable point in this example is to use an expression to compute the duration. ```rust fn ms(ms: u32) -> Duration { Duration::from_millis(ms.into()) } #[rstest] #[case::pass(ms(1), 4)] #[timeout(ms(10))] #[case::fail_timeout(ms(60), 4)] #[case::fail_value(ms(1), 5)] #[timeout(ms(100))] async fn group_one_timeout_override(#[case] delay: Duration, #[case] expected: u32) { assert_eq!(expected, delayed_sum(2, 2, delay).await); } ``` If you want to use `timeout` for `async` test you need to use `async-timeout` feature (enabled by default). ### Inject Test Attribute If you would like to use another `test` attribute for your test you can simply indicate it in your test function's attributes. For instance if you want to test some async function with use `actix_rt::test` attribute you can just write: ```rust use rstest::*; use actix_rt; use std::future::Future; #[rstest] #[case(2, async { 4 })] #[case(21, async { 42 })] #[actix_rt::test] async fn my_async_test(#[case] a: u32, result: #[case] #[future] u32) { assert_eq!(2 * a, result.await); } ``` Just the attributes that ends with `test` (last path segment) can be injected. ### Use `#[once]` Fixture If you need to a fixture that should be inizialized just once for all tests you can use `#[once]` attribute. `rstest` call your fixture function just once and return a reference to your function result to all your tests: ```rust #[fixture] #[once] fn once_fixture() -> i32 { 42 } #[rstest] fn single(once_fixture: &i32) { // All tests that use once_fixture will share the same reference to once_fixture() // function result. assert_eq!(&42, once_fixture) } ``` ## Complete Example All these features can be used together with a mixture of fixture variables, fixed cases and bunch of values. For instance, you might need two test cases which test for panics, one for a logged in user and one for a guest user. ```rust use rstest::*; #[fixture] fn repository() -> InMemoryRepository { let mut r = InMemoryRepository::default(); // fill repository with some data r } #[fixture] fn alice() -> User { User::logged("Alice", "2001-10-04", "London", "UK") } #[rstest] #[case::authed_user(alice())] // We can use `fixture` also as standard function #[case::guest(User::Guest)] // We can give a name to every case : `guest` in this case // and `authed_user` #[should_panic(expected = "Invalid query error")] // We whould test a panic fn should_be_invalid_query_error( repository: impl Repository, #[case] user: User, #[values(" ", "^%$some#@invalid!chars", ".n.o.d.o.t.s.")] query: &str, ) { repository.find_items(&user, query).unwrap(); } ``` This example will generate exactly 6 tests grouped by 2 different cases: ``` running 6 tests test should_be_invalid_query_error::case_1_authed_user::query_1_____ - should panic ... ok test should_be_invalid_query_error::case_2_guest::query_2_____someinvalid_chars__ - should panic ... ok test should_be_invalid_query_error::case_1_authed_user::query_2_____someinvalid_chars__ - should panic ... ok test should_be_invalid_query_error::case_2_guest::query_3____n_o_d_o_t_s___ - should panic ... ok test should_be_invalid_query_error::case_1_authed_user::query_3____n_o_d_o_t_s___ - should panic ... ok test should_be_invalid_query_error::case_2_guest::query_1_____ - should panic ... ok test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` Note that the names of the values _try_ to convert the input expression in a Rust valid identifier name to help you to find wich tests fail. ## More Is that all? Not quite yet! A fixture can be injected by another fixture and they can be called using just some of its arguments. ```rust #[fixture] fn user(#[default("Alice")] name: &str, #[default(22)] age: u8) -> User { User::new(name, age) } #[rstest] fn is_alice(user: User) { assert_eq!(user.name(), "Alice") } #[rstest] fn is_22(user: User) { assert_eq!(user.age(), 22) } #[rstest] fn is_bob(#[with("Bob")] user: User) { assert_eq!(user.name(), "Bob") } #[rstest] fn is_42(#[with("", 42)] user: User) { assert_eq!(user.age(), 42) } ``` As you noted you can provide default values without the need of a fixture to define it. Finally if you need tracing the input values you can just add the `trace` attribute to your test to enable the dump of all input variables. ```rust #[rstest] #[case(42, "FortyTwo", ("minus twelve", -12))] #[case(24, "TwentyFour", ("minus twentyfour", -24))] #[trace] //This attribute enable traceing fn should_fail(#[case] number: u32, #[case] name: &str, #[case] tuple: (&str, i32)) { assert!(false); // <- stdout come out just for failed tests } ``` ``` running 2 tests test should_fail::case_1 ... FAILED test should_fail::case_2 ... FAILED failures: ---- should_fail::case_1 stdout ---- ------------ TEST ARGUMENTS ------------ number = 42 name = "FortyTwo" tuple = ("minus twelve", -12) -------------- TEST START -------------- thread 'should_fail::case_1' panicked at 'assertion failed: false', src/main.rs:64:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. ---- should_fail::case_2 stdout ---- ------------ TEST ARGUMENTS ------------ number = 24 name = "TwentyFour" tuple = ("minus twentyfour", -24) -------------- TEST START -------------- thread 'should_fail::case_2' panicked at 'assertion failed: false', src/main.rs:64:5 failures: should_fail::case_1 should_fail::case_2 test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out ``` In case one or more variables don't implement the `Debug` trait, an error is raised, but it's also possible to exclude a variable using the `#[notrace]` argument attribute. You can learn more on [Docs][docs-link] and find more examples in [`tests/resources`](tests/resources) directory. ## Changelog See [CHANGELOG.md](CHANGELOG.md) ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [license-apache-link]) * MIT license [LICENSE-MIT](LICENSE-MIT) or [license-MIT-link] at your option. [//]: # (links) [crate-image]: https://img.shields.io/crates/v/rstest.svg [crate-link]: https://crates.io/crates/rstest [docs-image]: https://docs.rs/rstest/badge.svg [docs-link]: https://docs.rs/rstest/ [test-action-image]: https://github.com/la10736/rstest/workflows/Test/badge.svg [test-action-link]: https://github.com/la10736/rstest/actions?query=workflow:Test [license-apache-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg [license-mit-image]: https://img.shields.io/badge/license-MIT-blue.svg [license-apache-link]: http://www.apache.org/licenses/LICENSE-2.0 [license-MIT-link]: http://opensource.org/licenses/MIT [reuse-crate-link]: https://crates.io/crates/rstest_reuse rstest-0.17.0/src/lib.rs000064400000000000000000000177121046102023000131500ustar 00000000000000//! This crate will help you to write simpler tests by leveraging a software testing concept called //! [test fixtures](https://en.wikipedia.org/wiki/Test_fixture#Software). A fixture is something //! that you can use in your tests to encapsulate a test's dependencies. //! //! The general idea is to have smaller tests that only describe the thing you're testing while you //! hide the auxiliary utilities your tests make use of somewhere else. //! For instance, if you have an application that has many tests with users, shopping baskets, and //! products, you'd have to create a user, a shopping basket, and product every single time in //! every test which becomes unwieldy quickly. In order to cut down on that repetition, you can //! instead use fixtures to declare that you need those objects for your function and the fixtures //! will take care of creating those by themselves. Focus on the important stuff in your tests! //! //! In `rstest` a fixture is a function that can return any kind of valid Rust type. This //! effectively means that your fixtures are not limited by the kind of data they can return. //! A test can consume an arbitrary number of fixtures at the same time. //! //! ## What //! //! The `rstest` crate defines the following procedural macros: //! //! - [`[rstest]`](macro@rstest): Declare that a test or a group of tests that may take //! [fixtures](attr.rstest.html#injecting-fixtures), //! [input table](attr.rstest.html#test-parametrized-cases) or //! [list of values](attr.rstest.html#values-lists). //! - [`[fixture]`](macro@fixture): To mark a function as a fixture. //! //! ## Why //! //! Very often in Rust we write tests like this //! //! ``` //! #[test] //! fn should_process_two_users() { //! let mut repository = create_repository(); //! repository.add("Bob", 21); //! repository.add("Alice", 22); //! //! let processor = string_processor(); //! processor.send_all(&repository, "Good Morning"); //! //! assert_eq!(2, processor.output.find("Good Morning").count()); //! assert!(processor.output.contains("Bob")); //! assert!(processor.output.contains("Alice")); //! } //! ``` //! //! By making use of [`[rstest]`](macro@rstest) we can isolate the dependencies `empty_repository` and //! `string_processor` by passing them as fixtures: //! //! ``` //! # use rstest::*; //! #[rstest] //! fn should_process_two_users(mut empty_repository: impl Repository, //! string_processor: FakeProcessor) { //! empty_repository.add("Bob", 21); //! empty_repository.add("Alice", 22); //! //! string_processor.send_all("Good Morning"); //! //! assert_eq!(2, string_processor.output.find("Good Morning").count()); //! assert!(string_processor.output.contains("Bob")); //! assert!(string_processor.output.contains("Alice")); //! } //! ``` //! //! ... or if you use `"Alice"` and `"Bob"` in other tests, you can isolate `alice_and_bob` fixture //! and use it directly: //! //! ``` //! # use rstest::*; //! # trait Repository { fn add(&mut self, name: &str, age: u8); } //! # struct Rep; //! # impl Repository for Rep { fn add(&mut self, name: &str, age: u8) {} } //! # #[fixture] //! # fn empty_repository() -> Rep { //! # Rep //! # } //! #[fixture] //! fn alice_and_bob(mut empty_repository: impl Repository) -> impl Repository { //! empty_repository.add("Bob", 21); //! empty_repository.add("Alice", 22); //! empty_repository //! } //! //! #[rstest] //! fn should_process_two_users(alice_and_bob: impl Repository, //! string_processor: FakeProcessor) { //! string_processor.send_all("Good Morning"); //! //! assert_eq!(2, string_processor.output.find("Good Morning").count()); //! assert!(string_processor.output.contains("Bob")); //! assert!(string_processor.output.contains("Alice")); //! } //! ``` //! //! ## Injecting fixtures as function arguments //! //! `rstest` functions can receive fixtures by using them as input arguments. //! A function decorated with [`[rstest]`](attr.rstest.html#injecting-fixtures) //! will resolve each argument name by call the fixture function. //! Fixtures should be annotated with the [`[fixture]`](macro@fixture) attribute. //! //! Fixtures will be resolved like function calls by following the standard resolution rules. //! Therefore, an identically named fixture can be use in different context. //! //! ``` //! # use rstest::*; //! # trait Repository { } //! # #[derive(Default)] //! # struct DataSet {} //! # impl Repository for DataSet { } //! mod empty_cases { //! # use rstest::*; //! # trait Repository { } //! # #[derive(Default)] //! # struct DataSet {} //! # impl Repository for DataSet { } //! use super::*; //! //! #[fixture] //! fn repository() -> impl Repository { //! DataSet::default() //! } //! //! #[rstest] //! fn should_do_nothing(repository: impl Repository) { //! //.. test impl .. //! } //! } //! //! mod non_trivial_case { //! # use rstest::*; //! # trait Repository { } //! # #[derive(Default)] //! # struct DataSet {} //! # impl Repository for DataSet { } //! use super::*; //! //! #[fixture] //! fn repository() -> impl Repository { //! let mut ds = DataSet::default(); //! // Fill your dataset with interesting case //! ds //! } //! //! #[rstest] //! fn should_notify_all_entries(repository: impl Repository) { //! //.. test impl .. //! } //! } //! //! ``` //! //! Last but not least, fixtures can be injected like we saw in `alice_and_bob` example. //! //! ## Creating parametrized tests //! //! You can use also [`[rstest]`](attr.rstest.html#test-parametrized-cases) to create //! simple table-based tests. Let's see the classic Fibonacci example: //! //! ``` //! use rstest::rstest; //! //! #[rstest] //! #[case(0, 0)] //! #[case(1, 1)] //! #[case(2, 1)] //! #[case(3, 2)] //! #[case(4, 3)] //! #[case(5, 5)] //! #[case(6, 8)] //! fn fibonacci_test(#[case] input: u32,#[case] expected: u32) { //! assert_eq!(expected, fibonacci(input)) //! } //! //! fn fibonacci(input: u32) -> u32 { //! match input { //! 0 => 0, //! 1 => 1, //! n => fibonacci(n - 2) + fibonacci(n - 1) //! } //! } //! ``` //! This will generate a bunch of tests, one for every `#[case(a, b)]`. //! //! ## Creating a test for each combinations of given values //! //! In some cases you need to test your code for each combinations of some input values. In this //! cases [`[rstest]`](attr.rstest.html#values-lists) give you the ability to define a list //! of values (rust expressions) to use for an arguments. //! //! ``` //! # use rstest::rstest; //! # #[derive(PartialEq, Debug)] //! # enum State { Init, Start, Processing, Terminated } //! # #[derive(PartialEq, Debug)] //! # enum Event { Error, Fatal } //! # impl State { fn process(self, event: Event) -> Self { self } } //! //! #[rstest] //! fn should_terminate( //! #[values(State::Init, State::Start, State::Processing)] //! state: State, //! #[values(Event::Error, Event::Fatal)] //! event: Event //! ) { //! assert_eq!(State::Terminated, state.process(event)) //! } //! ``` //! //! This will generate a test for each combination of `state` and `event`. //! //! ## Magic Conversion //! //! If you need a value where its type implement `FromStr()` trait you //! can use a literal string to build it. //! //! ``` //! # use rstest::rstest; //! # use std::net::SocketAddr; //! #[rstest] //! #[case("1.2.3.4:8080", 8080)] //! #[case("127.0.0.1:9000", 9000)] //! fn check_port(#[case] addr: SocketAddr, #[case] expected: u16) { //! assert_eq!(expected, addr.port()); //! } //! ``` //! You can use this feature also in value list and in fixture default value. //! //! # Optional features //! //! `rstest` Enable all fetures by default. You can disable them if you need to //! speed up compilation. //! //! - **`async-timeout`** *(enabled by default)* — Implement timeout for async //! tests. #[doc(hidden)] pub mod magic_conversion; #[doc(hidden)] pub mod timeout; pub use rstest_macros::{fixture, rstest}; rstest-0.17.0/src/magic_conversion.rs000064400000000000000000000045301046102023000157210ustar 00000000000000pub struct Magic(pub std::marker::PhantomData); pub trait ViaParseDebug<'a, T> { fn magic_conversion(&self, input: &'a str) -> T; } impl<'a, T> ViaParseDebug<'a, T> for &&Magic where T: std::str::FromStr, T::Err: std::fmt::Debug, { fn magic_conversion(&self, input: &'a str) -> T { T::from_str(input).unwrap() } } pub trait ViaParse<'a, T> { fn magic_conversion(&self, input: &'a str) -> T; } impl<'a, T> ViaParse<'a, T> for &Magic where T: std::str::FromStr, { fn magic_conversion(&self, input: &'a str) -> T { match T::from_str(input) { Ok(v) => v, Err(_) => { panic!( "Cannot parse '{}' to get {}", input, std::any::type_name::() ); } } } } pub trait ViaIdent<'a, T> { fn magic_conversion(&self, input: &'a str) -> T; } impl<'a> ViaIdent<'a, &'a str> for &&Magic<&'a str> { fn magic_conversion(&self, input: &'a str) -> &'a str { input } } #[cfg(test)] mod test { use super::*; use std::str::FromStr; #[test] fn should_return_the_same_slice_string() { assert_eq!( "something", (&&&Magic::<&str>(std::marker::PhantomData)).magic_conversion("something") ); } #[test] fn should_parse_via_parse_debug() { assert_eq!( 42u32, (&&&Magic::(std::marker::PhantomData)).magic_conversion("42") ); } #[test] fn should_parse_via_parse_no_error_debug() { struct S(String); struct E; impl FromStr for S { type Err = E; fn from_str(s: &str) -> Result { Ok(S(s.to_owned())) } } assert_eq!( "some", (&&&Magic::(std::marker::PhantomData)) .magic_conversion("some") .0 ); } #[test] #[should_panic(expected = "MyTypeName")] fn should_show_error() { struct MyTypeName; struct E; impl FromStr for MyTypeName { type Err = E; fn from_str(_s: &str) -> Result { Err(E) } } (&&&Magic::(std::marker::PhantomData)).magic_conversion(""); } } rstest-0.17.0/src/timeout.rs000064400000000000000000000132341046102023000140630ustar 00000000000000use std::{sync::mpsc, thread, time::Duration}; #[cfg(feature = "async-timeout")] use futures::{select, Future, FutureExt}; #[cfg(feature = "async-timeout")] use futures_timer::Delay; pub fn execute_with_timeout_sync T + Send + 'static>( code: F, timeout: Duration, ) -> T { let (sender, receiver) = mpsc::channel(); let thread = if let Some(name) = thread::current().name() { thread::Builder::new().name(name.to_string()) } else { thread::Builder::new() }; let handle = thread.spawn(move || sender.send(code())).unwrap(); match receiver.recv_timeout(timeout) { Ok(result) => { // Unwraps are safe because we got a result from the thread, which is not a `SendError`, // and there was no panic within the thread which caused a disconnect. handle.join().unwrap().unwrap(); result } Err(mpsc::RecvTimeoutError::Timeout) => panic!("Timeout {:?} expired", timeout), Err(mpsc::RecvTimeoutError::Disconnected) => match handle.join() { Err(any) => std::panic::resume_unwind(any), Ok(_) => unreachable!(), }, } } #[cfg(feature = "async-timeout")] pub async fn execute_with_timeout_async, F: FnOnce() -> Fut>( code: F, timeout: Duration, ) -> T { select! { () = async { Delay::new(timeout).await; }.fuse() => panic!("Timeout {:?} expired", timeout), out = code().fuse() => out, } } #[cfg(test)] mod tests { use super::*; #[cfg(feature = "async-timeout")] mod async_version { use super::*; use std::time::Duration; async fn delayed_sum(a: u32, b: u32, delay: Duration) -> u32 { async_std::task::sleep(delay).await; a + b } async fn test(delay: Duration) { let result = delayed_sum(2, 2, delay).await; assert_eq!(result, 4); } mod use_async_std_runtime { use super::*; #[async_std::test] #[should_panic] async fn should_fail() { execute_with_timeout_async( || test(Duration::from_millis(40)), Duration::from_millis(10), ) .await } #[async_std::test] async fn should_pass() { execute_with_timeout_async( || test(Duration::from_millis(10)), Duration::from_millis(40), ) .await } #[async_std::test] #[should_panic = "inner message"] async fn should_fail_for_panic_with_right_panic_message() { execute_with_timeout_async( || async { panic!("inner message"); }, Duration::from_millis(30), ) .await } #[async_std::test] async fn should_compile_also_with_no_copy_move() { struct S {} async fn test(_s: S) { assert!(true); } let s = S {}; execute_with_timeout_async(move || test(s), Duration::from_millis(20)).await } } mod use_tokio_runtime { use super::*; #[tokio::test] #[should_panic] async fn should_fail() { execute_with_timeout_async( || test(Duration::from_millis(40)), Duration::from_millis(10), ) .await } #[async_std::test] #[should_panic = "inner message"] async fn should_fail_for_panic_with_right_panic_message() { execute_with_timeout_async( || async { panic!("inner message"); }, Duration::from_millis(30), ) .await } #[tokio::test] async fn should_pass() { execute_with_timeout_async( || test(Duration::from_millis(10)), Duration::from_millis(40), ) .await } } } mod thread_version { use super::*; pub fn delayed_sum(a: u32, b: u32, delay: Duration) -> u32 { std::thread::sleep(delay); a + b } fn test(delay: Duration) { let result = delayed_sum(2, 2, delay); assert_eq!(result, 4); } #[test] fn should_pass() { execute_with_timeout_sync( || test(Duration::from_millis(30)), Duration::from_millis(70), ) } #[test] #[should_panic = "inner message"] fn should_fail_for_panic_with_right_panic_message() { execute_with_timeout_sync( || { panic!("inner message"); }, Duration::from_millis(30), ) } #[test] #[should_panic] fn should_fail() { execute_with_timeout_sync( || test(Duration::from_millis(70)), Duration::from_millis(30), ) } #[test] fn should_compile_also_with_no_copy_move() { struct S {} fn test(_s: S) { assert!(true); } let s = S {}; execute_with_timeout_sync(move || test(s), Duration::from_millis(20)) } } } rstest-0.17.0/tests/fixture/mod.rs000064400000000000000000000222711046102023000152160ustar 00000000000000use std::path::Path; pub use unindent::Unindent; use super::resources; use mytest::*; use rstest_test::{assert_in, assert_not_in, Project, Stringable, TestResults}; fn prj(res: &str) -> Project { let path = Path::new("fixture").join(res); crate::prj().set_code_file(resources(path)) } fn run_test(res: &str) -> (std::process::Output, String) { let prj = prj(res); ( prj.run_tests().unwrap(), prj.get_name().to_owned().to_string(), ) } mod should { use rstest_test::{assert_regex, CountMessageOccurrence}; use super::*; #[test] fn use_input_fixtures() { let (output, _) = run_test("simple_injection.rs"); TestResults::new().ok("success").fail("fail").assert(output); } #[test] fn create_a_struct_that_return_the_fixture() { let (output, _) = run_test("fixture_struct.rs"); TestResults::new() .ok("resolve_new") .ok("resolve_default") .ok("injected_new") .ok("injected_default") .assert(output); } #[test] fn be_accessible_from_other_module() { let (output, _) = run_test("from_other_module.rs"); TestResults::new().ok("struct_access").assert(output); } #[test] fn not_show_any_warning() { let (output, _) = run_test("no_warning.rs"); assert_not_in!(output.stderr.str(), "warning:"); } #[test] fn rename() { let (output, _) = run_test("rename.rs"); TestResults::new().ok("test").assert(output); } mod accept_and_return { use super::*; #[test] fn impl_traits() { let (output, _) = run_test("impl.rs"); TestResults::new() .ok("base_impl_return") .ok("nested_impl_return") .ok("nested_multiple_impl_return") .ok("base_impl_input") .ok("nested_impl_input") .ok("nested_multiple_impl_input") .assert(output); } #[test] fn dyn_traits() { let (output, _) = run_test("dyn.rs"); TestResults::new() .ok("test_dyn_box") .ok("test_dyn_ref") .ok("test_dyn_box_resolve") .ok("test_dyn_ref_resolve") .assert(output); } } #[rstest] #[case::base("async_fixture.rs")] #[case::use_global("await_complete_fixture.rs")] #[case::use_selective("await_partial_fixture.rs")] fn resolve_async_fixture(#[case] code: &str) { let prj = prj(code); prj.add_dependency("async-std", r#"{version="*", features=["attributes"]}"#); let output = prj.run_tests().unwrap(); TestResults::new() .ok("default_is_async") .ok("use_async_fixture") .ok("use_async_impl_output") .ok("use_async_nest_fixture_default") .ok("use_async_nest_fixture_injected") .ok("use_async_nest_fixture_with_default") .ok("use_two_args_mix_fixture") .ok("use_two_args_mix_fixture_inject_first") .ok("use_two_args_mix_fixture_inject_both") .assert(output); } #[test] fn resolve_fixture_generics_by_fixture_input() { let (output, _) = run_test("resolve.rs"); TestResults::new() .ok("test_u32") .ok("test_i32") .assert(output); } #[test] fn use_defined_return_type_if_any() { let (output, _) = run_test("defined_return_type.rs"); TestResults::new() .ok("resolve") .ok("resolve_partial") .ok("resolve_attrs") .ok("resolve_partial_attrs") .assert(output); } #[test] fn clean_up_default_from_unused_generics() { let (output, _) = run_test("clean_up_default_generics.rs"); TestResults::new() .ok("resolve") .ok("resolve_partial") .assert(output); } #[test] fn apply_partial_fixture() { let (output, _) = run_test("partial.rs"); TestResults::new() .ok("default") .ok("t_partial_1") .ok("t_partial_2") .ok("t_complete") .assert(output); } #[test] fn apply_partial_fixture_from_value_attribute() { let (output, _) = run_test("partial_in_attr.rs"); TestResults::new() .ok("default") .ok("t_partial_1") .ok("t_partial_2") .ok("t_complete") .assert(output); } #[rstest] #[case::compact_form("default.rs")] #[case::attrs_form("default_in_attrs.rs")] fn use_input_values_if_any(#[case] file: &str) { let (output, _) = run_test(file); TestResults::new() .ok("test_simple") .ok("test_simple_changed") .ok("test_double") .ok("test_double_changed") .ok("test_mixed") .assert(output); } #[test] fn convert_literal_string_for_default_values() { let (output, _) = run_test("default_conversion.rs"); assert_regex!( "Cannot parse 'error' to get [a-z:_0-9]*MyType", output.stdout.str() ); TestResults::new() .ok("test_base") .ok("test_byte_array") .ok("test_convert_custom") .fail("test_fail_conversion") .assert(output); } #[rstest] #[case("once.rs")] #[case::no_return("once_no_return.rs")] #[case::defined_type("once_defined_type.rs")] fn accept_once_attribute_and_call_fixture_just_once(#[case] fname: &str) { let project = prj(fname).with_nocapture(); let output = project.run_tests().unwrap(); // Just to see the errors if fixture doesn't compile assert_in!(output.stderr.str(), "Exec fixture() just once"); let occurences = output.stderr.str().count("Exec fixture() just once"); assert_eq!(1, occurences); } #[test] fn show_correct_errors() { let prj = prj("errors.rs"); let output = prj.run_tests().unwrap(); let name = prj.get_name(); assert_in!(output.stderr.str(), "error[E0433]: "); assert_in!( output.stderr.str(), format!( r#" --> {}/src/lib.rs:12:33 | 12 | fn error_cannot_resolve_fixture(no_fixture: u32) {{"#, name ) .unindent() ); assert_in!( output.stderr.str(), format!( r#" error[E0308]: mismatched types --> {}/src/lib.rs:8:18 | 8 | let a: u32 = ""; "#, name ) .unindent() ); assert_in!( output.stderr.str(), format!( " error[E0308]: mismatched types --> {}/src/lib.rs:16:29 ", name ) .unindent() ); assert_in!( output.stderr.str(), " 16 | fn error_fixture_wrong_type(fixture: String) { | ^^^^^^" .unindent() ); assert_in!( output.stderr.str(), format!( " error: Missed argument: 'not_a_fixture' should be a test function argument. --> {}/src/lib.rs:19:11 | 19 | #[fixture(not_a_fixture(24))] | ^^^^^^^^^^^^^ ", name ) .unindent() ); assert_in!( output.stderr.str(), format!( r#" error: Duplicate argument: 'f' is already defined. --> {}/src/lib.rs:33:23 | 33 | #[fixture(f("first"), f("second"))] | ^ "#, name ) .unindent() ); assert_in!( output.stderr.str(), format!( r#" error: Cannot apply #[once] to async fixture. --> {}/src/lib.rs:38:3 | 38 | #[once] | ^^^^ "#, name ) .unindent() ); assert_in!( output.stderr.str(), format!( r#" error: Cannot apply #[once] on generic fixture. --> {}/src/lib.rs:43:3 | 43 | #[once] | ^^^^ "#, name ) .unindent() ); assert_in!( output.stderr.str(), format!( r#" error: Cannot apply #[once] on generic fixture. --> {}/src/lib.rs:49:3 | 49 | #[once] | ^^^^ "#, name ) .unindent() ); } } rstest-0.17.0/tests/integration.rs000064400000000000000000000014311046102023000152670ustar 00000000000000use rstest_test::{sanitize_name, testname, Project}; /// Rstest integration tests mod rstest; /// Fixture's integration tests mod fixture; use lazy_static::lazy_static; use std::path::{Path, PathBuf}; use temp_testdir::TempDir; lazy_static! { static ref ROOT_DIR: TempDir = TempDir::default().permanent(); static ref ROOT_PROJECT: Project = Project::new(ROOT_DIR.as_ref()); } pub fn base_prj() -> Project { let prj_name = sanitize_name(testname()); ROOT_PROJECT.subproject(&prj_name) } pub fn prj() -> Project { let prj_name = sanitize_name(testname()); let prj = ROOT_PROJECT.subproject(&prj_name); prj.add_local_dependency("rstest"); prj } pub fn resources>(name: O) -> PathBuf { Path::new("tests").join("resources").join(name) } rstest-0.17.0/tests/resources/fixture/async_fixture.rs000064400000000000000000000034211046102023000213300ustar 00000000000000use std::io::prelude::*; use rstest::*; #[fixture] async fn async_u32() -> u32 { 42 } #[fixture] async fn nest_fixture(#[future] async_u32: u32) -> u32 { async_u32.await } #[fixture(fortytwo = async { 42 })] async fn nest_fixture_with_default(#[future] fortytwo: u32) -> u32 { fortytwo.await } #[rstest] async fn default_is_async() { assert_eq!(42, async_u32::default().await); } #[rstest] async fn use_async_nest_fixture_default(#[future] nest_fixture: u32) { assert_eq!(42, nest_fixture.await); } #[rstest(nest_fixture(async { 24 }))] async fn use_async_nest_fixture_injected(#[future] nest_fixture: u32) { assert_eq!(24, nest_fixture.await); } #[rstest] async fn use_async_nest_fixture_with_default(#[future] nest_fixture_with_default: u32) { assert_eq!(42, nest_fixture_with_default.await); } #[rstest] async fn use_async_fixture(#[future] async_u32: u32) { assert_eq!(42, async_u32.await); } #[fixture] async fn async_impl_output() -> impl Read { std::io::Cursor::new(vec![1, 2, 3, 4, 5]) } #[rstest] async fn use_async_impl_output(#[future] async_impl_output: T) { let reader = async_impl_output.await; } #[fixture(four = async { 4 }, two = 2)] async fn two_args_mix_fixture(#[future] four: u32, two: u32) -> u32 { four.await * 10 + two } #[rstest] async fn use_two_args_mix_fixture(#[future] two_args_mix_fixture: u32) { assert_eq!(42, two_args_mix_fixture.await); } #[rstest(two_args_mix_fixture(async { 5 }))] async fn use_two_args_mix_fixture_inject_first(#[future] two_args_mix_fixture: u32) { assert_eq!(52, two_args_mix_fixture.await); } #[rstest(two_args_mix_fixture(async { 3 }, 1))] async fn use_two_args_mix_fixture_inject_both(#[future] two_args_mix_fixture: u32) { assert_eq!(31, two_args_mix_fixture.await); }rstest-0.17.0/tests/resources/fixture/await_complete_fixture.rs000064400000000000000000000035231046102023000232130ustar 00000000000000use std::io::prelude::*; use rstest::*; #[fixture] async fn async_u32() -> u32 { 42 } #[fixture] #[awt] async fn nest_fixture(#[future] async_u32: u32) -> u32 { async_u32 } #[fixture] #[awt] async fn nest_fixture_with_default( #[future] #[default(async { 42 })] fortytwo: u32, ) -> u32 { fortytwo } #[rstest] async fn default_is_async() { assert_eq!(42, async_u32::default().await); } #[rstest] #[awt] async fn use_async_nest_fixture_default(#[future] nest_fixture: u32) { assert_eq!(42, nest_fixture); } #[rstest] #[awt] async fn use_async_nest_fixture_injected( #[future] #[with(async { 24 })] nest_fixture: u32, ) { assert_eq!(24, nest_fixture); } #[rstest] #[awt] async fn use_async_nest_fixture_with_default(#[future] nest_fixture_with_default: u32) { assert_eq!(42, nest_fixture_with_default); } #[rstest] #[awt] async fn use_async_fixture(#[future] async_u32: u32) { assert_eq!(42, async_u32); } #[fixture] async fn async_impl_output() -> impl Read { std::io::Cursor::new(vec![1, 2, 3, 4, 5]) } #[rstest] #[awt] async fn use_async_impl_output(#[future] async_impl_output: T) { let reader = async_impl_output; } #[fixture] #[awt] async fn two_args_mix_fixture( #[future] #[default(async { 4 })] four: u32, #[default(2)] two: u32, ) -> u32 { four * 10 + two } #[rstest] #[awt] async fn use_two_args_mix_fixture(#[future] two_args_mix_fixture: u32) { assert_eq!(42, two_args_mix_fixture); } #[rstest] #[awt] async fn use_two_args_mix_fixture_inject_first( #[future] #[with(async { 5 })] two_args_mix_fixture: u32, ) { assert_eq!(52, two_args_mix_fixture); } #[rstest] #[awt] async fn use_two_args_mix_fixture_inject_both( #[future] #[with(async { 3 }, 1)] two_args_mix_fixture: u32, ) { assert_eq!(31, two_args_mix_fixture); } rstest-0.17.0/tests/resources/fixture/await_partial_fixture.rs000064400000000000000000000034751046102023000230450ustar 00000000000000use std::io::prelude::*; use rstest::*; #[fixture] async fn async_u32() -> u32 { 42 } #[fixture] async fn nest_fixture(#[future(awt)] async_u32: u32) -> u32 { async_u32 } #[fixture] async fn nest_fixture_with_default( #[future(awt)] #[default(async { 42 })] fortytwo: u32, ) -> u32 { fortytwo } #[rstest] async fn default_is_async() { assert_eq!(42, async_u32::default().await); } #[rstest] async fn use_async_nest_fixture_default(#[future(awt)] nest_fixture: u32) { assert_eq!(42, nest_fixture); } #[rstest] async fn use_async_nest_fixture_injected( #[future(awt)] #[with(async { 24 })] nest_fixture: u32, ) { assert_eq!(24, nest_fixture); } #[rstest] async fn use_async_nest_fixture_with_default(#[future(awt)] nest_fixture_with_default: u32) { assert_eq!(42, nest_fixture_with_default); } #[rstest] async fn use_async_fixture(#[future(awt)] async_u32: u32) { assert_eq!(42, async_u32); } #[fixture] async fn async_impl_output() -> impl Read { std::io::Cursor::new(vec![1, 2, 3, 4, 5]) } #[rstest] async fn use_async_impl_output(#[future(awt)] async_impl_output: T) { let reader = async_impl_output; } #[fixture] async fn two_args_mix_fixture( #[future(awt)] #[default(async { 4 })] four: u32, #[default(2)] two: u32, ) -> u32 { four * 10 + two } #[rstest] async fn use_two_args_mix_fixture(#[future(awt)] two_args_mix_fixture: u32) { assert_eq!(42, two_args_mix_fixture); } #[rstest] async fn use_two_args_mix_fixture_inject_first( #[future(awt)] #[with(async { 5 })] two_args_mix_fixture: u32, ) { assert_eq!(52, two_args_mix_fixture); } #[rstest] async fn use_two_args_mix_fixture_inject_both( #[future(awt)] #[with(async { 3 }, 1)] two_args_mix_fixture: u32, ) { assert_eq!(31, two_args_mix_fixture); } rstest-0.17.0/tests/resources/fixture/clean_up_default_generics.rs000064400000000000000000000006371046102023000236240ustar 00000000000000use rstest::*; #[fixture] fn s() -> &'static str { "42" } #[fixture] fn fx(s: S) -> usize { s.to_string().len() } #[fixture] fn sum() -> usize { 42 } #[fixture] fn fx_double(sum: usize, s: S) -> usize { s.to_string().len() + sum } #[test] fn resolve() { assert_eq!(2, fx::default()) } #[test] fn resolve_partial() { assert_eq!(12, fx_double::partial_1(10)) } rstest-0.17.0/tests/resources/fixture/default.rs000064400000000000000000000013641046102023000200750ustar 00000000000000use rstest::{fixture, rstest}; #[fixture(value = 42)] pub fn simple(value: u32) -> u32 { value } #[fixture(value = 21, mult = 2)] pub fn double(value: u32, mult: u32) -> u32 { value * mult } #[fixture] pub fn middle() -> u32 { 2 } #[fixture(value = 21, mult = 4)] pub fn mixed(value: u32, middle: u32, mult: u32) -> u32 { value * mult / middle } #[rstest] fn test_simple(simple: u32) { assert_eq!(simple, 42) } #[rstest(simple(21))] fn test_simple_changed(simple: u32) { assert_eq!(simple, 21) } #[rstest] fn test_double(double: u32) { assert_eq!(double, 42) } #[rstest(double(20, 3))] fn test_double_changed(double: u32) { assert_eq!(double, 60) } #[rstest] fn test_mixed(mixed: u32) { assert_eq!(mixed, 42) } rstest-0.17.0/tests/resources/fixture/default_conversion.rs000064400000000000000000000017411046102023000223410ustar 00000000000000use rstest::{fixture, rstest}; use std::net::{Ipv4Addr, SocketAddr}; struct MyType(String); struct E; impl core::str::FromStr for MyType { type Err = E; fn from_str(s: &str) -> Result { match s { "error" => Err(E), inner => Ok(MyType(inner.to_owned())), } } } #[fixture] fn base(#[default("1.2.3.4")] ip: Ipv4Addr, #[default(r#"8080"#)] port: u16) -> SocketAddr { SocketAddr::new(ip.into(), port) } #[fixture] fn fail(#[default("error")] t: MyType) -> MyType { t } #[fixture] fn valid(#[default("some")] t: MyType) -> MyType { t } #[rstest] fn test_base(base: SocketAddr) { assert_eq!(base, "1.2.3.4:8080".parse().unwrap()); } #[fixture] fn byte_array(#[default(b"1234")] some: &[u8]) -> usize { some.len() } #[rstest] fn test_byte_array(byte_array: usize) { assert_eq!(4, byte_array); } #[rstest] fn test_convert_custom(valid: MyType) {} #[rstest] fn test_fail_conversion(fail: MyType) {} rstest-0.17.0/tests/resources/fixture/default_in_attrs.rs000064400000000000000000000014211046102023000217720ustar 00000000000000use rstest::{fixture, rstest}; #[fixture] pub fn simple(#[default(42)] value: u32) -> u32 { value } #[fixture] pub fn double(#[default(20 + 1)] value: u32, #[default(1 + 1)] mult: u32) -> u32 { value * mult } #[fixture] pub fn middle() -> u32 { 2 } #[fixture] pub fn mixed(#[default(21)] value: u32, middle: u32, #[default(2 + 2)] mult: u32) -> u32 { value * mult / middle } #[rstest] fn test_simple(simple: u32) { assert_eq!(simple, 42) } #[rstest(simple(21))] fn test_simple_changed(simple: u32) { assert_eq!(simple, 21) } #[rstest] fn test_double(double: u32) { assert_eq!(double, 42) } #[rstest(double(20, 3))] fn test_double_changed(double: u32) { assert_eq!(double, 60) } #[rstest] fn test_mixed(mixed: u32) { assert_eq!(mixed, 42) } rstest-0.17.0/tests/resources/fixture/defined_return_type.rs000064400000000000000000000015371046102023000225110ustar 00000000000000use rstest::*; #[fixture] pub fn i() -> u32 { 42 } #[fixture] pub fn j() -> i32 { -42 } #[fixture(::default>::partial_1>)] pub fn fx(i: I, j: J) -> impl Iterator { std::iter::once((i, j)) } #[test] fn resolve() { assert_eq!((42, -42), fx::default().next().unwrap()) } #[test] fn resolve_partial() { assert_eq!((42.0, -42), fx::partial_1(42.0).next().unwrap()) } #[fixture] #[default(impl Iterator)] #[partial_1(impl Iterator)] pub fn fx_attrs(i: I, j: J) -> impl Iterator { std::iter::once((i, j)) } #[test] fn resolve_attrs() { assert_eq!((42, -42), fx_attrs::default().next().unwrap()) } #[test] fn resolve_partial_attrs() { assert_eq!((42.0, -42), fx_attrs::partial_1(42.0).next().unwrap()) }rstest-0.17.0/tests/resources/fixture/dyn.rs000064400000000000000000000014251046102023000172410ustar 00000000000000use rstest::*; #[fixture] fn dyn_box() -> Box> { Box::new(std::iter::once(42)) } #[fixture] fn dyn_ref() -> &'static dyn ToString { &42 } #[fixture] fn dyn_box_resolve(mut dyn_box: Box>) -> i32 { dyn_box.next().unwrap() } #[fixture] fn dyn_ref_resolve(dyn_ref: &dyn ToString) -> String { dyn_ref.to_string() } #[rstest] fn test_dyn_box(mut dyn_box: Box>) { assert_eq!(42, dyn_box.next().unwrap()) } #[rstest] fn test_dyn_ref(dyn_ref: &dyn ToString) { assert_eq!("42", dyn_ref.to_string()) } #[rstest] fn test_dyn_box_resolve(dyn_box_resolve: i32) { assert_eq!(42, dyn_box_resolve) } #[rstest] fn test_dyn_ref_resolve(dyn_ref_resolve: String) { assert_eq!("42", dyn_ref_resolve) } rstest-0.17.0/tests/resources/fixture/errors.rs000064400000000000000000000014441046102023000177640ustar 00000000000000use rstest::*; #[fixture] pub fn fixture() -> u32 { 42 } #[fixture] fn error_inner(fixture: u32) { let a: u32 = ""; } #[fixture] fn error_cannot_resolve_fixture(no_fixture: u32) { } #[fixture] fn error_fixture_wrong_type(fixture: String) { } #[fixture(not_a_fixture(24))] fn error_inject_an_invalid_fixture(fixture: String) { } #[fixture] fn name() -> &'static str { "name" } #[fixture] fn f(name: &str) -> String { name.to_owned() } #[fixture(f("first"), f("second"))] fn error_inject_a_fixture_more_than_once(f: String) { } #[fixture] #[once] async fn error_async_once_fixture() { } #[fixture] #[once] fn error_generics_once_fixture() -> T { 42 } #[fixture] #[once] fn error_generics_once_fixture() -> impl Iterator { std::iter::once(42) } rstest-0.17.0/tests/resources/fixture/fixture_struct.rs000064400000000000000000000012641046102023000215420ustar 00000000000000use rstest::fixture; trait Mult { fn mult(&self, n: u32) -> u32; } struct M(u32); impl Mult for M { fn mult(&self, n: u32) -> u32 { n * self.0 } } #[fixture] fn my_fixture() -> u32 { 42 } #[fixture] fn multiplier() -> M { M(2) } #[fixture] fn my_fixture_injected(my_fixture: u32, multiplier: impl Mult) -> u32 { multiplier.mult(my_fixture) } #[test] fn resolve_new() { assert_eq!(42, my_fixture::get()); } #[test] fn resolve_default() { assert_eq!(42, my_fixture::default()); } #[test] fn injected_new() { assert_eq!(63, my_fixture_injected::get(21, M(3))); } #[test] fn injected_default() { assert_eq!(84, my_fixture_injected::default()); } rstest-0.17.0/tests/resources/fixture/from_other_module.rs000064400000000000000000000003101046102023000221500ustar 00000000000000 mod my_mod { use rstest::{fixture}; #[fixture] pub fn mod_fixture() -> u32 { 42 } } use my_mod::mod_fixture; #[test] fn struct_access() { assert_eq!(42, mod_fixture::default()); } rstest-0.17.0/tests/resources/fixture/impl.rs000064400000000000000000000034311046102023000174070ustar 00000000000000use rstest::*; #[fixture] fn fx_base_impl_return() -> impl Iterator { std::iter::once(42) } #[fixture] fn fx_base_impl_input(mut fx_base_impl_return: impl Iterator) -> u32 { fx_base_impl_return.next().unwrap() } #[rstest] fn base_impl_return(mut fx_base_impl_return: impl Iterator) { assert_eq!(42, fx_base_impl_return.next().unwrap()); } #[rstest] fn base_impl_input(mut fx_base_impl_input: u32) { assert_eq!(42, fx_base_impl_input); } #[fixture] fn fx_nested_impl_return() -> impl Iterator { std::iter::once(42) } #[fixture] fn fx_nested_impl_input(mut fx_nested_impl_return: impl Iterator) -> String { fx_nested_impl_return.next().unwrap().to_string() } #[rstest] fn nested_impl_return(mut fx_nested_impl_return: impl Iterator) { assert_eq!("42", fx_nested_impl_return.next().unwrap().to_string()); } #[rstest] fn nested_impl_input(mut fx_nested_impl_input: String) { assert_eq!("42", &fx_nested_impl_input); } #[fixture] fn fx_nested_multiple_impl_return() -> (impl Iterator, impl ToString) { (std::iter::once(42), 42i32) } #[fixture] fn fx_nested_multiple_impl_input(mut fx_nested_multiple_impl_return: (impl Iterator, impl ToString)) -> bool { fx_nested_multiple_impl_return.0.next().unwrap().to_string() == fx_nested_multiple_impl_return.1.to_string() } #[rstest] fn nested_multiple_impl_return(mut fx_nested_multiple_impl_return: (impl Iterator, impl ToString)) { assert_eq!(fx_nested_multiple_impl_return.0.next().unwrap().to_string(), fx_nested_multiple_impl_return.1.to_string()); } #[rstest] fn nested_multiple_impl_input(fx_nested_multiple_impl_input: bool) { assert!(fx_nested_multiple_impl_input); } rstest-0.17.0/tests/resources/fixture/no_warning.rs000064400000000000000000000003051046102023000206040ustar 00000000000000use rstest::*; #[fixture] fn val() -> i32 { 21 } #[fixture] fn fortytwo(mut val: i32) -> i32 { val *= 2; val } #[rstest] fn the_test(fortytwo: i32) { assert_eq!(fortytwo, 42); } rstest-0.17.0/tests/resources/fixture/once.rs000064400000000000000000000005371046102023000173760ustar 00000000000000use rstest::{fixture, rstest}; #[fixture] #[once] fn once_fixture() -> u32 { eprintln!("Exec fixture() just once"); 42 } #[rstest] fn base(once_fixture: &u32) { assert_eq!(&42, once_fixture); } #[rstest] #[case(2)] #[case(3)] #[case(7)] fn cases(once_fixture: &u32, #[case] divisor: u32) { assert_eq!(0, *once_fixture % divisor); } rstest-0.17.0/tests/resources/fixture/once_defined_type.rs000064400000000000000000000011641046102023000221120ustar 00000000000000use rstest::{fixture, rstest}; #[fixture] #[default(u32)] #[partial_1(u32)] #[once] fn once_fixture(#[default(())] a: (), #[default(())] b: ()) -> u32 { eprintln!("Exec fixture() just once"); 42 } #[rstest] fn base(once_fixture: &u32) { assert_eq!(&42, once_fixture); } #[rstest] fn base_partial(#[with(())] once_fixture: &u32) { assert_eq!(&42, once_fixture); } #[rstest] fn base_complete(#[with((), ())] once_fixture: &u32) { assert_eq!(&42, once_fixture); } #[rstest] #[case(2)] #[case(3)] #[case(7)] fn cases(once_fixture: &u32, #[case] divisor: u32) { assert_eq!(0, *once_fixture % divisor); } rstest-0.17.0/tests/resources/fixture/once_no_return.rs000064400000000000000000000003751046102023000214710ustar 00000000000000use rstest::*; #[fixture] #[once] fn once_fixture() { eprintln!("Exec fixture() just once"); } #[rstest] fn base(_once_fixture: ()) { assert!(true); } #[rstest] #[case()] #[case()] #[case()] fn cases(_once_fixture: ()) { assert!(true); } rstest-0.17.0/tests/resources/fixture/partial.rs000064400000000000000000000013071046102023000201020ustar 00000000000000use rstest::*; #[fixture] fn f1() -> u32 { 0 } #[fixture] fn f2() -> u32 { 0 } #[fixture] fn f3() -> u32 { 0 } #[fixture] fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { f1 + 10 * f2 + 100 * f3 } #[fixture(fixture(7))] fn partial_1(fixture: u32) -> u32 { fixture } #[fixture(fixture(2, 4))] fn partial_2(fixture: u32) -> u32 { fixture } #[fixture(fixture(2, 4, 5))] fn complete(fixture: u32) -> u32 { fixture } #[rstest] fn default(fixture: u32) { assert_eq!(fixture, 0); } #[rstest] fn t_partial_1(partial_1: u32) { assert_eq!(partial_1, 7); } #[rstest] fn t_partial_2(partial_2: u32) { assert_eq!(partial_2, 42); } #[rstest] fn t_complete(complete: u32) { assert_eq!(complete, 542); } rstest-0.17.0/tests/resources/fixture/partial_in_attr.rs000064400000000000000000000013401046102023000216170ustar 00000000000000use rstest::*; #[fixture] fn f1() -> u32 { 0 } #[fixture] fn f2() -> u32 { 0 } #[fixture] fn f3() -> u32 { 0 } #[fixture] fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { f1 + 10 * f2 + 100 * f3 } #[fixture] fn partial_1(#[with(7)] fixture: u32) -> u32 { fixture } #[fixture] fn partial_2(#[with(2, 4)] fixture: u32) -> u32 { fixture } #[fixture] fn complete(#[with(2, 4, 5)] fixture: u32) -> u32 { fixture } #[rstest] fn default(fixture: u32) { assert_eq!(fixture, 0); } #[rstest] fn t_partial_1(partial_1: u32) { assert_eq!(partial_1, 7); } #[rstest] fn t_partial_2(partial_2: u32) { assert_eq!(partial_2, 42); } #[rstest] fn t_complete(complete: u32) { assert_eq!(complete, 542); } rstest-0.17.0/tests/resources/fixture/rename.rs000064400000000000000000000012701046102023000177140ustar 00000000000000use rstest::*; #[fixture] fn very_long_and_boring_name(#[default(42)] inject: u32) -> u32 { inject } #[fixture(very_long_and_boring_name as foo)] fn compact(foo: u32) -> u32 { foo } #[fixture(very_long_and_boring_name(21) as foo)] fn compact_injected(foo: u32) -> u32 { foo } #[fixture] fn attribute(#[from(very_long_and_boring_name)] foo: u32) -> u32 { foo } #[fixture] fn attribute_injected( #[from(very_long_and_boring_name)] #[with(21)] foo: u32, ) -> u32 { foo } #[rstest] fn test(compact: u32, attribute: u32, compact_injected: u32, attribute_injected: u32) { assert_eq!(compact, attribute); assert_eq!(compact_injected, attribute_injected); } rstest-0.17.0/tests/resources/fixture/resolve.rs000064400000000000000000000007251046102023000201300ustar 00000000000000use rstest::{rstest, fixture}; pub trait Tr { fn get() -> Self; } impl Tr for i32 { fn get() -> Self { 42 } } impl Tr for u32 { fn get() -> Self { 42 } } #[fixture] pub fn f() -> T { T::get() } #[fixture] pub fn fu32(f: u32) -> u32 { f } #[fixture] pub fn fi32(f: i32) -> i32 { f } #[rstest] fn test_u32(fu32: u32) { assert_eq!(fu32, 42) } #[rstest] fn test_i32(fi32: i32) { assert_eq!(fi32, 42) } rstest-0.17.0/tests/resources/fixture/simple_injection.rs000064400000000000000000000004121046102023000217750ustar 00000000000000use rstest::{rstest, fixture}; #[fixture] fn root() -> u32 { 21 } #[fixture] fn injection(root: u32) -> u32 { 2 * root } #[rstest] fn success(injection: u32) { assert_eq!(42, injection); } #[rstest] fn fail(injection: u32) { assert_eq!(41, injection); } rstest-0.17.0/tests/resources/rstest/cases/args_with_no_cases.rs000064400000000000000000000001641046102023000232430ustar 00000000000000use rstest::rstest; #[rstest(one, two, three)] fn should_show_error_for_no_case(one: u32, two: u32, three: u32) {} rstest-0.17.0/tests/resources/rstest/cases/async.rs000064400000000000000000000007451046102023000205240ustar 00000000000000use rstest::*; #[rstest] #[case::pass(42, async { 42 })] #[case::fail(42, async { 41 })] #[should_panic] #[case::pass_panic(42, async { 41 })] #[should_panic] #[case::fail_panic(42, async { 42 })] async fn my_async_test(#[case] expected: u32, #[case] #[future] value: u32) { assert_eq!(expected, value.await); } #[rstest] #[case::pass(42, async { 42 })] async fn my_async_test_revert(#[case] expected: u32, #[future] #[case] value: u32) { assert_eq!(expected, value.await); }rstest-0.17.0/tests/resources/rstest/cases/async_awt.rs000064400000000000000000000010121046102023000213630ustar 00000000000000use rstest::*; #[rstest] #[case::pass(42, async { 42 })] #[case::fail(42, async { 41 })] #[should_panic] #[case::pass_panic(42, async { 41 })] #[should_panic] #[case::fail_panic(42, async { 42 })] async fn my_async_test( #[case] expected: u32, #[case] #[future(awt)] value: u32, ) { assert_eq!(expected, value); } #[rstest] #[case::pass(42, async { 42 })] async fn my_async_test_revert( #[case] expected: u32, #[future(awt)] #[case] value: u32, ) { assert_eq!(expected, value); } rstest-0.17.0/tests/resources/rstest/cases/async_awt_global.rs000064400000000000000000000010161046102023000227070ustar 00000000000000use rstest::*; #[rstest] #[case::pass(42, async { 42 })] #[case::fail(42, async { 41 })] #[should_panic] #[case::pass_panic(42, async { 41 })] #[should_panic] #[case::fail_panic(42, async { 42 })] #[awt] async fn my_async_test( #[case] expected: u32, #[case] #[future] value: u32, ) { assert_eq!(expected, value); } #[rstest] #[case::pass(42, async { 42 })] #[awt] async fn my_async_test_revert( #[case] expected: u32, #[future] #[case] value: u32, ) { assert_eq!(expected, value); } rstest-0.17.0/tests/resources/rstest/cases/case_attributes.rs000064400000000000000000000010531046102023000225610ustar 00000000000000use rstest::rstest; #[rstest( val, case::no_panic(0), #[should_panic] case::panic(2), #[should_panic(expected="expected")] case::panic_with_message(3), case::no_panic_but_fail(1), #[should_panic] case::panic_but_fail(0), #[should_panic(expected="other")] case::panic_with_wrong_message(3), )] fn attribute_per_case(val: i32) { match val { 0 => assert!(true), 1 => assert!(false), 2 => panic!("No catch"), 3 => panic!("expected"), _ => panic!("Not defined"), } } rstest-0.17.0/tests/resources/rstest/cases/case_with_wrong_args.rs000064400000000000000000000003461046102023000236020ustar 00000000000000use rstest::rstest; #[cfg(test)] #[rstest(a, b, case(42), case(1, 2), case(43))] fn error_less_arguments(a: u32, b: u32) {} #[cfg(test)] #[rstest(a, case(42, 43), case(12), case(24, 34))] fn error_too_much_arguments(a: u32) {} rstest-0.17.0/tests/resources/rstest/cases/description.rs000064400000000000000000000003151046102023000217230ustar 00000000000000use rstest::rstest; #[rstest( expected, case::user_test_description(true), case(true), case::user_test_description_fail(false) )] fn description(expected: bool) { assert!(expected); } rstest-0.17.0/tests/resources/rstest/cases/dump_just_one_case.rs000064400000000000000000000003221046102023000232440ustar 00000000000000use rstest::*; #[rstest] #[case::first_no_dump("Please don't trace me")] #[trace] #[case::dump_me("Trace it!")] #[case::last_no_dump("Please don't trace me")] fn cases(#[case] s: &str) { assert!(false); } rstest-0.17.0/tests/resources/rstest/cases/inject.rs000064400000000000000000000010141046102023000206510ustar 00000000000000use rstest::*; use actix_rt; use std::future::Future; #[rstest(expected, value, case::pass(42, 42), #[should_panic] case::panic(41, 42), case::fail(1, 42) )] #[test] fn sync(expected: u32, value: u32) { assert_eq!(expected, value); } #[rstest(expected, value, case::pass(42, async { 42 }), #[should_panic] case::panic(41, async { 42 }), case::fail(1, async { 42 }) )] #[actix_rt::test] async fn fn_async(expected: u32, value: impl Future) { assert_eq!(expected, value.await); } rstest-0.17.0/tests/resources/rstest/cases/missed_argument.rs000064400000000000000000000001411046102023000225630ustar 00000000000000use rstest::rstest; #[cfg(test)] #[rstest(f, case(42), case(24))] fn error_param_not_exist() {} rstest-0.17.0/tests/resources/rstest/cases/missed_some_arguments.rs000064400000000000000000000001611046102023000237730ustar 00000000000000use rstest::rstest; #[cfg(test)] #[rstest(a,b,c, case(1,2,3), case(3,2,1))] fn error_param_not_exist(b: u32) {} rstest-0.17.0/tests/resources/rstest/cases/partial.rs000064400000000000000000000022321046102023000210340ustar 00000000000000use rstest::*; #[fixture] fn f1() -> u32 { 0 } #[fixture] fn f2() -> u32 { 0 } #[fixture] fn f3() -> u32 { 0 } #[fixture] fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { f1 + 10 * f2 + 100 * f3 } #[rstest(expected, case(0), case(1000))] fn default(fixture: u32, expected: u32) { assert_eq!(fixture, expected); } #[rstest(fixture(7), expected, case(7), case(1000))] fn partial_1(fixture: u32, expected: u32) { assert_eq!(fixture, expected); } #[rstest(expected, case(7), case(1000))] fn partial_attr_1(#[with(7)] fixture: u32, expected: u32) { assert_eq!(fixture, expected); } #[rstest(fixture(2, 4), expected, case(42), case(1000))] fn partial_2(fixture: u32, expected: u32) { assert_eq!(fixture, expected); } #[rstest(expected, case(42), case(1000))] fn partial_attr_2(#[with(2, 4)] fixture: u32, expected: u32) { assert_eq!(fixture, expected); } #[rstest(fixture(2, 4, 5), expected, case(542), case(1000))] fn complete(fixture: u32, expected: u32) { assert_eq!(fixture, expected); } #[rstest(expected, case(542), case(1000))] fn complete_attr(#[with(2, 4, 5)] fixture: u32, expected: u32) { assert_eq!(fixture, expected); } rstest-0.17.0/tests/resources/rstest/cases/simple.rs000064400000000000000000000002671046102023000206770ustar 00000000000000use rstest::rstest; #[rstest( expected, input, case(4, "ciao"), case(3, "Foo") )] fn strlen_test(expected: usize, input: &str) { assert_eq!(expected, input.len()); } rstest-0.17.0/tests/resources/rstest/cases/use_attr.rs000064400000000000000000000014441046102023000212320ustar 00000000000000use rstest::rstest; #[rstest] #[case::ciao(4, "ciao")] #[should_panic] #[case::panic(42, "Foo")] #[case::foo(3, "Foo")] fn all(#[case] expected: usize, #[case] input: &str) { assert_eq!(expected, input.len()); } #[rstest(expected, input)] #[case::ciao(4, "ciao")] #[case::foo(3, "Foo")] #[should_panic] #[case::panic(42, "Foo")] fn just_cases(expected: usize, input: &str) { assert_eq!(expected, input.len()); } #[rstest( case::ciao(4, "ciao"), case::foo(3, "Foo"), #[should_panic] case::panic(42, "Foo"), )] fn just_args(#[case] expected: usize, #[case] input: &str) { assert_eq!(expected, input.len()); } #[rstest] #[case(0, "ciao")] #[case(0, "Foo")] #[should_panic] fn all_panic(#[case] expected: usize, #[case] input: &str) { assert_eq!(expected, input.len()); } rstest-0.17.0/tests/resources/rstest/convert_string_literal.rs000064400000000000000000000034131046102023000230660ustar 00000000000000use rstest::*; use std::net::SocketAddr; #[rstest] #[case(true, "1.2.3.4:42")] #[case(true, r#"4.3.2.1:24"#)] #[case(false, "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443")] #[case(false, r#"[2aa1:db8:85a3:8af:1319:8a2e:375:4873]:344"#)] #[case(false, "this.is.not.a.socket.address")] #[case(false, r#"this.is.not.a.socket.address"#)] fn cases(#[case] expected: bool, #[case] addr: SocketAddr) { assert_eq!(expected, addr.is_ipv4()); } #[rstest] fn values( #[values( "1.2.3.4:42", r#"4.3.2.1:24"#, "this.is.not.a.socket.address", r#"this.is.not.a.socket.address"# )] addr: SocketAddr, ) { assert!(addr.is_ipv4()) } #[rstest] #[case(b"12345")] fn not_convert_byte_array(#[case] cases: &[u8], #[values(b"abc")] values: &[u8]) { assert_eq!(5, cases.len()); assert_eq!(3, values.len()); } trait MyTrait { fn my_trait(&self) -> u32 { 42 } } impl MyTrait for &str {} #[rstest] #[case("impl", "nothing")] fn not_convert_impl(#[case] that_impl: impl MyTrait, #[case] s: &str) { assert_eq!(42, that_impl.my_trait()); assert_eq!(42, s.my_trait()); } #[rstest] #[case("1.2.3.4", "1.2.3.4:42")] #[case("1.2.3.4".to_owned(), "1.2.3.4:42")] fn not_convert_generics>(#[case] ip: S, #[case] addr: SocketAddr) { assert_eq!(addr.ip().to_string(), ip.as_ref()); } struct MyType(String); struct E; impl core::str::FromStr for MyType { type Err = E; fn from_str(s: &str) -> Result { match s { "error" => Err(E), inner => Ok(MyType(inner.to_owned())), } } } #[rstest] #[case("hello", "hello")] #[case("doesn't mater", "error")] fn convert_without_debug(#[case] expected: &str, #[case] converted: MyType) { assert_eq!(expected, converted.0); } rstest-0.17.0/tests/resources/rstest/dump_debug.rs000064400000000000000000000022431046102023000204170ustar 00000000000000use rstest::*; #[derive(Debug)] struct A {} #[fixture] fn fu32() -> u32 { 42 } #[fixture] fn fstring() -> String { "A String".to_string() } #[fixture] fn ftuple() -> (A, String, i32) { (A {}, "A String".to_string(), -12) } #[rstest] #[trace] fn single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { assert!(false); } #[rstest] fn no_trace_single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { assert!(false); } #[rstest] #[case(42, "str", ("ss", -12))] #[case(24, "trs", ("tt", -24))] #[trace] fn cases_fail(#[case] u: u32, #[case] s: &str, #[case] t: (&str, i32)) { assert!(false); } #[rstest] #[case(42, "str", ("ss", -12))] #[case(24, "trs", ("tt", -24))] fn no_trace_cases_fail(#[case] u: u32, #[case] s: &str, #[case] t: (&str, i32)) { assert!(false); } #[rstest] #[trace] fn matrix_fail( #[values(1, 3)] u: u32, #[values("rst", "srt")] s: &str, #[values(("SS", -12), ("TT", -24))] t: (&str, i32), ) { assert!(false); } #[rstest] fn no_trace_matrix_fail( #[values(1, 3)] u: u32, #[values("rst", "srt")] s: &str, #[values(("SS", -12), ("TT", -24))] t: (&str, i32), ) { assert!(false); } rstest-0.17.0/tests/resources/rstest/dump_debug_compact.rs000064400000000000000000000022011046102023000221170ustar 00000000000000use rstest::*; #[derive(Debug)] struct A {} #[fixture] fn fu32() -> u32 { 42 } #[fixture] fn fstring() -> String { "A String".to_string() } #[fixture] fn ftuple() -> (A, String, i32) { (A {}, "A String".to_string(), -12) } #[rstest(::trace)] fn single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { assert!(false); } #[rstest] fn no_trace_single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { assert!(false); } #[rstest(u, s, t, case(42, "str", ("ss", -12)), case(24, "trs", ("tt", -24)) ::trace )] fn cases_fail(u: u32, s: &str, t: (&str, i32)) { assert!(false); } #[rstest(u, s, t, case(42, "str", ("ss", -12)), case(24, "trs", ("tt", -24)) )] fn no_trace_cases_fail(u: u32, s: &str, t: (&str, i32)) { assert!(false); } #[rstest( u => [1, 2], s => ["rst", "srt"], t => [("SS", -12), ("TT", -24)] ::trace )] fn matrix_fail(u: u32, s: &str, t: (&str, i32)) { assert!(false); } #[rstest( u => [1, 2], s => ["rst", "srt"], t => [("SS", -12), ("TT", -24)] )] fn no_trace_matrix_fail(u: u32, s: &str, t: (&str, i32)) { assert!(false); } rstest-0.17.0/tests/resources/rstest/dump_exclude_some_inputs.rs000064400000000000000000000012241046102023000234050ustar 00000000000000use rstest::*; struct A; struct B; #[derive(Debug)] struct D; #[fixture] fn fu32() -> u32 { 42 } #[fixture] fn fb() -> B { B {} } #[fixture] fn fd() -> D { D {} } #[fixture] fn fa() -> A { A {} } #[rstest] #[trace] fn simple(fu32: u32, #[notrace] fa: A, #[notrace] fb: B, fd: D) { assert!(false); } #[rstest] #[trace] #[case(A{}, B{}, D{})] fn cases(fu32: u32, #[case] #[notrace] a: A, #[case] #[notrace] b: B, #[case] d: D) { assert!(false); } #[rstest] #[trace] fn matrix( fu32: u32, #[notrace] #[values(A{})] a: A, #[notrace] #[values(B{})] b: B, #[values(D{}) ] dd: D, ) { assert!(false); } rstest-0.17.0/tests/resources/rstest/dump_exclude_some_inputs_compact.rs000064400000000000000000000011141046102023000251110ustar 00000000000000use rstest::*; struct A; struct B; #[derive(Debug)] struct D; #[fixture] fn fu32() -> u32 { 42 } #[fixture] fn fb() -> B { B {} } #[fixture] fn fd() -> D { D {} } #[fixture] fn fa() -> A { A {} } #[rstest( ::trace::notrace(fa,fb)) ] fn simple(fu32: u32, fa: A, fb: B, fd: D) { assert!(false); } #[rstest(a,b,d, case(A{}, B{}, D{}) ::trace::notrace(a,b)) ] fn cases(fu32: u32, a: A, b: B, d: D) { assert!(false); } #[rstest( a => [A{}], b => [B{}], dd => [D{}], ::trace::notrace(a,b)) ] fn matrix(fu32: u32, a: A, b: B, dd: D) { assert!(false); } rstest-0.17.0/tests/resources/rstest/dump_not_debug.rs000064400000000000000000000004171046102023000213000ustar 00000000000000struct S; #[rustfmt::skip] mod _skip_format { use rstest::*; use super::*; #[fixture] fn fixture() -> S { S {} } #[rstest] #[trace] fn single(fixture: S) {} #[rstest(s)] #[trace] #[case(S{})] fn cases(s: S) {} #[rstest( s => [S{}])] #[trace] fn matrix(s: S) {} } rstest-0.17.0/tests/resources/rstest/dump_not_debug_compact.rs000064400000000000000000000004341046102023000230050ustar 00000000000000struct S; #[rustfmt::skip] mod _skip_format { use rstest::*; use super::*; #[fixture] fn fixture() -> S { S {} } #[rstest( ::trace)] fn single(fixture: S) {} #[rstest(s, case(S{}) ::trace)] fn cases(s: S) {} #[rstest( s => [S{}] ::trace)] fn matrix(s: S) {} } rstest-0.17.0/tests/resources/rstest/errors.rs000064400000000000000000000046621046102023000176270ustar 00000000000000use rstest::*; #[fixture] pub fn fixture() -> u32 { 42 } #[rstest(f, case(42))] fn error_inner(f: i32) { let a: u32 = ""; } #[rstest(f, case(42))] fn error_cannot_resolve_fixture(no_fixture: u32, f: u32) {} #[rstest(f, case(42))] fn error_fixture_wrong_type(fixture: String, f: u32) {} #[rstest(f, case(42))] fn error_case_wrong_type(f: &str) {} #[rstest(condition, case(vec![1,2,3].contains(2))) ] fn error_in_arbitrary_rust_code_cases(condition: bool) { assert!(condition) } #[rstest(f, case(42), not_a_fixture(24))] fn error_inject_an_invalid_fixture(f: u32) {} #[fixture] fn n() -> u32 { 24 } #[fixture] fn f(n: u32) -> u32 { 2 * n } #[rstest(f, f(42), case(12))] fn error_inject_a_fixture_that_is_already_a_case(f: u32) {} #[rstest(f(42), f, case(12))] fn error_define_case_that_is_already_an_injected_fixture(f: u32) {} #[rstest(v, f(42), f(42), case(12))] fn error_inject_a_fixture_more_than_once(v: u32, f: u32) {} #[rstest(f => [42])] fn error_matrix_wrong_type(f: &str) {} #[rstest(condition => [vec![1,2,3].contains(2)] )] fn error_arbitrary_rust_code_matrix(condition: bool) { assert!(condition) } #[rstest(empty => [])] fn error_empty_list(empty: &str) {} #[rstest(not_exist_1 => [42], not_exist_2 => [42])] fn error_no_match_args() {} #[rstest(f => [41, 42], f(42))] fn error_inject_a_fixture_that_is_already_a_value_list(f: u32) {} #[rstest(f(42), f => [41, 42])] fn error_define_a_value_list_that_is_already_an_injected_fixture(f: u32) {} #[rstest(a, case(42), a => [42])] fn error_define_a_value_list_that_is_already_a_case_arg(a: u32) {} #[rstest(a => [42], a, case(42))] fn error_define_a_case_arg_that_is_already_a_value_list(a: u32) {} #[rstest(a => [42, 24], a => [24, 42])] fn error_define_a_value_list_that_is_already_a_value_list(f: u32) {} #[rstest(a, a, case(42))] fn error_define_a_case_arg_that_is_already_a_case_arg(a: u32) {} struct S; #[rstest] #[case("donald duck")] fn error_convert_to_type_that_not_implement_from_str(#[case] s: S) {} #[rstest] #[case(async { "hello" } )] async fn error_future_on_impl_type(#[case] #[future] s: impl AsRef) {} #[rstest] #[case(async { 42 } )] async fn error_future_on_impl_type(#[case] #[future] #[future] a: i32) {} #[rstest] #[timeout] fn error_timeout_without_arg() {} #[rstest] #[timeout(some -> strange -> invalid -> expression)] fn error_timeout_without_expression_arg() {} #[rstest] #[timeout(42)] fn error_timeout_without_duration() {} rstest-0.17.0/tests/resources/rstest/generic.rs000064400000000000000000000005541046102023000177230ustar 00000000000000use rstest::*; #[fixture] fn fixture() -> String { "str".to_owned() } #[rstest] fn simple>(fixture: S) { assert_eq!(3, fixture.as_ref().len()); } #[rstest( expected, input, case(4, String::from("ciao")), case(3, "Foo") )] fn strlen_test>(expected: usize, input: S) { assert_eq!(expected, input.as_ref().len()); } rstest-0.17.0/tests/resources/rstest/happy_path.rs000064400000000000000000000007431046102023000204440ustar 00000000000000use rstest::*; #[fixture] fn inject() -> u32 { 0 } #[fixture] fn ex() -> u32 { 42 } #[fixture] fn fix(inject: u32, ex: u32) -> bool { (inject * 2) == ex } #[rstest( fix(21), a, case(21, 2), expected => [4, 2*3-2], )] #[case::second(14, 3)] fn happy( fix: bool, a: u32, #[case] b: u32, expected: usize, #[values("ciao", "buzz")] input: &str, ) { assert!(fix); assert_eq!(a * b, 42); assert_eq!(expected, input.len()); } rstest-0.17.0/tests/resources/rstest/ignore_args.rs000064400000000000000000000002261046102023000206020ustar 00000000000000use rstest::*; #[rstest] #[case(42, 2)] #[case(43, 3)] fn test(#[case] _ignore1: u32, #[case] _ignore2: u32, #[values(1, 2, 3, 4)] _ignore3: u32) {} rstest-0.17.0/tests/resources/rstest/impl_param.rs000064400000000000000000000005521046102023000204260ustar 00000000000000use rstest::*; #[fixture] fn fixture() -> String { "str".to_owned() } #[rstest] fn simple(fixture: impl AsRef) { assert_eq!(3, fixture.as_ref().len()); } #[rstest( expected, input, case(4, String::from("ciao")), case(3, "Foo") )] fn strlen_test(expected: usize, input: impl AsRef) { assert_eq!(expected, input.as_ref().len()); } rstest-0.17.0/tests/resources/rstest/matrix/async.rs000064400000000000000000000003211046102023000207200ustar 00000000000000use rstest::*; #[rstest] async fn my_async_test( #[future] #[values(async { 1 }, async { 2 })] first: u32, #[values(42, 21)] second: u32 ) { assert_eq!(42, first.await * second); }rstest-0.17.0/tests/resources/rstest/matrix/async_awt.rs000064400000000000000000000003201046102023000215720ustar 00000000000000use rstest::*; #[rstest] async fn my_async_test( #[future(awt)] #[values(async { 1 }, async { 2 })] first: u32, #[values(42, 21)] second: u32 ) { assert_eq!(42, first * second); }rstest-0.17.0/tests/resources/rstest/matrix/async_awt_global.rs000064400000000000000000000003221046102023000231140ustar 00000000000000use rstest::*; #[rstest] #[awt] async fn my_async_test( #[future] #[values(async { 1 }, async { 2 })] first: u32, #[values(42, 21)] second: u32 ) { assert_eq!(42, first * second); }rstest-0.17.0/tests/resources/rstest/matrix/inject.rs000064400000000000000000000006041046102023000210630ustar 00000000000000use rstest::*; use actix_rt; use std::future::Future; #[rstest( first => [1, 2], second => [2, 1], )] #[test] fn sync(first: u32, second: u32) { assert_eq!(2, first * second); } #[rstest( first => [async { 1 }, async { 2 }], second => [2, 1], )] #[actix_rt::test] async fn fn_async(first: impl Future, second: u32) { assert_eq!(2, first.await * second); } rstest-0.17.0/tests/resources/rstest/matrix/partial.rs000064400000000000000000000021341046102023000212430ustar 00000000000000use rstest::*; #[fixture] fn f1() -> u32 { 0 } #[fixture] fn f2() -> u32 { 0 } #[fixture] fn f3() -> u32 { 0 } #[fixture] fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { f1 + f2 + 2 * f3 } #[rstest(a => [0, 1], b => [0, 2])] fn default(fixture: u32, a: u32, b: u32) { assert_eq!(fixture, a * b); } #[rstest(a => [0, 1], b => [0, 2], fixture(1))] fn partial_1(fixture: u32, a: u32, b: u32) { assert_eq!(fixture, a * b); } #[rstest(a => [0, 1], b => [0, 2])] fn partial_attr_1(#[with(1)] fixture: u32, a: u32, b: u32) { assert_eq!(fixture, a * b); } #[rstest(a => [0, 1], b => [0, 2], fixture(0, 2))] fn partial_2(fixture: u32, a: u32, b: u32) { assert_eq!(fixture, a * b); } #[rstest(a => [0, 1], b => [0, 2])] fn partial_attr_2(#[with(0, 2)] fixture: u32, a: u32, b: u32) { assert_eq!(fixture, a * b); } #[rstest(a => [0, 1], b => [0, 2], fixture(0, 0, 1))] fn complete(fixture: u32, a: u32, b: u32) { assert_eq!(fixture, a * b); } #[rstest(a => [0, 1], b => [0, 2])] fn complete_attr(#[with(0, 0, 1)] fixture: u32, a: u32, b: u32) { assert_eq!(fixture, a * b); } rstest-0.17.0/tests/resources/rstest/matrix/simple.rs000064400000000000000000000002651046102023000211030ustar 00000000000000use rstest::rstest; #[rstest( expected => [4, 2*3-2], input => ["ciao", "buzz"], )] fn strlen_test(expected: usize, input: &str) { assert_eq!(expected, input.len()); } rstest-0.17.0/tests/resources/rstest/matrix/use_attr.rs000064400000000000000000000007061046102023000214400ustar 00000000000000use rstest::rstest; #[rstest] fn both(#[values(4, 2*3-2)] expected: usize, #[values("ciao", "buzz")] input: &str) { assert_eq!(expected, input.len()); } #[rstest( input => ["ciao", "buzz"] )] fn first(#[values(4, 2*3-2)] expected: usize, input: &str) { assert_eq!(expected, input.len()); } #[rstest( expected => [4, 2*3-2] )] fn second(expected: usize, #[values("ciao", "buzz")] input: &str) { assert_eq!(expected, input.len()); } rstest-0.17.0/tests/resources/rstest/mut.rs000064400000000000000000000007271046102023000171160ustar 00000000000000use rstest::*; #[fixture] pub fn fixture() -> u32 { 42 } #[rstest] fn should_success(mut fixture: u32) { fixture += 1; assert_eq!(fixture, 43); } #[rstest] fn should_fail(mut fixture: u32) { fixture += 1; assert_ne!(fixture, 43); } #[rstest( expected, val, case(45, 1), case(46, 2), case(47, 2) )] fn add_test(mut fixture: u32, expected: u32, mut val: u32) { fixture += 1; val += fixture + 1; assert_eq!(expected, val); } rstest-0.17.0/tests/resources/rstest/panic.rs000064400000000000000000000006311046102023000173750ustar 00000000000000use rstest::*; #[fixture] pub fn fixture() -> u32 { 42 } #[rstest] #[should_panic] fn should_success(fixture: u32) { assert_ne!(fixture, 42); } #[rstest] #[should_panic] fn should_fail(fixture: u32) { assert_eq!(fixture, 42); } #[rstest( expected, input, case(4, 5), case(3, 2), case(3, 3) )] #[should_panic] fn fail(expected: i32, input: i32) { assert_eq!(expected, input); } rstest-0.17.0/tests/resources/rstest/reject_no_item_function.rs000064400000000000000000000001351046102023000231750ustar 00000000000000use rstest::rstest; #[rstest] struct Foo; #[rstest] impl Foo {} #[rstest] mod mod_baz {} rstest-0.17.0/tests/resources/rstest/remove_underscore.rs000064400000000000000000000001711046102023000220300ustar 00000000000000use rstest::*; #[fixture] fn can_be_ignored() {} #[rstest] fn ignore_input(_can_be_ignored: ()) { assert!(true); } rstest-0.17.0/tests/resources/rstest/rename.rs000064400000000000000000000010311046102023000175450ustar 00000000000000use rstest::*; #[fixture] fn very_long_and_boring_name(#[default(42)] inject: u32) -> u32 { inject } #[rstest(very_long_and_boring_name as foo)] fn compact(foo: u32) { assert!(42 == foo); } #[rstest(very_long_and_boring_name(21) as foo)] fn compact_injected(foo: u32) { assert!(21 == foo); } #[rstest] fn attribute(#[from(very_long_and_boring_name)] foo: u32) { assert!(42 == foo); } #[rstest] fn attribute_injected( #[from(very_long_and_boring_name)] #[with(21)] foo: u32, ) { assert!(21 == foo); } rstest-0.17.0/tests/resources/rstest/return_result.rs000064400000000000000000000005471046102023000212260ustar 00000000000000use rstest::rstest; #[rstest] fn should_success() -> Result<(), &'static str> { Ok(()) } #[rstest] fn should_fail() -> Result<(), &'static str> { Err("Return Error") } #[rstest(ret, case::should_success(Ok(())), case::should_fail(Err("Return Error")) )] fn return_type(ret: Result<(), &'static str>) -> Result<(), &'static str> { ret } rstest-0.17.0/tests/resources/rstest/single/async.rs000064400000000000000000000010011046102023000206710ustar 00000000000000use rstest::*; #[fixture] async fn fixture() -> u32 { 42 } #[rstest] async fn should_pass(#[future] fixture: u32) { assert_eq!(fixture.await, 42); } #[rstest] async fn should_fail(#[future] fixture: u32) { assert_ne!(fixture.await, 42); } #[rstest] #[should_panic] async fn should_panic_pass(#[future] fixture: u32) { panic!(format!("My panic -> fixture = {}", fixture.await)); } #[rstest] #[should_panic] async fn should_panic_fail(#[future] fixture: u32) { assert_eq!(fixture.await, 42); } rstest-0.17.0/tests/resources/rstest/single/async_awt.rs000064400000000000000000000010011046102023000215440ustar 00000000000000use rstest::*; #[fixture] async fn fixture() -> u32 { 42 } #[rstest] async fn should_pass(#[future(awt)] fixture: u32) { assert_eq!(fixture, 42); } #[rstest] async fn should_fail(#[future(awt)] fixture: u32) { assert_ne!(fixture, 42); } #[rstest] #[should_panic] async fn should_panic_pass(#[future(awt)] fixture: u32) { panic!(format!("My panic -> fixture = {}", fixture)); } #[rstest] #[should_panic] async fn should_panic_fail(#[future(awt)] fixture: u32) { assert_eq!(fixture, 42); } rstest-0.17.0/tests/resources/rstest/single/async_awt_global.rs000064400000000000000000000010111046102023000230650ustar 00000000000000use rstest::*; #[fixture] async fn fixture() -> u32 { 42 } #[rstest] #[awt] async fn should_pass(#[future] fixture: u32) { assert_eq!(fixture, 42); } #[rstest] #[awt] async fn should_fail(#[future] fixture: u32) { assert_ne!(fixture, 42); } #[rstest] #[awt] #[should_panic] async fn should_panic_pass(#[future] fixture: u32) { panic!(format!("My panic -> fixture = {}", fixture)); } #[rstest] #[awt] #[should_panic] async fn should_panic_fail(#[future] fixture: u32) { assert_eq!(fixture, 42); } rstest-0.17.0/tests/resources/rstest/single/dump_debug.rs000064400000000000000000000005211046102023000216750ustar 00000000000000use rstest::*; #[derive(Debug)] struct A {} #[fixture] fn fu32() -> u32 { 42 } #[fixture] fn fstring() -> String { "A String".to_string() } #[fixture] fn ftuple() -> (A, String, i32) { (A{}, "A String".to_string(), -12) } #[rstest(::trace)] fn should_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { assert!(false); } rstest-0.17.0/tests/resources/rstest/single/inject.rs000064400000000000000000000012231046102023000210360ustar 00000000000000use rstest::*; use actix_rt; #[fixture] fn a() -> u32 { 42 } #[rstest] #[test] fn sync_case(a: u32) {} #[rstest] #[test] #[should_panic] fn sync_case_panic(a: u32) { panic!("panic") } #[rstest] #[test] fn sync_case_fail(a: u32) { assert_eq!(2, a); } #[rstest] #[test] fn sync_case_panic_fail(a: u32) { panic!("panic") } #[rstest] #[actix_rt::test] async fn async_case(a: u32) {} #[rstest] #[actix_rt::test] async fn async_case_fail(a: u32) { assert_eq!(2, a); } #[rstest] #[actix_rt::test] #[should_panic] async fn async_case_panic(a: u32) { panic!("panic") } #[rstest] #[actix_rt::test] async fn async_case_panic_fail(a: u32) { panic!("panic") }rstest-0.17.0/tests/resources/rstest/single/partial.rs000064400000000000000000000014471046102023000212260ustar 00000000000000use rstest::*; #[fixture] fn f1() -> u32 { 0 } #[fixture] fn f2() -> u32 { 0 } #[fixture] fn f3() -> u32 { 0 } #[fixture] fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { f1 + 10 * f2 + 100 * f3 } #[rstest] fn default(fixture: u32) { assert_eq!(fixture, 0); } #[rstest(fixture(7))] fn partial_1(fixture: u32) { assert_eq!(fixture, 7); } #[rstest] fn partial_attr_1(#[with(7)] fixture: u32) { assert_eq!(fixture, 7); } #[rstest(fixture(2, 4))] fn partial_2(fixture: u32) { assert_eq!(fixture, 42); } #[rstest] fn partial_attr_2(#[with(2, 4)] fixture: u32) { assert_eq!(fixture, 42); } #[rstest(fixture(2, 4, 5))] fn complete(fixture: u32) { assert_eq!(fixture, 542); } #[rstest] fn complete_attr(#[with(2, 4, 5)] fixture: u32) { assert_eq!(fixture, 542); } rstest-0.17.0/tests/resources/rstest/single/resolve.rs000064400000000000000000000005661046102023000212520ustar 00000000000000use rstest::*; pub trait Tr { fn get() -> Self; } impl Tr for i32 { fn get() -> Self { 42 } } impl Tr for u32 { fn get() -> Self { 42 } } #[fixture] pub fn fgen() -> T { T::get() } #[rstest] fn generics_u32(fgen: u32) { assert_eq!(fgen, 42u32); } #[rstest] fn generics_i32(fgen: i32) { assert_eq!(fgen, 42i32); } rstest-0.17.0/tests/resources/rstest/single/simple.rs000064400000000000000000000003171046102023000210560ustar 00000000000000use rstest::*; #[fixture] pub fn fixture() -> u32 { 42 } #[rstest] fn should_success(fixture: u32) { assert_eq!(fixture, 42); } #[rstest] fn should_fail(fixture: u32) { assert_ne!(fixture, 42); } rstest-0.17.0/tests/resources/rstest/timeout.rs000064400000000000000000000121221046102023000177670ustar 00000000000000use rstest::*; use std::time::Duration; fn ms(ms: u32) -> Duration { Duration::from_millis(ms.into()) } mod thread { use super::*; fn delayed_sum(a: u32, b: u32, delay: Duration) -> u32 { std::thread::sleep(delay); a + b } #[rstest] #[timeout(ms(80))] fn single_pass() { assert_eq!(4, delayed_sum(2, 2, ms(10))); } #[rstest] #[timeout(ms(100))] fn single_fail_value() { assert_eq!(5, delayed_sum(2, 2, ms(1))); } #[rstest] #[timeout(ms(1000))] #[should_panic = "user message"] fn fail_with_user_message() { panic!("user message"); } #[rstest] #[timeout(ms(10))] fn single_fail_timeout() { assert_eq!(4, delayed_sum(2, 2, ms(80))); } #[rstest] #[timeout(ms(80))] #[case(ms(10))] fn one_pass(#[case] delay: Duration) { assert_eq!(4, delayed_sum(2, 2, delay)); } #[rstest] #[timeout(ms(10))] #[case(ms(80))] fn one_fail_timeout(#[case] delay: Duration) { assert_eq!(4, delayed_sum(2, 2, delay)); } #[rstest] #[timeout(ms(100))] #[case(ms(1))] fn one_fail_value(#[case] delay: Duration) { assert_eq!(5, delayed_sum(2, 2, delay)); } #[rstest] #[case::pass(ms(1), 4)] #[case::fail_timeout(ms(80), 4)] #[case::fail_value(ms(1), 5)] #[timeout(ms(40))] fn group_same_timeout(#[case] delay: Duration, #[case] expected: u32) { assert_eq!(expected, delayed_sum(2, 2, delay)); } #[rstest] #[timeout(ms(100))] #[case::pass(ms(1), 4)] #[timeout(ms(30))] #[case::fail_timeout(ms(70), 4)] #[timeout(ms(100))] #[case::fail_value(ms(1), 5)] fn group_single_timeout(#[case] delay: Duration, #[case] expected: u32) { assert_eq!(expected, delayed_sum(2, 2, delay)); } #[rstest] #[case::pass(ms(1), 4)] #[timeout(ms(10))] #[case::fail_timeout(ms(60), 4)] #[case::fail_value(ms(1), 5)] #[timeout(ms(100))] fn group_one_timeout_override(#[case] delay: Duration, #[case] expected: u32) { assert_eq!(expected, delayed_sum(2, 2, delay)); } struct S {} #[rstest] #[case(S{})] fn compile_with_no_copy_arg(#[case] _s: S) { assert!(true); } #[fixture] fn no_copy() -> S { S {} } #[rstest] fn compile_with_no_copy_fixture(no_copy: S) { assert!(true); } } mod async_std_cases { use super::*; async fn delayed_sum(a: u32, b: u32, delay: Duration) -> u32 { async_std::task::sleep(delay).await; a + b } #[rstest] #[timeout(ms(80))] async fn single_pass() { assert_eq!(4, delayed_sum(2, 2, ms(10)).await); } #[rstest] #[timeout(ms(10))] async fn single_fail_timeout() { assert_eq!(4, delayed_sum(2, 2, ms(80)).await); } #[rstest] #[timeout(ms(100))] async fn single_fail_value() { assert_eq!(5, delayed_sum(2, 2, ms(1)).await); } #[rstest] #[timeout(ms(1000))] #[should_panic = "user message"] async fn fail_with_user_message() { panic! {"user message"}; } #[rstest] #[timeout(ms(80))] #[case(ms(10))] async fn one_pass(#[case] delay: Duration) { assert_eq!(4, delayed_sum(2, 2, delay).await); } #[rstest] #[timeout(ms(10))] #[case(ms(80))] async fn one_fail_timeout(#[case] delay: Duration) { assert_eq!(4, delayed_sum(2, 2, delay).await); } #[rstest] #[timeout(ms(100))] #[case(ms(1))] async fn one_fail_value(#[case] delay: Duration) { assert_eq!(5, delayed_sum(2, 2, delay).await); } #[rstest] #[case::pass(ms(1), 4)] #[case::fail_timeout(ms(80), 4)] #[case::fail_value(ms(1), 5)] #[timeout(ms(40))] async fn group_same_timeout(#[case] delay: Duration, #[case] expected: u32) { assert_eq!(expected, delayed_sum(2, 2, delay).await); } #[rstest] #[timeout(ms(100))] #[case::pass(ms(1), 4)] #[timeout(ms(30))] #[case::fail_timeout(ms(70), 4)] #[timeout(ms(100))] #[case::fail_value(ms(1), 5)] async fn group_single_timeout(#[case] delay: Duration, #[case] expected: u32) { assert_eq!(expected, delayed_sum(2, 2, delay).await); } #[rstest] #[case::pass(ms(1), 4)] #[timeout(ms(10))] #[case::fail_timeout(ms(60), 4)] #[case::fail_value(ms(1), 5)] #[timeout(ms(100))] async fn group_one_timeout_override(#[case] delay: Duration, #[case] expected: u32) { assert_eq!(expected, delayed_sum(2, 2, delay).await); } struct S {} #[rstest] #[case(S{})] async fn compile_with_no_copy_arg(#[case] _s: S) { assert!(true); } #[fixture] fn no_copy() -> S { S {} } #[rstest] fn compile_with_no_copy_fixture(_no_copy: S) { assert!(true); } #[fixture] async fn a_fix() -> S { S {} } #[rstest] fn compile_with_async_fixture(#[future] a_fix: S) { assert!(true); } #[rstest] async fn compile_with_async_awt_fixture(#[future(awt)] a_fix: S) { assert!(true); } } rstest-0.17.0/tests/resources/rstest/timeout_async.rs000064400000000000000000000005151046102023000211670ustar 00000000000000use rstest::*; use std::time::Duration; fn ms(ms: u32) -> Duration { Duration::from_millis(ms.into()) } async fn delayed_sum(a: u32, b: u32,delay: Duration) -> u32 { async_std::task::sleep(delay).await; a + b } #[rstest] #[timeout(ms(80))] async fn single_pass() { assert_eq!(4, delayed_sum(2, 2, ms(10)).await); }rstest-0.17.0/tests/resources/rstest/use_mutable_fixture_in_parametric_argumnts.rs000064400000000000000000000007221046102023000271740ustar 00000000000000use rstest::*; #[fixture] fn f() -> String { "f".to_owned() } fn append(s: &mut String, a: &str) -> String { s.push_str("-"); s.push_str(a); s.clone() } #[rstest] #[case(append(&mut f, "a"), "f-a", "f-a-b")] fn use_mutate_fixture( mut f: String, #[case] a: String, #[values(append(&mut f, "b"))] b: String, #[case] expected_a: &str, #[case] expected_b: &str, ) { assert_eq!(expected_a, a); assert_eq!(expected_b, b); } rstest-0.17.0/tests/resources/rstest/values_tests_name.rs000064400000000000000000000005121046102023000220220ustar 00000000000000use rstest::*; enum Application { Python, Node, Go, } enum Method { GET, POST, PUT, HEAD, } #[rstest] fn name_values( #[values(Application::Python, Application::Node, Application::Go)] _val: Application, #[values(Method::GET, Method::POST, Method::PUT, Method::HEAD)] _method: Method, ) { } rstest-0.17.0/tests/rstest/mod.rs000064400000000000000000001232171046102023000150560ustar 00000000000000use std::path::Path; use mytest::*; use rstest_test::*; use unindent::Unindent; pub fn resources(res: impl AsRef) -> std::path::PathBuf { let path = Path::new("rstest").join(res.as_ref()); super::resources(path) } fn prj(res: impl AsRef) -> Project { crate::prj().set_code_file(resources(res)) } fn run_test(res: impl AsRef) -> (std::process::Output, String) { let prj = prj(res); ( prj.run_tests().unwrap(), prj.get_name().to_owned().to_string(), ) } #[test] fn mutable_input() { let (output, _) = run_test("mut.rs"); TestResults::new() .ok("should_success") .fail("should_fail") .ok("add_test::case_1") .ok("add_test::case_2") .fail("add_test::case_3") .assert(output); } #[test] fn test_with_return_type() { let (output, _) = run_test("return_result.rs"); TestResults::new() .ok("should_success") .fail("should_fail") .ok("return_type::case_1_should_success") .fail("return_type::case_2_should_fail") .assert(output); } #[test] fn should_panic() { let (output, _) = run_test("panic.rs"); TestResults::new() .ok("should_success") .fail("should_fail") .ok("fail::case_1") .ok("fail::case_2") .fail("fail::case_3") .assert(output); } #[test] fn should_not_show_a_warning_for_should_panic_attribute() { let (output, _) = run_test("panic.rs"); assert!(!output.stderr.str().contains("unused attribute")); } #[test] fn should_not_show_a_warning_for_values_test_names() { let (output, _) = run_test("values_tests_name.rs"); assert_not_in!(output.stderr.str(), "warning:"); } #[test] fn should_map_fixture_by_remove_first_underscore_if_any() { let (output, _) = run_test("remove_underscore.rs"); TestResults::new().ok("ignore_input").assert(output); } #[test] fn generic_input() { let (output, _) = run_test("generic.rs"); TestResults::new() .ok("simple") .ok("strlen_test::case_1") .ok("strlen_test::case_2") .assert(output); } #[test] fn impl_input() { let (output, _) = run_test("impl_param.rs"); TestResults::new() .ok("simple") .ok("strlen_test::case_1") .ok("strlen_test::case_2") .assert(output); } #[test] fn use_mutable_fixture_in_parametric_argumnts() { let (output, _) = run_test("use_mutable_fixture_in_parametric_argumnts.rs"); TestResults::new() .with_contains(true) .ok("use_mutate_fixture::case_1::b_1") .assert(output); } #[test] fn should_reject_no_item_function() { let (output, name) = run_test("reject_no_item_function.rs"); assert_in!( output.stderr.str(), format!( " error: expected `fn` --> {}/src/lib.rs:4:1 | 4 | struct Foo; | ^^^^^^ ", name ) .unindent() ); assert_in!( output.stderr.str(), format!( " error: expected `fn` --> {}/src/lib.rs:7:1 | 7 | impl Foo {{}} | ^^^^ ", name ) .unindent() ); assert_in!( output.stderr.str(), format!( " error: expected `fn` --> {}/src/lib.rs:10:1 | 10 | mod mod_baz {{}} | ^^^ ", name ) .unindent() ); } mod dump_input_values { use super::*; #[rstest] #[case::compact_syntax("dump_debug_compact.rs")] #[case::attr_syntax("dump_debug.rs")] fn if_implements_debug(#[case] source: &str) { let (output, _) = run_test(source); let out = output.stdout.str().to_string(); TestResults::new() .fail("single_fail") .fail("no_trace_single_fail") .fail("cases_fail::case_1") .fail("cases_fail::case_2") .fail("no_trace_cases_fail::case_1") .fail("no_trace_cases_fail::case_2") .fail_with("matrix_fail::u_1", false, 8) .fail_with("matrix_fail::u_2", false, 8) .assert(output); assert_in!(out, "fu32 = 42"); assert_in!(out, r#"fstring = "A String""#); assert_in!(out, r#"ftuple = (A, "A String", -12"#); assert_in!(out, "u = 42"); assert_in!(out, r#"s = "str""#); assert_in!(out, r#"t = ("ss", -12)"#); assert_in!(out, "u = 24"); assert_in!(out, r#"s = "trs""#); assert_in!(out, r#"t = ("tt", -24)"#); assert_in!(out, "u = 1"); assert_in!(out, r#"s = "rst""#); assert_in!(out, r#"t = ("SS", -12)"#); assert_in!(out, "u = 2"); assert_in!(out, r#"s = "srt""#); assert_in!(out, r#"t = ("TT", -24)"#); let expected = 11; for marker in ["TEST START", "TEST ARGUMENTS"] { let n_found = out.lines().filter(|l| l.contains(marker)).count(); assert_eq!( n_found, expected, "Should contain {expected} '{marker}' but found {n_found}. [Should not enclose output if no trace]" ); } } #[rstest] #[case::compact_syntax("dump_not_debug_compact.rs")] #[case::attr_syntax("dump_not_debug.rs")] fn should_not_compile_if_not_implement_debug(#[case] source: &str) { let (output, name) = run_test(source); assert_all_in!( output.stderr.str(), format!("--> {}/src/lib.rs:10:11", name), "fn single(fixture: S) {}", "^^^^^^^ `S` cannot be formatted using `{:?}`" ); assert_in!( output.stderr.str(), format!("--> {}/src/lib.rs:15:10", name), "fn cases(s: S) {}", "^ `S` cannot be formatted using `{:?}`" ); assert_in!( output.stderr.str(), format!("--> {}/src/lib.rs:20:11", name), "fn matrix(s: S) {}", "^ `S` cannot be formatted using `{:?}`" ); } #[rstest] #[case::compact_syntax("dump_exclude_some_inputs_compact.rs")] #[case::attr_syntax("dump_exclude_some_inputs.rs")] fn can_exclude_some_inputs(#[case] source: &str) { let (output, _) = run_test(source); let out = output.stdout.str().to_string(); TestResults::new() .fail("simple") .fail("cases::case_1") .fail_in("matrix::a_1") .assert(output); assert_in!(out, "fu32 = 42"); assert_in!(out, "d = D"); assert_in!(out, "fd = D"); assert_in!(out, "dd = D"); } #[test] fn should_be_enclosed_in_an_explicit_session() { let (output, _) = run_test(Path::new("single").join("dump_debug.rs")); let out = output.stdout.str().to_string(); TestResults::new().fail("should_fail").assert(output); let lines = out .lines() .skip_while(|l| !l.contains("TEST ARGUMENTS")) .take_while(|l| !l.contains("TEST START")) .collect::>(); let expected = 4; assert_eq!( expected, lines.len(), "Not contains {expected} lines but {}: '{}'", lines.len(), lines.join("\n") ); } } mod single { use super::*; fn res(name: impl AsRef) -> impl AsRef { Path::new("single").join(name.as_ref()) } #[test] fn one_success_and_one_fail() { let (output, _) = run_test(res("simple.rs")); TestResults::new() .ok("should_success") .fail("should_fail") .assert(output); } #[test] fn should_resolve_generics_fixture_outputs() { let (output, _) = run_test(res("resolve.rs")); TestResults::new() .ok("generics_u32") .ok("generics_i32") .assert(output); } #[test] fn should_apply_partial_fixture() { let (output, _) = run_test(res("partial.rs")); TestResults::new() .ok("default") .ok("partial_1") .ok("partial_attr_1") .ok("partial_2") .ok("partial_attr_2") .ok("complete") .ok("complete_attr") .assert(output); } #[rstest] #[case("async.rs")] #[case("async_awt.rs")] #[case("async_awt_global.rs")] fn should_run_async_function(#[case] name: &str) { let prj = prj(res(name)); prj.add_dependency("async-std", r#"{version="*", features=["attributes"]}"#); let output = prj.run_tests().unwrap(); TestResults::new() .ok("should_pass") .fail("should_fail") .ok("should_panic_pass") .fail("should_panic_fail") .assert(output); } #[test] fn should_use_injected_test_attr() { let prj = prj(res("inject.rs")); prj.add_dependency("actix-rt", r#""1.1.0""#); let output = prj.run_tests().unwrap(); TestResults::new() .ok("sync_case") .ok("sync_case_panic") .fail("sync_case_fail") .fail("sync_case_panic_fail") .ok("async_case") .ok("async_case_panic") .fail("async_case_fail") .fail("async_case_panic_fail") .assert(output); } } mod cases { use super::*; fn res(name: impl AsRef) -> impl AsRef { Path::new("cases").join(name.as_ref()) } #[test] fn should_compile() { let output = prj(res("simple.rs")).compile().unwrap(); assert_eq!( Some(0), output.status.code(), "Compile error due: {}", output.stderr.str() ) } #[test] fn happy_path() { let (output, _) = run_test(res("simple.rs")); TestResults::new() .ok("strlen_test::case_1") .ok("strlen_test::case_2") .assert(output); } #[test] fn use_attr() { let (output, _) = run_test(res("use_attr.rs")); TestResults::new() .ok("all::case_1_ciao") .ok("all::case_2_panic") .ok("all::case_3_foo") .ok("just_cases::case_1_ciao") .ok("just_cases::case_2_foo") .ok("just_cases::case_3_panic") .ok("just_args::case_1_ciao") .ok("just_args::case_2_foo") .ok("just_args::case_3_panic") .ok("all_panic::case_1") .ok("all_panic::case_2") .assert(output); } #[test] fn case_description() { let (output, _) = run_test(res("description.rs")); TestResults::new() .ok("description::case_1_user_test_description") .ok("description::case_2") .fail("description::case_3_user_test_description_fail") .assert(output); } #[test] fn should_apply_partial_fixture() { let (output, _) = run_test(res("partial.rs")); TestResults::new() .ok("default::case_1") .ok("partial_1::case_1") .ok("partial_2::case_1") .ok("complete::case_1") .ok("partial_attr_1::case_1") .ok("partial_attr_2::case_1") .ok("complete_attr::case_1") .fail("default::case_2") .fail("partial_1::case_2") .fail("partial_2::case_2") .fail("complete::case_2") .fail("partial_attr_1::case_2") .fail("partial_attr_2::case_2") .fail("complete_attr::case_2") .assert(output); } #[test] fn should_use_case_attributes() { let (output, _) = run_test(res("case_attributes.rs")); TestResults::new() .ok("attribute_per_case::case_1_no_panic") .ok("attribute_per_case::case_2_panic") .ok("attribute_per_case::case_3_panic_with_message") .fail("attribute_per_case::case_4_no_panic_but_fail") .fail("attribute_per_case::case_5_panic_but_fail") .fail("attribute_per_case::case_6_panic_with_wrong_message") .assert(output); } #[rstest] #[case("async.rs")] #[case("async_awt.rs")] #[case("async_awt_global.rs")] fn should_run_async_function(#[case] name: &str) { let prj = prj(res(name)); prj.add_dependency("async-std", r#"{version="*", features=["attributes"]}"#); let output = prj.run_tests().unwrap(); TestResults::new() .ok("my_async_test::case_1_pass") .fail("my_async_test::case_2_fail") .ok("my_async_test::case_3_pass_panic") .fail("my_async_test::case_4_fail_panic") .ok("my_async_test_revert::case_1_pass") .assert(output); } #[test] fn should_use_injected_test_attr() { let prj = prj(res("inject.rs")); prj.add_dependency("actix-rt", r#""1.1.0""#); let output = prj.run_tests().unwrap(); TestResults::new() .ok("sync::case_1_pass") .ok("sync::case_2_panic") .fail("sync::case_3_fail") .ok("fn_async::case_1_pass") .ok("fn_async::case_2_panic") .fail("fn_async::case_3_fail") .assert(output); } #[test] fn trace_just_one_test() { let (output, _) = run_test(res("dump_just_one_case.rs")); let out = output.stdout.str().to_string(); TestResults::new() .fail("cases::case_1_first_no_dump") .fail("cases::case_2_dump_me") .fail("cases::case_3_last_no_dump") .assert(output); assert_in!(out, r#"s = "Trace it!""#); assert_not_in!(out, r#"s = "Please don't trace me""#); } mod not_compile_if_missed_arguments { use super::*; #[test] fn happy_path() { let (output, _) = run_test(res("missed_argument.rs")); let stderr = output.stderr.str(); assert_ne!(Some(0), output.status.code()); assert_in!(stderr, "Missed argument"); assert_in!( stderr, " | 4 | #[rstest(f, case(42), case(24))] | ^ " .unindent() ); } #[test] fn should_reports_all() { let (output, _) = run_test(res("missed_some_arguments.rs")); let stderr = output.stderr.str(); assert_in!( stderr, " | 4 | #[rstest(a,b,c, case(1,2,3), case(3,2,1))] | ^ " .unindent() ); assert_in!( stderr, " | 4 | #[rstest(a,b,c, case(1,2,3), case(3,2,1))] | ^ " .unindent() ); assert_eq!( 2, stderr.count("Missed argument"), "Should contain message exactly 2 occurrences in error message:\n{}", stderr ) } #[test] fn should_report_just_one_error_message_for_all_test_cases() { let (output, _) = run_test(res("missed_argument.rs")); let stderr = output.stderr.str(); assert_eq!( 1, stderr.count("Missed argument"), "More than one message occurrence in error message:\n{}", stderr ) } #[test] fn should_not_report_error_in_macro_syntax() { let (output, _) = run_test(res("missed_argument.rs")); let stderr = output.stderr.str(); assert!(!stderr.contains("macros that expand to items")); } } mod not_compile_if_a_case_has_a_wrong_signature { use std::process::Output; use lazy_static::lazy_static; use super::*; //noinspection RsTypeCheck fn execute() -> &'static (Output, String) { lazy_static! { static ref OUTPUT: (Output, String) = run_test(res("case_with_wrong_args.rs")); } assert_ne!(Some(0), OUTPUT.0.status.code(), "Should not compile"); &OUTPUT } #[test] fn with_too_much_arguments() { let (output, _) = execute(); let stderr = output.stderr.str(); assert_in!( stderr, " | 8 | #[rstest(a, case(42, 43), case(12), case(24, 34))] | ^^^^^^ " .unindent() ); assert_in!( stderr, " | 8 | #[rstest(a, case(42, 43), case(12), case(24, 34))] | ^^^^^^ " .unindent() ); } #[test] fn with_less_arguments() { let (output, _) = execute(); let stderr = output.stderr.str(); assert_in!( stderr, " | 4 | #[rstest(a, b, case(42), case(1, 2), case(43))] | ^^ " .unindent() ); assert_in!( stderr, " | 4 | #[rstest(a, b, case(42), case(1, 2), case(43))] | ^^ " .unindent() ); } #[test] fn and_reports_all_errors() { let (output, _) = execute(); let stderr = output.stderr.str(); // Exactly 4 cases are wrong assert_eq!( 4, stderr.count("Wrong case signature: should match the given parameters list."), "Should contain message exactly 4 occurrences in error message:\n{}", stderr ); } } mod not_compile_if_args_but_no_cases { use std::process::Output; use lazy_static::lazy_static; use super::*; //noinspection RsTypeCheck fn execute() -> &'static (Output, String) { lazy_static! { static ref OUTPUT: (Output, String) = run_test(res("args_with_no_cases.rs")); } assert_ne!(Some(0), OUTPUT.0.status.code(), "Should not compile"); &OUTPUT } #[test] fn report_error() { let (output, name) = execute(); let stderr = output.stderr.str(); assert_in!( stderr, format!( " error: No cases for this argument. --> {}/src/lib.rs:3:10 | 3 | #[rstest(one, two, three)] | ^^^ ", name ) .unindent() ); } #[test] fn and_reports_all_errors() { let (output, _) = execute(); let stderr = output.stderr.str(); // Exactly 3 cases are wrong assert_eq!( 3, stderr.count("No cases for this argument."), "Should contain message exactly 3 occurrences in error message:\n{}", stderr ); } } } mod matrix { use super::*; fn res(name: impl AsRef) -> impl AsRef { Path::new("matrix").join(name.as_ref()) } #[test] fn should_compile() { let output = prj(res("simple.rs")).compile().unwrap(); assert_eq!( Some(0), output.status.code(), "Compile error due: {}", output.stderr.str() ) } #[test] fn happy_path() { let (output, _) = run_test(res("simple.rs")); TestResults::new() .with_contains(true) .ok("strlen_test::expected_1_4::input_1___ciao__") .ok("strlen_test::expected_1_4::input_2___buzz__") .ok("strlen_test::expected_2_2_3_2::input_1___ciao__") .ok("strlen_test::expected_2_2_3_2::input_2___buzz__") .assert(output); } #[test] fn should_apply_partial_fixture() { let (output, _) = run_test(res("partial.rs")); TestResults::new() .with_contains(true) .ok_times("default::a_1", 2) .ok("default::a_2") .ok("partial_2::a_2") .ok("partial_attr_2::a_2") .ok("complete::a_2") .ok("complete_attr::a_2") .fail("default::a_2") .fail_times("partial_1::a_1", 2) .fail_times("partial_1::a_2", 2) .fail_times("partial_2::a_1", 2) .fail("partial_2::a_2") .fail_times("complete::a_1", 2) .fail("complete::a_2") .fail_times("partial_attr_1::a_1", 2) .fail_times("partial_attr_1::a_2", 2) .fail_times("partial_attr_2::a_1", 2) .fail("partial_attr_2::a_2") .fail_times("complete_attr::a_1", 2) .fail("complete_attr::a_2") .assert(output); } #[rstest] #[case("async.rs")] #[case("async_awt.rs")] #[case("async_awt_global.rs")] fn should_run_async_function(#[case] name: &str) { let prj = prj(res(name)); prj.add_dependency("async-std", r#"{version="*", features=["attributes"]}"#); let output = prj.run_tests().unwrap(); TestResults::new() .with_contains(true) .ok("my_async_test::first_1") .fail("my_async_test::first_1") .fail("my_async_test::first_2") .ok("my_async_test::first_2") .assert(output); } #[test] fn should_use_injected_test_attr() { let prj = prj(res("inject.rs")); prj.add_dependency("actix-rt", r#""1.1.0""#); let output = prj.run_tests().unwrap(); TestResults::new() .with_contains(true) .ok("sync::first_1") .fail("sync::first_1") .fail("sync::first_2") .ok("sync::first_2") .ok("fn_async::first_1") .fail("fn_async::first_1") .fail("fn_async::first_2") .ok("fn_async::first_2") .assert(output); } #[test] fn use_args_attributes() { let (output, _) = run_test(res("use_attr.rs")); TestResults::new() .ok("both::expected_1_4::input_1___ciao__") .ok("both::expected_1_4::input_2___buzz__") .ok("both::expected_2_2_3_2::input_1___ciao__") .ok("both::expected_2_2_3_2::input_2___buzz__") .ok("first::input_1___ciao__::expected_1_4") .ok("first::input_2___buzz__::expected_1_4") .ok("first::input_1___ciao__::expected_2_2_3_2") .ok("first::input_2___buzz__::expected_2_2_3_2") .ok("second::expected_1_4::input_1___ciao__") .ok("second::expected_1_4::input_2___buzz__") .ok("second::expected_2_2_3_2::input_1___ciao__") .ok("second::expected_2_2_3_2::input_2___buzz__") .assert(output); } } #[test] fn convert_string_literal() { let (output, _) = run_test("convert_string_literal.rs"); assert_regex!( "Cannot parse 'error' to get [a-z:_0-9]*MyType", output.stdout.str() ); TestResults::new() .ok("cases::case_1") .ok("cases::case_2") .ok("cases::case_3") .ok("cases::case_4") .fail("cases::case_5") .fail("cases::case_6") .ok_in("values::addr_1") .ok_in("values::addr_2") .fail_in("values::addr_3") .fail_in("values::addr_4") .ok_in("not_convert_byte_array::case_1::values_1") .ok("not_convert_impl::case_1") .ok("not_convert_generics::case_1") .ok("not_convert_generics::case_2") .ok("convert_without_debug::case_1") .fail("convert_without_debug::case_2") .assert(output); } #[test] fn happy_path() { let (output, _) = run_test("happy_path.rs"); TestResults::new() .ok("happy::case_1::expected_1_4::input_1___ciao__") .ok("happy::case_1::expected_1_4::input_2___buzz__") .ok("happy::case_1::expected_2_2_3_2::input_1___ciao__") .ok("happy::case_1::expected_2_2_3_2::input_2___buzz__") .ok("happy::case_2_second::expected_1_4::input_1___ciao__") .ok("happy::case_2_second::expected_1_4::input_2___buzz__") .ok("happy::case_2_second::expected_2_2_3_2::input_1___ciao__") .ok("happy::case_2_second::expected_2_2_3_2::input_2___buzz__") .assert(output); } #[test] fn rename() { let (output, _) = run_test("rename.rs"); TestResults::new() .ok("compact") .ok("compact_injected") .ok("attribute") .ok("attribute_injected") .assert(output); } #[test] fn ignore_underscore_args() { let (output, _) = run_test("ignore_args.rs"); TestResults::new() .with_contains(true) .ok("test::case_1::_ignore3_1") .ok("test::case_1::_ignore3_2") .ok("test::case_1::_ignore3_3") .ok("test::case_1::_ignore3_4") .ok("test::case_2::_ignore3_1") .ok("test::case_2::_ignore3_2") .ok("test::case_2::_ignore3_3") .ok("test::case_2::_ignore3_4") .assert(output); } #[test] fn timeout() { let prj = prj("timeout.rs"); prj.add_dependency("async-std", r#"{version="*", features=["attributes"]}"#); let output = prj.run_tests().unwrap(); TestResults::new() .ok("thread::single_pass") .fail("thread::single_fail_value") .ok("thread::fail_with_user_message") .fail("thread::single_fail_timeout") .ok("thread::one_pass::case_1") .fail("thread::one_fail_value::case_1") .fail("thread::one_fail_timeout::case_1") .ok("thread::group_same_timeout::case_1_pass") .fail("thread::group_same_timeout::case_2_fail_timeout") .fail("thread::group_same_timeout::case_3_fail_value") .ok("thread::group_single_timeout::case_1_pass") .fail("thread::group_single_timeout::case_2_fail_timeout") .fail("thread::group_single_timeout::case_3_fail_value") .ok("thread::group_one_timeout_override::case_1_pass") .fail("thread::group_one_timeout_override::case_2_fail_timeout") .fail("thread::group_one_timeout_override::case_3_fail_value") .ok("thread::compile_with_no_copy_arg::case_1") .ok("thread::compile_with_no_copy_fixture") .ok("async_std_cases::single_pass") .fail("async_std_cases::single_fail_value") .ok("async_std_cases::fail_with_user_message") .fail("async_std_cases::single_fail_timeout") .ok("async_std_cases::one_pass::case_1") .fail("async_std_cases::one_fail_value::case_1") .fail("async_std_cases::one_fail_timeout::case_1") .ok("async_std_cases::group_same_timeout::case_1_pass") .fail("async_std_cases::group_same_timeout::case_2_fail_timeout") .fail("async_std_cases::group_same_timeout::case_3_fail_value") .ok("async_std_cases::group_single_timeout::case_1_pass") .fail("async_std_cases::group_single_timeout::case_2_fail_timeout") .fail("async_std_cases::group_single_timeout::case_3_fail_value") .ok("async_std_cases::group_one_timeout_override::case_1_pass") .fail("async_std_cases::group_one_timeout_override::case_2_fail_timeout") .fail("async_std_cases::group_one_timeout_override::case_3_fail_value") .ok("async_std_cases::compile_with_no_copy_arg::case_1") .ok("async_std_cases::compile_with_no_copy_fixture") .ok("async_std_cases::compile_with_async_fixture") .ok("async_std_cases::compile_with_async_awt_fixture") .assert(output); } mod async_timeout_feature { use super::*; fn build_prj(features: &[&str]) -> Project { let prj = crate::base_prj(); let features = match features.is_empty() { true => String::new(), false => format!(r#", features=["{}"]"#, features.join(r#"",""#)), }; prj.add_dependency( "rstest", &format!( r#"{{path="{}", default-features = false {}}}"#, prj.exec_dir_str().as_str(), features ), ); prj.add_dependency("async-std", r#"{version="*", features=["attributes"]}"#); prj } #[test] fn should_not_compile_if_feature_disable() { let prj = build_prj(&[]); let output = prj .set_code_file(resources("timeout_async.rs")) .run_tests() .unwrap(); assert_in!(output.stderr.str(), "error: Enable async-timeout feature"); } #[test] fn should_work_if_feature_enabled() { let prj = build_prj(&["async-timeout"]); let output = prj .set_code_file(resources("timeout_async.rs")) .run_tests() .unwrap(); TestResults::new().ok("single_pass").assert(output); } } mod should_show_correct_errors { use std::process::Output; use lazy_static::lazy_static; use super::*; //noinspection RsTypeCheck fn execute() -> &'static (Output, String) { lazy_static! { static ref OUTPUT: (Output, String) = run_test("errors.rs"); } &OUTPUT } #[test] fn if_no_fixture() { let (output, name) = execute(); assert_in!(output.stderr.str(), "error[E0433]: "); assert_in!( output.stderr.str(), format!( " --> {}/src/lib.rs:13:33 | 13 | fn error_cannot_resolve_fixture(no_fixture: u32, f: u32) {{}}", name ) .unindent() ); } #[test] fn if_inject_wrong_fixture() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Missed argument: 'not_a_fixture' should be a test function argument. --> {}/src/lib.rs:28:23 | 28 | #[rstest(f, case(42), not_a_fixture(24))] | ^^^^^^^^^^^^^ ", name ) .unindent() ); } #[test] fn if_wrong_type() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( r#" error[E0308]: mismatched types --> {}/src/lib.rs:9:18 | 9 | let a: u32 = ""; "#, name ) .unindent() ); } #[test] fn if_wrong_type_fixture() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error[E0308]: mismatched types --> {}/src/lib.rs:16:29 | 16 | fn error_fixture_wrong_type(fixture: String, f: u32) {{}} ", name ) .unindent() ); } #[test] fn if_wrong_type_case_param() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error[E0308]: mismatched types --> {}/src/lib.rs:19:26 | 19 | fn error_case_wrong_type(f: &str) {{}}", name ) .unindent() ); } #[test] fn if_wrong_type_matrix_param() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error[E0308]: mismatched types --> {}/src/lib.rs:51:28 | 51 | fn error_matrix_wrong_type(f: &str) {{}}", name ) .unindent() ); } #[test] fn if_arbitrary_rust_code_has_some_errors() { let (output, name) = execute(); assert_regex!( format!( r#"error\[E0308\]: mismatched types \s+--> {}/src/lib\.rs:22:31"#, name ) .unindent(), output.stderr.str() ); assert_regex!( r#"22\s+|\s+case\(vec!\[1,2,3\]\.contains\(2\)\)\)"#, output.stderr.str() ); assert_regex!( format!( r#"error\[E0308\]: mismatched types \s+--> {}/src/lib\.rs:53:45"#, name ) .unindent(), output.stderr.str() ); assert_regex!( r#"53\s+|\s+#\[rstest\(condition => \[vec!\[1,2,3\]\.contains\(2\)\] \)\]"#, output.stderr.str() ); } #[test] fn if_inject_a_fixture_that_is_already_a_case() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'f' is already defined. --> {}/src/lib.rs:41:13 | 41 | #[rstest(f, f(42), case(12))] | ^", name ) .unindent() ); } #[test] fn if_define_a_case_arg_that_is_already_an_injected_fixture() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'f' is already defined. --> {}/src/lib.rs:44:17 | 44 | #[rstest(f(42), f, case(12))] | ^", name ) .unindent() ); } #[test] fn if_inject_a_fixture_more_than_once() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'f' is already defined. --> {}/src/lib.rs:47:20 | 47 | #[rstest(v, f(42), f(42), case(12))] | ^", name ) .unindent() ); } #[test] fn if_list_argument_dont_match_function_signature() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Missed argument: 'not_exist_1' should be a test function argument. --> {}/src/lib.rs:61:10 | 61 | #[rstest(not_exist_1 => [42], | ^^^^^^^^^^^", name ) .unindent() ); assert_in!( output.stderr.str(), format!( " error: Missed argument: 'not_exist_2' should be a test function argument. --> {}/src/lib.rs:62:10 | 62 | not_exist_2 => [42])] | ^^^^^^^^^^^", name ) .unindent() ); } #[test] fn if_inject_a_fixture_that_is_already_a_value_list() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'f' is already defined. --> {}/src/lib.rs:65:25 | 65 | #[rstest(f => [41, 42], f(42))] | ^", name ) .unindent() ); } #[test] fn if_define_value_list_more_that_once() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'a' is already defined. --> {}/src/lib.rs:77:25 | 77 | #[rstest(a => [42, 24], a => [24, 42])] | ^", name ) .unindent() ); } #[test] fn if_define_value_list_that_is_already_an_injected_fixture() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'f' is already defined. --> {}/src/lib.rs:68:17 | 68 | #[rstest(f(42), f => [41, 42])] | ^", name ) .unindent() ); } #[test] fn if_define_value_list_that_is_already_a_case_arg() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'a' is already defined. --> {}/src/lib.rs:71:23 | 71 | #[rstest(a, case(42), a => [42])] | ^", name ) .unindent() ); } #[test] fn if_define_a_case_arg_that_is_already_a_value_list() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'a' is already defined. --> {}/src/lib.rs:74:21 | 74 | #[rstest(a => [42], a, case(42))] | ^", name ) .unindent() ); } #[test] fn if_define_a_case_arg_more_that_once() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Duplicate argument: 'a' is already defined. --> {}/src/lib.rs:80:13 | 80 | #[rstest(a, a, case(42))] | ^", name ) .unindent() ); } #[test] fn if_a_value_contains_empty_list() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: Values list should not be empty --> {}/src/lib.rs:58:19 | 58 | #[rstest(empty => [])] | ^^", name ) .unindent() ); } #[test] fn if_try_to_convert_literal_string_to_a_type_that_not_implement_from_str() { let (output, name) = execute(); assert_in!(output.stderr.str(), format!("--> {}/src/lib.rs:84:1", name)); assert_in!( output.stderr.str(), "| -------- doesn't satisfy `S: FromStr`" ); } #[test] fn if_try_to_use_future_on_an_impl() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " --> {}/src/lib.rs:90:57 | 90 | async fn error_future_on_impl_type(#[case] #[future] s: impl AsRef) {{}} | ^^^^^^^^^^^^^^^ ", name ) .unindent() ); } #[test] fn if_try_to_use_future_more_that_once() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " --> {}/src/lib.rs:94:54 | 94 | async fn error_future_on_impl_type(#[case] #[future] #[future] a: i32) {{}} | ^^^^^^^^^ ", name ) .unindent() ); } #[test] fn if_use_timeout_without_arg() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: expected attribute arguments in parentheses: #[timeout(...)] --> {}/src/lib.rs:97:1 | 97 | #[timeout] | ^^^^^^^^^^ ", name ) .unindent() ); } #[test] fn if_timeout_is_not_an_expression() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error: expected expression --> {}/src/lib.rs:101:17 | 101 | #[timeout(some -> strange -> invalid -> expression)] | ^ ", name ) .unindent() ); } #[test] fn if_timeout_is_not_a_duration() { let (output, name) = execute(); assert_in!( output.stderr.str(), format!( " error[E0308]: mismatched types --> {}/src/lib.rs:105:11", name ) .unindent() ); assert_in!( output.stderr.str(), " 105 | #[timeout(42)] | ^^ expected struct `Duration`, found integer " .unindent() ); } }