├── .github ├── dependabot.yml └── workflows │ ├── test.yml │ └── update_head_docs.yml ├── .gitignore ├── .rustfmt.toml ├── .vscode └── launch.json ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── checkoutlist.md ├── docs └── head │ ├── .lock │ ├── COPYRIGHT.txt │ ├── FiraSans-LICENSE.txt │ ├── FiraSans-Medium.woff │ ├── FiraSans-Regular.woff │ ├── LICENSE-APACHE.txt │ ├── LICENSE-MIT.txt │ ├── SourceCodePro-LICENSE.txt │ ├── SourceCodePro-Regular.woff │ ├── SourceCodePro-Semibold.woff │ ├── SourceSerifPro-Bold.ttf.woff │ ├── SourceSerifPro-It.ttf.woff │ ├── SourceSerifPro-LICENSE.md │ ├── SourceSerifPro-Regular.ttf.woff │ ├── aliases.js │ ├── brush.svg │ ├── dark.css │ ├── down-arrow.svg │ ├── favicon.ico │ ├── light.css │ ├── main.js │ ├── normalize.css │ ├── noscript.css │ ├── rstest │ ├── all.html │ ├── attr.fixture.html │ ├── attr.rstest.html │ ├── attr.rstest_matrix.html │ ├── attr.rstest_parametrize.html │ ├── index.html │ └── sidebar-items.js │ ├── rust-logo.png │ ├── rustdoc.css │ ├── search-index.js │ ├── settings.css │ ├── settings.html │ ├── settings.js │ ├── source-files.js │ ├── source-script.js │ ├── src │ └── rstest │ │ ├── error.rs.html │ │ ├── lib.rs.html │ │ ├── parse │ │ ├── fixture.rs.html │ │ ├── macros.rs.html │ │ ├── mod.rs.html │ │ ├── rstest.rs.html │ │ ├── testcase.rs.html │ │ └── vlist.rs.html │ │ ├── refident.rs.html │ │ ├── render │ │ ├── fixture.rs.html │ │ ├── mod.rs.html │ │ └── wrapper.rs.html │ │ ├── resolver.rs.html │ │ └── utils.rs.html │ ├── storage.js │ ├── theme.js │ └── wheel.svg ├── notes.md ├── playground ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── files │ ├── myname.txt │ ├── other │ └── should_fail.txt └── src │ └── main.rs ├── rstest ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── src │ ├── context.rs │ ├── lib.rs │ ├── magic_conversion.rs │ └── timeout.rs └── tests │ ├── fixture │ └── mod.rs │ ├── integration.rs │ ├── resources │ ├── fixture │ │ ├── async_fixture.rs │ │ ├── await_complete_fixture.rs │ │ ├── await_partial_fixture.rs │ │ ├── clean_up_default_generics.rs │ │ ├── default.rs │ │ ├── default_conversion.rs │ │ ├── default_in_attrs.rs │ │ ├── defined_return_type.rs │ │ ├── deny_docs.rs │ │ ├── dyn.rs │ │ ├── errors.rs │ │ ├── errors_once.rs │ │ ├── fixture_struct.rs │ │ ├── from_other_module.rs │ │ ├── impl.rs │ │ ├── no_warning.rs │ │ ├── once.rs │ │ ├── once_defined_type.rs │ │ ├── once_no_return.rs │ │ ├── partial.rs │ │ ├── partial_in_attr.rs │ │ ├── rename.rs │ │ ├── resolve.rs │ │ └── simple_injection.rs │ └── rstest │ │ ├── by_ref.rs │ │ ├── cases │ │ ├── args_with_no_cases.rs │ │ ├── async.rs │ │ ├── async_awt.rs │ │ ├── async_awt_global.rs │ │ ├── async_awt_mut.rs │ │ ├── case_attributes.rs │ │ ├── case_with_wrong_args.rs │ │ ├── description.rs │ │ ├── dump_just_one_case.rs │ │ ├── inject.rs │ │ ├── missed_argument.rs │ │ ├── missed_some_arguments.rs │ │ ├── partial.rs │ │ ├── simple.rs │ │ └── use_attr.rs │ │ ├── context.rs │ │ ├── convert_string_literal.rs │ │ ├── convert_string_literal_other_name.rs │ │ ├── destruct.rs │ │ ├── dump_debug.rs │ │ ├── dump_debug_compact.rs │ │ ├── dump_exclude_some_inputs.rs │ │ ├── dump_exclude_some_inputs_compact.rs │ │ ├── dump_not_debug.rs │ │ ├── dump_not_debug_compact.rs │ │ ├── errors.rs │ │ ├── files.rs │ │ ├── generic.rs │ │ ├── happy_path.rs │ │ ├── ignore_args.rs │ │ ├── ignore_attributes_args_if_any.rs │ │ ├── impl_param.rs │ │ ├── lifetimes.rs │ │ ├── local_lifetime.rs │ │ ├── matrix │ │ ├── async.rs │ │ ├── async_awt.rs │ │ ├── async_awt_global.rs │ │ ├── inject.rs │ │ ├── partial.rs │ │ ├── simple.rs │ │ └── use_attr.rs │ │ ├── mut.rs │ │ ├── no_std.rs │ │ ├── panic.rs │ │ ├── reject_no_item_function.rs │ │ ├── remove_underscore.rs │ │ ├── rename.rs │ │ ├── return_result.rs │ │ ├── single │ │ ├── async.rs │ │ ├── async_awt.rs │ │ ├── async_awt_global.rs │ │ ├── dump_debug.rs │ │ ├── inject.rs │ │ ├── partial.rs │ │ ├── resolve.rs │ │ └── simple.rs │ │ ├── timeout.rs │ │ ├── timeout_async.rs │ │ ├── timeout_other_name.rs │ │ ├── use_mutable_fixture_in_parametric_arguments.rs │ │ └── values_tests_name.rs │ └── rstest │ └── mod.rs ├── rstest_fixtures ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT └── src │ └── lib.rs ├── rstest_macros ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── build.rs └── src │ ├── error.rs │ ├── lib.rs │ ├── parse │ ├── arguments.rs │ ├── by_ref.rs │ ├── context.rs │ ├── expressions.rs │ ├── fixture.rs │ ├── future.rs │ ├── ignore.rs │ ├── just_once.rs │ ├── macros.rs │ ├── mod.rs │ ├── rstest.rs │ ├── rstest │ │ └── files.rs │ ├── testcase.rs │ └── vlist.rs │ ├── refident.rs │ ├── render │ ├── apply_arguments.rs │ ├── crate_resolver.rs │ ├── fixture.rs │ ├── inject.rs │ ├── mod.rs │ ├── test.rs │ └── wrapper.rs │ ├── resolver.rs │ ├── test.rs │ └── utils.rs ├── rstest_reuse ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── checkoutlist.md ├── src │ └── lib.rs └── tests │ ├── acceptance.rs │ └── resources │ ├── copy_args_attributes_from_template.rs │ ├── deny_docs.rs │ ├── export_not_used.rs │ ├── export_template.rs │ ├── export_template_root.rs │ ├── import_template.rs │ ├── in_mod.rs │ ├── no_local_macro_should_not_compile.rs │ ├── not_used.rs │ ├── qualify_template_use.rs │ ├── rstest_reuse_not_in_crate_root.rs │ ├── simple_example.rs │ ├── templates_with_same_name.rs │ └── use_before_define.rs └── rstest_test ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── checkoutlist.md ├── src ├── lib.rs ├── prj.rs └── utils.rs └── tests ├── framework.rs └── macros.rs /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | - package-ecosystem: "docker" 8 | directory: "/" 9 | schedule: 10 | interval: "monthly" 11 | - package-ecosystem: "github-actions" 12 | directory: "/" 13 | schedule: 14 | interval: "monthly" 15 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | schedule: 8 | - cron: '0 6 * * SAT' 9 | pull_request: 10 | branches: 11 | - master 12 | release: 13 | types: # This configuration does not affect the page_build event above 14 | - created 15 | workflow_dispatch: 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Install latest nightly 25 | uses: actions-rs/toolchain@v1 26 | with: 27 | toolchain: nightly 28 | override: true 29 | - name: Install latest beta 30 | uses: actions-rs/toolchain@v1 31 | with: 32 | toolchain: beta 33 | - name: Build 34 | run: cargo build --all --verbose 35 | - name: Run tests stable 36 | run: RSTEST_TEST_CHANNEL=stable cargo test --all --verbose 37 | - name: Run tests beta 38 | run: RSTEST_TEST_CHANNEL=beta cargo test --all --verbose 39 | - name: Run tests nightly 40 | run: RSTEST_TEST_CHANNEL=nightly cargo test --all --verbose 41 | msrv: 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v4 45 | - uses: taiki-e/install-action@cargo-hack 46 | - run: cargo hack check --rust-version --workspace --ignore-private 47 | - run: | 48 | cargo hack test --rust-version --workspace \ 49 | --exclude rstest_reuse --ignore-private \ 50 | -- --skip rstest::ignore_attributes_args_if_any 51 | -------------------------------------------------------------------------------- /.github/workflows/update_head_docs.yml: -------------------------------------------------------------------------------- 1 | name: Update Head Docs 2 | 3 | on: 4 | repository_dispatch: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | build: 9 | 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: Install latest nightly 15 | uses: actions-rs/toolchain@v1 16 | with: 17 | toolchain: nightly 18 | - name: Build Docs 19 | uses: actions-rs/cargo@v1 20 | with: 21 | command: doc 22 | toolchain: nightly 23 | args: --no-deps 24 | - name: Copy docs 25 | run: cp -ra target/doc/* docs/head/ 26 | - name: Commit files 27 | run: | 28 | git config --local user.email "action@github.com" 29 | git config --local user.name "GitHub Action" 30 | git commit -m "Update docs" -a 31 | - name: Push changes 32 | uses: ad-m/github-push-action@master 33 | with: 34 | github_token: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | target 3 | **/*.rs.bk 4 | Cargo.lock 5 | *.iml 6 | .vscode -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/.rustfmt.toml -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Usare IntelliSense per informazioni sui possibili attributi. 3 | // Al passaggio del mouse vengono visualizzate le descrizioni degli attributi esistenti. 4 | // Per altre informazioni, visitare: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug integration test 'acceptance'", 11 | "cargo": { 12 | "args": [ 13 | "test", 14 | "--no-run", 15 | "--test=acceptance", 16 | "--package=rstest_reuse" 17 | ], 18 | "filter": { 19 | "name": "acceptance", 20 | "kind": "test" 21 | } 22 | }, 23 | "args": [], 24 | "cwd": "${workspaceFolder}" 25 | }, 26 | { 27 | "type": "lldb", 28 | "request": "launch", 29 | "name": "Debug unit tests in library 'rstest_test'", 30 | "cargo": { 31 | "args": [ 32 | "test", 33 | "--no-run", 34 | "--lib", 35 | "--package=rstest_test" 36 | ], 37 | "filter": { 38 | "name": "rstest_test", 39 | "kind": "lib" 40 | } 41 | }, 42 | "args": [], 43 | "cwd": "${workspaceFolder}" 44 | }, 45 | { 46 | "type": "lldb", 47 | "request": "launch", 48 | "name": "Debug integration test 'framework'", 49 | "cargo": { 50 | "args": [ 51 | "test", 52 | "--no-run", 53 | "--test=framework", 54 | "--package=rstest_test" 55 | ], 56 | "filter": { 57 | "name": "framework", 58 | "kind": "test" 59 | } 60 | }, 61 | "args": [], 62 | "cwd": "${workspaceFolder}" 63 | }, 64 | { 65 | "type": "lldb", 66 | "request": "launch", 67 | "name": "Debug integration test 'macros'", 68 | "cargo": { 69 | "args": [ 70 | "test", 71 | "--no-run", 72 | "--test=macros", 73 | "--package=rstest_test" 74 | ], 75 | "filter": { 76 | "name": "macros", 77 | "kind": "test" 78 | } 79 | }, 80 | "args": [], 81 | "cwd": "${workspaceFolder}" 82 | }, 83 | { 84 | "type": "lldb", 85 | "request": "launch", 86 | "name": "Debug unit tests in library 'rstest'", 87 | "cargo": { 88 | "args": [ 89 | "test", 90 | "--no-run", 91 | "--lib", 92 | "--package=rstest" 93 | ], 94 | "filter": { 95 | "name": "rstest", 96 | "kind": "lib" 97 | } 98 | }, 99 | "args": [], 100 | "cwd": "${workspaceFolder}" 101 | }, 102 | { 103 | "type": "lldb", 104 | "request": "launch", 105 | "name": "Debug integration test 'integration'", 106 | "cargo": { 107 | "args": [ 108 | "test", 109 | "--no-run", 110 | "--test=integration", 111 | "--package=rstest" 112 | ], 113 | "filter": { 114 | "name": "integration", 115 | "kind": "test" 116 | } 117 | }, 118 | "args": [], 119 | "cwd": "${workspaceFolder}" 120 | } 121 | ] 122 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | exclude = ["playground", "rstest_fixtures"] 4 | members = ["rstest_macros", "rstest", "rstest_test", "rstest_reuse"] 5 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2018-19 Michele d'Amico 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation the 6 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 | sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 15 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 16 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /checkoutlist.md: -------------------------------------------------------------------------------- 1 | # TODO list 2 | 3 | - [ ] Update rustup 4 | - [ ] Run `cargo clippy` 5 | - [ ] Check msrv: 6 | - [ ] `cargo hack check --rust-version --workspace --ignore-private` 7 | - [ ] `cargo hack test --rust-version --workspace --exclude rstest_reuse --ignore-private -- --skip rstest::ignore_args_not_fixtures` 8 | - [ ] Update Release 9 | - [ ] `README.md` 10 | - [ ] Run all test: `for channel in stable beta nightly; do RSTEST_TEST_CHANNEL=${channel} cargo +${channel} test; done` 11 | - [ ] Remove the `-dev` suffix, run `cargo test` after 12 | - [ ] Create docs and checks links 13 | - [ ] Check CHANGELOG: **RELEASE DATE** and remove empty blocks 14 | - [ ] Check README 15 | - [ ] **Commit** 16 | - [ ] Create tag (Use github release) 17 | - [ ] deploy: 18 | - [ ] `cargo publish -p rstest_macros --dry-run` 19 | - [ ] `cargo publish -p rstest_macros` 20 | - [ ] `cargo publish -p rstest --dry-run` 21 | - [ ] `cargo publish -p rstest` 22 | - [ ] Prepare next changelog 23 | - [ ] New `-dev` version 24 | - [ ] Update inner `rstest` reference 25 | -------------------------------------------------------------------------------- /docs/head/.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/.lock -------------------------------------------------------------------------------- /docs/head/COPYRIGHT.txt: -------------------------------------------------------------------------------- 1 | These documentation pages include resources by third parties. This copyright 2 | file applies only to those resources. The following third party resources are 3 | included, and carry their own copyright notices and license terms: 4 | 5 | * Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): 6 | 7 | Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ 8 | with Reserved Font Name Fira Sans. 9 | 10 | Copyright (c) 2014, Telefonica S.A. 11 | 12 | Licensed under the SIL Open Font License, Version 1.1. 13 | See FiraSans-LICENSE.txt. 14 | 15 | * rustdoc.css, main.js, and playpen.js: 16 | 17 | Copyright 2015 The Rust Developers. 18 | Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or 19 | the MIT license (LICENSE-MIT.txt) at your option. 20 | 21 | * normalize.css: 22 | 23 | Copyright (c) Nicolas Gallagher and Jonathan Neal. 24 | Licensed under the MIT license (see LICENSE-MIT.txt). 25 | 26 | * Source Code Pro (SourceCodePro-Regular.ttf.woff, 27 | SourceCodePro-Semibold.ttf.woff, SourceCodePro-It.ttf.woff): 28 | 29 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), 30 | with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark 31 | of Adobe Systems Incorporated in the United States and/or other countries. 32 | 33 | Licensed under the SIL Open Font License, Version 1.1. 34 | See SourceCodePro-LICENSE.txt. 35 | 36 | * Source Serif 4 (SourceSerif4-Regular.ttf.woff, SourceSerif4-Bold.ttf.woff, 37 | SourceSerif4-It.ttf.woff): 38 | 39 | Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 40 | 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United 41 | States and/or other countries. 42 | 43 | Licensed under the SIL Open Font License, Version 1.1. 44 | See SourceSerif4-LICENSE.md. 45 | 46 | This copyright file is intended to be distributed with rustdoc output. 47 | -------------------------------------------------------------------------------- /docs/head/FiraSans-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. 2 | with Reserved Font Name < Fira >, 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: 6 | http://scripts.sil.org/OFL 7 | 8 | 9 | ----------------------------------------------------------- 10 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 11 | ----------------------------------------------------------- 12 | 13 | PREAMBLE 14 | The goals of the Open Font License (OFL) are to stimulate worldwide 15 | development of collaborative font projects, to support the font creation 16 | efforts of academic and linguistic communities, and to provide a free and 17 | open framework in which fonts may be shared and improved in partnership 18 | with others. 19 | 20 | The OFL allows the licensed fonts to be used, studied, modified and 21 | redistributed freely as long as they are not sold by themselves. The 22 | fonts, including any derivative works, can be bundled, embedded, 23 | redistributed and/or sold with any software provided that any reserved 24 | names are not used by derivative works. The fonts and derivatives, 25 | however, cannot be released under any other type of license. The 26 | requirement for fonts to remain under this license does not apply 27 | to any document created using the fonts or their derivatives. 28 | 29 | DEFINITIONS 30 | "Font Software" refers to the set of files released by the Copyright 31 | Holder(s) under this license and clearly marked as such. This may 32 | include source files, build scripts and documentation. 33 | 34 | "Reserved Font Name" refers to any names specified as such after the 35 | copyright statement(s). 36 | 37 | "Original Version" refers to the collection of Font Software components as 38 | distributed by the Copyright Holder(s). 39 | 40 | "Modified Version" refers to any derivative made by adding to, deleting, 41 | or substituting -- in part or in whole -- any of the components of the 42 | Original Version, by changing formats or by porting the Font Software to a 43 | new environment. 44 | 45 | "Author" refers to any designer, engineer, programmer, technical 46 | writer or other person who contributed to the Font Software. 47 | 48 | PERMISSION & CONDITIONS 49 | Permission is hereby granted, free of charge, to any person obtaining 50 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 51 | redistribute, and sell modified and unmodified copies of the Font 52 | Software, subject to the following conditions: 53 | 54 | 1) Neither the Font Software nor any of its individual components, 55 | in Original or Modified Versions, may be sold by itself. 56 | 57 | 2) Original or Modified Versions of the Font Software may be bundled, 58 | redistributed and/or sold with any software, provided that each copy 59 | contains the above copyright notice and this license. These can be 60 | included either as stand-alone text files, human-readable headers or 61 | in the appropriate machine-readable metadata fields within text or 62 | binary files as long as those fields can be easily viewed by the user. 63 | 64 | 3) No Modified Version of the Font Software may use the Reserved Font 65 | Name(s) unless explicit written permission is granted by the corresponding 66 | Copyright Holder. This restriction only applies to the primary font name as 67 | presented to the users. 68 | 69 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 70 | Software shall not be used to promote, endorse or advertise any 71 | Modified Version, except to acknowledge the contribution(s) of the 72 | Copyright Holder(s) and the Author(s) or with their explicit written 73 | permission. 74 | 75 | 5) The Font Software, modified or unmodified, in part or in whole, 76 | must be distributed entirely under this license, and must not be 77 | distributed under any other license. The requirement for fonts to 78 | remain under this license does not apply to any document created 79 | using the Font Software. 80 | 81 | TERMINATION 82 | This license becomes null and void if any of the above conditions are 83 | not met. 84 | 85 | DISCLAIMER 86 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 87 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 88 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 89 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 90 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 91 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 92 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 93 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 94 | OTHER DEALINGS IN THE FONT SOFTWARE. 95 | -------------------------------------------------------------------------------- /docs/head/FiraSans-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/FiraSans-Medium.woff -------------------------------------------------------------------------------- /docs/head/FiraSans-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/FiraSans-Regular.woff -------------------------------------------------------------------------------- /docs/head/LICENSE-MIT.txt: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /docs/head/SourceCodePro-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /docs/head/SourceCodePro-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/SourceCodePro-Regular.woff -------------------------------------------------------------------------------- /docs/head/SourceCodePro-Semibold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/SourceCodePro-Semibold.woff -------------------------------------------------------------------------------- /docs/head/SourceSerifPro-Bold.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/SourceSerifPro-Bold.ttf.woff -------------------------------------------------------------------------------- /docs/head/SourceSerifPro-It.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/SourceSerifPro-It.ttf.woff -------------------------------------------------------------------------------- /docs/head/SourceSerifPro-LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /docs/head/SourceSerifPro-Regular.ttf.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/SourceSerifPro-Regular.ttf.woff -------------------------------------------------------------------------------- /docs/head/aliases.js: -------------------------------------------------------------------------------- 1 | var ALIASES = {}; 2 | ALIASES["rstest"] = {}; 3 | -------------------------------------------------------------------------------- /docs/head/brush.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/head/down-arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/head/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/favicon.ico -------------------------------------------------------------------------------- /docs/head/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ 2 | html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} -------------------------------------------------------------------------------- /docs/head/noscript.css: -------------------------------------------------------------------------------- 1 | #main .attributes{margin-left:0 !important;}#copy-path{display:none;} -------------------------------------------------------------------------------- /docs/head/rstest/all.html: -------------------------------------------------------------------------------- 1 | List of all items in this crate 2 | 3 |

List of all items[] 5 | 6 |

Attribute Macros

7 | -------------------------------------------------------------------------------- /docs/head/rstest/sidebar-items.js: -------------------------------------------------------------------------------- 1 | initSidebarItems({"attr":[["fixture","Define a fixture that you can use in all `rstest`’s test arguments. You should just mark your function as `#[fixture]` and then use it as a test’s argument. Fixture functions can also use other fixtures."],["rstest","The attribute that you should use for your tests. Your annotated function’s arguments can be injected with `[fixture]`s, provided by parametrized cases or by value lists."]]}); -------------------------------------------------------------------------------- /docs/head/rust-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/la10736/rstest/2e28584b03b88edf3c1638e2e28dc2474df92811/docs/head/rust-logo.png -------------------------------------------------------------------------------- /docs/head/search-index.js: -------------------------------------------------------------------------------- 1 | var searchIndex = JSON.parse('{\ 2 | "rstest":{"doc":"This crate will help you to write simpler tests by …","t":[23,23],"n":["fixture","rstest"],"q":["rstest",""],"d":["Define a fixture that you can use in all rstest’s test …","The attribute that you should use for your tests. Your …"],"i":[0,0],"f":[null,null],"p":[]}\ 3 | }'); 4 | if (window.initSearch) {window.initSearch(searchIndex)}; -------------------------------------------------------------------------------- /docs/head/settings.css: -------------------------------------------------------------------------------- 1 | .setting-line{padding:5px;position:relative;}.setting-line>div{display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{opacity:0;position:absolute;}.select-wrapper{float:right;position:relative;height:27px;min-width:25%;}.select-wrapper select{appearance:none;-moz-appearance:none;-webkit-appearance:none;background:none;border:2px solid #ccc;padding-right:28px;width:100%;}.select-wrapper img{pointer-events:none;position:absolute;right:0;bottom:0;background:#ccc;height:100%;width:28px;padding:0px 4px;}.select-wrapper select option{color:initial;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} -------------------------------------------------------------------------------- /docs/head/settings.html: -------------------------------------------------------------------------------- 1 | Rustdoc settings 2 | 3 |

Rustdoc settings

Theme preferences
Use system theme
Preferred dark theme
Preferred light theme
5 |
Auto-hide item contents for large items.
Auto-hide item methods' documentation
Auto-hide trait implementation documentation
Auto-hide implementors of a trait
Directly go to item in search if there is only one result
Show line numbers on code examples
Disable keyboard shortcuts
6 | -------------------------------------------------------------------------------- /docs/head/settings.js: -------------------------------------------------------------------------------- 1 | (function(){function changeSetting(settingName,value){updateLocalStorage("rustdoc-"+settingName,value);switch(settingName){case"preferred-dark-theme":case"preferred-light-theme":case"use-system-theme":updateSystemTheme();break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function setEvents(){onEachLazy(document.getElementsByClassName("slider"),function(elem){var toggle=elem.previousElementSibling;var settingId=toggle.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(document.getElementsByClassName("select-wrapper"),function(elem){var select=elem.getElementsByTagName("select")[0];var settingId=select.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){select.value=settingValue}select.onchange=function(){changeSetting(this.id,this.value)}})}window.addEventListener("DOMContentLoaded",setEvents)})() -------------------------------------------------------------------------------- /docs/head/source-files.js: -------------------------------------------------------------------------------- 1 | var N = null;var sourcesIndex = {}; 2 | sourcesIndex["rstest"] = {"name":"","dirs":[{"name":"parse","files":["expressions.rs","fixture.rs","future.rs","macros.rs","mod.rs","rstest.rs","testcase.rs","vlist.rs"]},{"name":"render","files":["fixture.rs","inject.rs","mod.rs","wrapper.rs"]}],"files":["error.rs","lib.rs","refident.rs","resolver.rs","utils.rs"]}; 3 | createSourceSidebar(); 4 | -------------------------------------------------------------------------------- /docs/head/source-script.js: -------------------------------------------------------------------------------- 1 | (function(){function getCurrentFilePath(){var parts=window.location.pathname.split("/");var rootPathParts=window.rootPath.split("/");for(var i=0,len=rootPathParts.length;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(!window.rootPath.endsWith("/")){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild);var selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}var lineNumbersRegex=/^#?(\d+)(?:-(\d+))?$/;function highlightSourceLines(scrollTo,match){if(typeof match==="undefined"){match=window.location.hash.match(lineNumbersRegex)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(tocur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",function(){var match=window.location.hash.match(lineNumbersRegex);if(match){return highlightSourceLines(false,match)}});onEachLazy(document.getElementsByClassName("line-numbers"),function(el){el.addEventListener("click",handleSourceHighlight)});highlightSourceLines(true);window.createSourceSidebar=createSourceSidebar})() -------------------------------------------------------------------------------- /docs/head/src/rstest/parse/macros.rs.html: -------------------------------------------------------------------------------- 1 | macros.rs - source 2 | 3 |
 1
 5 |  2
 6 |  3
 7 |  4
 8 |  5
 9 |  6
10 |  7
11 |  8
12 |  9
13 | 10
14 | 11
15 | 12
16 | 13
17 | 14
18 | 15
19 | 16
20 | 17
21 | 18
22 | 19
23 | 20
24 | 
25 | macro_rules! wrap_attributes {
26 |     ($ident:ident) => {
27 |         #[derive(Default, Debug, PartialEq, Clone)]
28 |         pub(crate) struct $ident {
29 |             inner: Attributes,
30 |         }
31 | 
32 |         impl From<Attributes> for $ident {
33 |             fn from(inner: Attributes) -> Self {
34 |                 $ident { inner }
35 |             }
36 |         }
37 | 
38 |         impl $ident {
39 |             fn iter(&self) -> impl Iterator<Item = &Attribute> {
40 |                 self.inner.attributes.iter()
41 |             }
42 |         }
43 |     };
44 | }
45 | 
46 |
47 | -------------------------------------------------------------------------------- /docs/head/src/rstest/render/wrapper.rs.html: -------------------------------------------------------------------------------- 1 | wrapper.rs - source 2 | 3 |
 1
 5 |  2
 6 |  3
 7 |  4
 8 |  5
 9 |  6
10 |  7
11 |  8
12 |  9
13 | 10
14 | 11
15 | 12
16 | 13
17 | 14
18 | 15
19 | 16
20 | 17
21 | 18
22 | 19
23 | 
24 | use proc_macro2::TokenStream;
25 | use quote::{quote, ToTokens};
26 | use syn::Ident;
27 | 
28 | pub(crate) trait WrapByModule {
29 |     fn wrap_by_mod(&self, mod_name: &Ident) -> TokenStream;
30 | }
31 | 
32 | impl<T: ToTokens> WrapByModule for T {
33 |     fn wrap_by_mod(&self, mod_name: &Ident) -> TokenStream {
34 |         quote! {
35 |             mod #mod_name {
36 |                 use super::*;
37 | 
38 |                 #self
39 |             }
40 |         }
41 |     }
42 | }
43 | 
44 |
45 | -------------------------------------------------------------------------------- /docs/head/storage.js: -------------------------------------------------------------------------------- 1 | var resourcesSuffix="";var darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");window.mainTheme=document.getElementById("mainThemeStyle");var settingsDataset=(function(){var settingsElement=document.getElementById("default-settings");if(settingsElement===null){return null}var dataset=settingsElement.dataset;if(dataset===undefined){return null}return dataset})();function getSettingValue(settingName){var current=getCurrentValue('rustdoc-'+settingName);if(current!==null){return current}if(settingsDataset!==null){var def=settingsDataset[settingName.replace(/-/g,'_')];if(def!==undefined){return def}}return null}var localStoredTheme=getSettingValue("theme");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed){for(i=length-1;i>=0;--i){if(func(arr[i])){return true}}}else{for(i=0;i=0){updateLocalStorage("rustdoc-preferred-dark-theme",localStoredTheme)}updateSystemTheme()}else{switchTheme(window.currentTheme,window.mainTheme,getSettingValue("theme")||"light",false)} -------------------------------------------------------------------------------- /docs/head/theme.js: -------------------------------------------------------------------------------- 1 | var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="themePicker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="themePicker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["dark","light"].forEach(function(item){var but=document.createElement('button');but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) -------------------------------------------------------------------------------- /docs/head/wheel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /notes.md: -------------------------------------------------------------------------------- 1 | You have to write a file parser. The first test is: 2 | 3 | ```rust 4 | use std::path::{PathBuf, Path}; 5 | 6 | #[derive(Default, Debug, PartialEq)] 7 | struct Matrix { rows: usize, cols: usize, data: Vec } 8 | 9 | impl> From

for Matrix { fn from(_: P) -> Self { Default::default() } } 10 | 11 | fn create_empty_file() -> PathBuf { "".into() } 12 | 13 | #[test] 14 | fn should_parse_empty_file() { 15 | let empty = create_empty_file(); 16 | 17 | let matrix: Matrix = Matrix::from(empty); 18 | 19 | assert_eq!(matrix, Default::default()) 20 | } 21 | ``` 22 | 23 | Ok, `create_empty_file()` should do a lot of job and can be reused in 24 | other tests and fixtures: it's a good candidate to be a fixture. 25 | Let's rewrite previous example by use `rstest`: we'll use `empty` for 26 | fixture instead of `create_empty_file()` because when we use as fixture 27 | will be an object instead an action. 28 | 29 | ```rust 30 | use std::path::{PathBuf, Path}; 31 | 32 | use rstest::*; 33 | 34 | #[derive(Default, Debug, PartialEq)] 35 | struct Matrix { rows: usize, cols: usize, data: Vec } 36 | impl> From

for Matrix { fn from(_: P) -> Self { Default::default() } } 37 | 38 | #[fixture] 39 | fn empty() -> PathBuf { 40 | let path = "empty_file".into(); 41 | std::fs::File::create(&path).expect("Cannot open"); 42 | path 43 | } 44 | 45 | #[rstest] 46 | fn should_parse_empty_file(empty: PathBuf) { 47 | let matrix: Matrix = Matrix::from(empty); 48 | 49 | assert_eq!(matrix, Default::default()) 50 | } 51 | ``` 52 | 53 | Now our `Matrix`'s `From` trait is a little bit more generic and can 54 | take every struct that implement `AsRef` like `PathBuf` do. So we 55 | can generalize our test too: 56 | 57 | ```rust 58 | use std::path::{PathBuf, Path}; 59 | 60 | use rstest::*; 61 | 62 | #[derive(Default, Debug, PartialEq)] 63 | struct Matrix { rows: usize, cols: usize, data: Vec } 64 | 65 | impl> From

for Matrix { fn from(_: P) -> Self { Default::default() } } 66 | 67 | #[rstest] 68 | fn should_parse_empty_file

(empty: P) 69 | where P: AsRef 70 | { 71 | let matrix: Matrix = Matrix::from(empty); 72 | 73 | assert_eq!(matrix, Default::default()) 74 | } 75 | ``` 76 | 77 | Our test is neat and clear but we have a big issue to fix: we cannot 78 | leave `"empty_file"` on our disk, we must remove it we are done! 79 | That is a job for Rust ownership!! 80 | 81 | We should just wrap `PathBuf` in out `TempFile` struct and implement 82 | both `Drop` and `AsRef` traits. We'll use `Drop` to delete it. 83 | 84 | ```rust 85 | use std::path::{PathBuf, Path}; 86 | 87 | use rstest::*; 88 | 89 | struct TempFile(PathBuf); 90 | 91 | impl Drop for TempFile {fn drop(&mut self) { 92 | std::fs::remove_file(&self.0).unwrap(); 93 | } 94 | } 95 | 96 | impl AsRef for TempFile { 97 | fn as_ref(&self) -> &Path { 98 | &self.0 99 | } 100 | } 101 | 102 | #[fixture] 103 | fn empty() -> TempFile { 104 | let path = "empty_file".into(); 105 | std::fs::File::create(&path).expect("Cannot open"); 106 | TempFile(path) 107 | } 108 | -------------------------------------------------------------------------------- /playground/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["michele "] 3 | edition = "2018" 4 | name = "playground" 5 | version = "0.1.0" 6 | 7 | [features] 8 | default = [] 9 | # Depends on nightly 10 | trace_all = [] 11 | 12 | [dependencies] 13 | async-std = { version = "1.13.0", features = ["attributes"] } 14 | lazy_static = "1.4.0" 15 | 16 | [dependencies.rstest] 17 | path = "../rstest" 18 | version = "0.25.0-dev" 19 | 20 | [dependencies.rstest_reuse] 21 | path = "../rstest_reuse" 22 | version = "*" 23 | -------------------------------------------------------------------------------- /playground/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /playground/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /playground/files/myname.txt: -------------------------------------------------------------------------------- 1 | myname.txt 2 | 3 | 4 | something else -------------------------------------------------------------------------------- /playground/files/other: -------------------------------------------------------------------------------- 1 | no test -------------------------------------------------------------------------------- /playground/files/should_fail.txt: -------------------------------------------------------------------------------- 1 | something else 2 | -------------------------------------------------------------------------------- /playground/src/main.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use std::fs::File; 3 | use std::path::PathBuf; 4 | use std::io::Read; 5 | 6 | #[rstest] 7 | fn start_with_name(#[files("files/*.txt")] path: PathBuf) { 8 | let name = path.file_name().unwrap(); 9 | let mut f = File::open(&path).unwrap(); 10 | let mut contents = String::new(); 11 | f.read_to_string(&mut contents).unwrap(); 12 | 13 | assert!(contents.starts_with(name.to_str().unwrap())) 14 | } -------------------------------------------------------------------------------- /rstest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Michele d'Amico "] 3 | categories = ["development-tools::testing"] 4 | description = """ 5 | Rust fixture based test framework. It use procedural macro 6 | to implement fixtures and table based tests. 7 | """ 8 | edition = "2021" 9 | homepage = "https://github.com/la10736/rstest" 10 | keywords = ["test", "fixture"] 11 | license = "MIT OR Apache-2.0" 12 | name = "rstest" 13 | readme = "README.md" 14 | repository = "https://github.com/la10736/rstest" 15 | rust-version = "1.70.0" 16 | version = "0.25.0-dev" 17 | 18 | [features] 19 | async-timeout = [ 20 | "dep:futures-timer", 21 | "dep:futures-util", 22 | "rstest_macros/async-timeout", 23 | ] 24 | crate-name = ["rstest_macros/crate-name"] 25 | default = ["async-timeout", "crate-name"] 26 | 27 | [lib] 28 | 29 | [dependencies] 30 | futures-timer = { version = "3.0.3", optional = true } 31 | futures-util = { version = "0.3.30", optional = true } 32 | rstest_macros = { version = "0.25.0-dev", path = "../rstest_macros", default-features = false } 33 | 34 | [dev-dependencies] 35 | actix-rt = "2.9.0" 36 | async-std = { version = "1.13.0", features = ["attributes"] } 37 | lazy_static = "1.5.0" 38 | macro_rules_attribute = "0.2.0" 39 | mytest = { package = "rstest", version = "0.25.0", default-features = false } 40 | pretty_assertions = "1.4.1" 41 | rstest_reuse = { path = "../rstest_reuse" } 42 | rstest_test = { path = "../rstest_test" } 43 | smol-macros = "0.1.1" 44 | temp_testdir = "0.2.3" 45 | tokio = { version = "1.38.1", features = ["rt", "macros"] } 46 | unindent = "0.2.3" 47 | 48 | [build-dependencies] 49 | rustc_version = "0.4.1" 50 | -------------------------------------------------------------------------------- /rstest/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /rstest/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /rstest/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /rstest/src/context.rs: -------------------------------------------------------------------------------- 1 | /// A test context. 2 | #[non_exhaustive] 3 | pub struct Context { 4 | /// The complete module test path 5 | pub module: &'static str, 6 | /// The test function name 7 | pub name: &'static str, 8 | /// The test description if present 9 | pub description: Option<&'static str>, 10 | /// The cardinal case number if it's a test case 11 | pub case: Option, 12 | /// Start time 13 | pub start: std::time::Instant, 14 | } 15 | 16 | impl Context { 17 | /// Create a new test context. This function set also the start time to the current time. 18 | pub fn new( 19 | module: &'static str, 20 | name: &'static str, 21 | description: Option<&'static str>, 22 | case: Option, 23 | ) -> Self { 24 | Self { 25 | module, 26 | name, 27 | description, 28 | case, 29 | start: std::time::Instant::now(), 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /rstest/src/magic_conversion.rs: -------------------------------------------------------------------------------- 1 | pub struct Magic(pub std::marker::PhantomData); 2 | 3 | pub trait ViaParseDebug<'a, T> { 4 | fn magic_conversion(&self, input: &'a str) -> T; 5 | } 6 | 7 | impl<'a, T> ViaParseDebug<'a, T> for &&Magic 8 | where 9 | T: std::str::FromStr, 10 | T::Err: std::fmt::Debug, 11 | { 12 | fn magic_conversion(&self, input: &'a str) -> T { 13 | T::from_str(input).unwrap() 14 | } 15 | } 16 | 17 | pub trait ViaParse<'a, T> { 18 | fn magic_conversion(&self, input: &'a str) -> T; 19 | } 20 | 21 | impl<'a, T> ViaParse<'a, T> for &Magic 22 | where 23 | T: std::str::FromStr, 24 | { 25 | fn magic_conversion(&self, input: &'a str) -> T { 26 | match T::from_str(input) { 27 | Ok(v) => v, 28 | Err(_) => { 29 | panic!( 30 | "Cannot parse '{}' to get {}", 31 | input, 32 | std::any::type_name::() 33 | ); 34 | } 35 | } 36 | } 37 | } 38 | 39 | pub trait ViaIdent<'a, T> { 40 | fn magic_conversion(&self, input: &'a str) -> T; 41 | } 42 | 43 | impl<'a> ViaIdent<'a, &'a str> for &&Magic<&'a str> { 44 | fn magic_conversion(&self, input: &'a str) -> &'a str { 45 | input 46 | } 47 | } 48 | 49 | #[cfg(test)] 50 | mod test { 51 | use super::*; 52 | use std::str::FromStr; 53 | 54 | #[test] 55 | fn should_return_the_same_slice_string() { 56 | assert_eq!( 57 | "something", 58 | (&&&Magic::<&str>(std::marker::PhantomData)).magic_conversion("something") 59 | ); 60 | } 61 | 62 | #[test] 63 | fn should_parse_via_parse_debug() { 64 | assert_eq!( 65 | 42u32, 66 | (&&&Magic::(std::marker::PhantomData)).magic_conversion("42") 67 | ); 68 | } 69 | 70 | #[test] 71 | fn should_parse_via_parse_no_error_debug() { 72 | struct S(String); 73 | struct E; 74 | impl FromStr for S { 75 | type Err = E; 76 | 77 | fn from_str(s: &str) -> Result { 78 | Ok(S(s.to_owned())) 79 | } 80 | } 81 | 82 | assert_eq!( 83 | "some", 84 | (&&&Magic::(std::marker::PhantomData)) 85 | .magic_conversion("some") 86 | .0 87 | ); 88 | } 89 | 90 | #[test] 91 | #[should_panic(expected = "MyTypeName")] 92 | fn should_show_error() { 93 | struct MyTypeName; 94 | struct E; 95 | impl FromStr for MyTypeName { 96 | type Err = E; 97 | 98 | fn from_str(_s: &str) -> Result { 99 | Err(E) 100 | } 101 | } 102 | (&&&Magic::(std::marker::PhantomData)).magic_conversion(""); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /rstest/tests/integration.rs: -------------------------------------------------------------------------------- 1 | use rstest_test::{sanitize_name, testname, Project}; 2 | 3 | /// Rstest integration tests 4 | mod rstest; 5 | 6 | /// Fixture's integration tests 7 | mod fixture; 8 | 9 | use lazy_static::lazy_static; 10 | 11 | use std::path::{Path, PathBuf}; 12 | use temp_testdir::TempDir; 13 | 14 | lazy_static! { 15 | static ref ROOT_DIR: TempDir = TempDir::default().permanent(); 16 | static ref ROOT_PROJECT: Project = Project::new(ROOT_DIR.as_ref()); 17 | } 18 | 19 | pub fn base_prj() -> Project { 20 | let prj_name = sanitize_name(testname()); 21 | 22 | ROOT_PROJECT.subproject(&prj_name) 23 | } 24 | 25 | pub fn prj() -> Project { 26 | let prj_name = sanitize_name(testname()); 27 | 28 | let prj = ROOT_PROJECT.subproject(&prj_name); 29 | prj.add_local_dependency("rstest"); 30 | prj 31 | } 32 | 33 | pub fn resources>(name: O) -> PathBuf { 34 | Path::new("tests").join("resources").join(name) 35 | } 36 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/async_fixture.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | 3 | use rstest::*; 4 | 5 | #[fixture] 6 | async fn async_u32() -> u32 { 7 | 42 8 | } 9 | 10 | #[fixture] 11 | async fn nest_fixture(#[future] async_u32: u32) -> u32 { 12 | async_u32.await 13 | } 14 | 15 | #[fixture(fortytwo = async { 42 })] 16 | async fn nest_fixture_with_default(#[future] fortytwo: u32) -> u32 { 17 | fortytwo.await 18 | } 19 | 20 | #[rstest] 21 | #[async_std::test] 22 | async fn default_is_async() { 23 | assert_eq!(42, async_u32::default().await); 24 | } 25 | 26 | #[rstest] 27 | #[async_std::test] 28 | async fn use_async_nest_fixture_default(#[future] nest_fixture: u32) { 29 | assert_eq!(42, nest_fixture.await); 30 | } 31 | 32 | #[rstest(nest_fixture(async { 24 }))] 33 | #[async_std::test] 34 | async fn use_async_nest_fixture_injected(#[future] nest_fixture: u32) { 35 | assert_eq!(24, nest_fixture.await); 36 | } 37 | 38 | #[rstest] 39 | #[async_std::test] 40 | async fn use_async_nest_fixture_with_default(#[future] nest_fixture_with_default: u32) { 41 | assert_eq!(42, nest_fixture_with_default.await); 42 | } 43 | 44 | #[rstest] 45 | #[async_std::test] 46 | async fn use_async_fixture(#[future] async_u32: u32) { 47 | assert_eq!(42, async_u32.await); 48 | } 49 | 50 | #[fixture] 51 | async fn async_impl_output() -> impl Read { 52 | std::io::Cursor::new(vec![1, 2, 3, 4, 5]) 53 | } 54 | 55 | #[rstest] 56 | #[async_std::test] 57 | async fn use_async_impl_output(#[future] async_impl_output: T) { 58 | let reader = async_impl_output.await; 59 | } 60 | 61 | #[fixture(four = async { 4 }, two = 2)] 62 | async fn two_args_mix_fixture(#[future] four: u32, two: u32) -> u32 { 63 | four.await * 10 + two 64 | } 65 | 66 | #[rstest] 67 | #[async_std::test] 68 | async fn use_two_args_mix_fixture(#[future] two_args_mix_fixture: u32) { 69 | assert_eq!(42, two_args_mix_fixture.await); 70 | } 71 | 72 | #[rstest(two_args_mix_fixture(async { 5 }))] 73 | #[async_std::test] 74 | async fn use_two_args_mix_fixture_inject_first(#[future] two_args_mix_fixture: u32) { 75 | assert_eq!(52, two_args_mix_fixture.await); 76 | } 77 | 78 | #[rstest(two_args_mix_fixture(async { 3 }, 1))] 79 | #[async_std::test] 80 | async fn use_two_args_mix_fixture_inject_both(#[future] two_args_mix_fixture: u32) { 81 | assert_eq!(31, two_args_mix_fixture.await); 82 | } 83 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/await_complete_fixture.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | 3 | use rstest::*; 4 | 5 | #[fixture] 6 | async fn async_u32() -> u32 { 7 | 42 8 | } 9 | 10 | #[fixture] 11 | #[awt] 12 | async fn nest_fixture(#[future] async_u32: u32) -> u32 { 13 | async_u32 14 | } 15 | 16 | #[fixture] 17 | #[awt] 18 | async fn nest_fixture_with_default( 19 | #[future] 20 | #[default(async { 42 })] 21 | fortytwo: u32, 22 | ) -> u32 { 23 | fortytwo 24 | } 25 | 26 | #[rstest] 27 | #[async_std::test] 28 | async fn default_is_async() { 29 | assert_eq!(42, async_u32::default().await); 30 | } 31 | 32 | #[rstest] 33 | #[async_std::test] 34 | #[awt] 35 | async fn use_async_nest_fixture_default(#[future] nest_fixture: u32) { 36 | assert_eq!(42, nest_fixture); 37 | } 38 | 39 | #[rstest] 40 | #[async_std::test] 41 | #[awt] 42 | async fn use_async_nest_fixture_injected( 43 | #[future] 44 | #[with(async { 24 })] 45 | nest_fixture: u32, 46 | ) { 47 | assert_eq!(24, nest_fixture); 48 | } 49 | 50 | #[rstest] 51 | #[async_std::test] 52 | #[awt] 53 | async fn use_async_nest_fixture_with_default(#[future] nest_fixture_with_default: u32) { 54 | assert_eq!(42, nest_fixture_with_default); 55 | } 56 | 57 | #[rstest] 58 | #[async_std::test] 59 | #[awt] 60 | async fn use_async_fixture(#[future] async_u32: u32) { 61 | assert_eq!(42, async_u32); 62 | } 63 | 64 | #[fixture] 65 | async fn async_impl_output() -> impl Read { 66 | std::io::Cursor::new(vec![1, 2, 3, 4, 5]) 67 | } 68 | 69 | #[rstest] 70 | #[async_std::test] 71 | #[awt] 72 | async fn use_async_impl_output(#[future] async_impl_output: T) { 73 | let reader = async_impl_output; 74 | } 75 | 76 | #[fixture] 77 | #[awt] 78 | async fn two_args_mix_fixture( 79 | #[future] 80 | #[default(async { 4 })] 81 | four: u32, 82 | #[default(2)] two: u32, 83 | ) -> u32 { 84 | four * 10 + two 85 | } 86 | 87 | #[rstest] 88 | #[async_std::test] 89 | #[awt] 90 | async fn use_two_args_mix_fixture(#[future] two_args_mix_fixture: u32) { 91 | assert_eq!(42, two_args_mix_fixture); 92 | } 93 | 94 | #[rstest] 95 | #[async_std::test] 96 | #[awt] 97 | async fn use_two_args_mix_fixture_inject_first( 98 | #[future] 99 | #[with(async { 5 })] 100 | two_args_mix_fixture: u32, 101 | ) { 102 | assert_eq!(52, two_args_mix_fixture); 103 | } 104 | 105 | #[rstest] 106 | #[async_std::test] 107 | #[awt] 108 | async fn use_two_args_mix_fixture_inject_both( 109 | #[future] 110 | #[with(async { 3 }, 1)] 111 | two_args_mix_fixture: u32, 112 | ) { 113 | assert_eq!(31, two_args_mix_fixture); 114 | } 115 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/await_partial_fixture.rs: -------------------------------------------------------------------------------- 1 | use std::io::prelude::*; 2 | 3 | use rstest::*; 4 | 5 | #[fixture] 6 | async fn async_u32() -> u32 { 7 | 42 8 | } 9 | 10 | #[fixture] 11 | async fn nest_fixture(#[future(awt)] async_u32: u32) -> u32 { 12 | async_u32 13 | } 14 | 15 | #[fixture] 16 | async fn nest_fixture_with_default( 17 | #[future(awt)] 18 | #[default(async { 42 })] 19 | fortytwo: u32, 20 | ) -> u32 { 21 | fortytwo 22 | } 23 | 24 | #[rstest] 25 | #[async_std::test] 26 | async fn default_is_async() { 27 | assert_eq!(42, async_u32::default().await); 28 | } 29 | 30 | #[rstest] 31 | #[async_std::test] 32 | async fn use_async_nest_fixture_default(#[future(awt)] nest_fixture: u32) { 33 | assert_eq!(42, nest_fixture); 34 | } 35 | 36 | #[rstest] 37 | #[async_std::test] 38 | async fn use_async_nest_fixture_injected( 39 | #[future(awt)] 40 | #[with(async { 24 })] 41 | nest_fixture: u32, 42 | ) { 43 | assert_eq!(24, nest_fixture); 44 | } 45 | 46 | #[rstest] 47 | #[async_std::test] 48 | async fn use_async_nest_fixture_with_default(#[future(awt)] nest_fixture_with_default: u32) { 49 | assert_eq!(42, nest_fixture_with_default); 50 | } 51 | 52 | #[rstest] 53 | #[async_std::test] 54 | async fn use_async_fixture(#[future(awt)] async_u32: u32) { 55 | assert_eq!(42, async_u32); 56 | } 57 | 58 | #[fixture] 59 | async fn async_impl_output() -> impl Read { 60 | std::io::Cursor::new(vec![1, 2, 3, 4, 5]) 61 | } 62 | 63 | #[rstest] 64 | #[async_std::test] 65 | async fn use_async_impl_output(#[future(awt)] async_impl_output: T) { 66 | let reader = async_impl_output; 67 | } 68 | 69 | #[fixture] 70 | async fn two_args_mix_fixture( 71 | #[future(awt)] 72 | #[default(async { 4 })] 73 | four: u32, 74 | #[default(2)] two: u32, 75 | ) -> u32 { 76 | four * 10 + two 77 | } 78 | 79 | #[rstest] 80 | #[async_std::test] 81 | async fn use_two_args_mix_fixture(#[future(awt)] two_args_mix_fixture: u32) { 82 | assert_eq!(42, two_args_mix_fixture); 83 | } 84 | 85 | #[rstest] 86 | #[async_std::test] 87 | async fn use_two_args_mix_fixture_inject_first( 88 | #[future(awt)] 89 | #[with(async { 5 })] 90 | two_args_mix_fixture: u32, 91 | ) { 92 | assert_eq!(52, two_args_mix_fixture); 93 | } 94 | 95 | #[rstest] 96 | #[async_std::test] 97 | async fn use_two_args_mix_fixture_inject_both( 98 | #[future(awt)] 99 | #[with(async { 3 }, 1)] 100 | two_args_mix_fixture: u32, 101 | ) { 102 | assert_eq!(31, two_args_mix_fixture); 103 | } 104 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/clean_up_default_generics.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn s() -> &'static str { 5 | "42" 6 | } 7 | 8 | #[fixture] 9 | fn fx(s: S) -> usize { 10 | s.to_string().len() 11 | } 12 | 13 | #[fixture] 14 | fn sum() -> usize { 15 | 42 16 | } 17 | 18 | #[fixture] 19 | fn fx_double(sum: usize, s: S) -> usize { 20 | s.to_string().len() + sum 21 | } 22 | 23 | #[test] 24 | fn resolve() { 25 | assert_eq!(2, fx::default()) 26 | } 27 | 28 | #[test] 29 | fn resolve_partial() { 30 | assert_eq!(12, fx_double::partial_1(10)) 31 | } 32 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/default.rs: -------------------------------------------------------------------------------- 1 | use rstest::{fixture, rstest}; 2 | 3 | #[fixture(value = 42)] 4 | pub fn simple(value: u32) -> u32 { 5 | value 6 | } 7 | 8 | #[fixture(value = 21, mult = 2)] 9 | pub fn double(value: u32, mult: u32) -> u32 { 10 | value * mult 11 | } 12 | 13 | #[fixture] 14 | pub fn middle() -> u32 { 15 | 2 16 | } 17 | 18 | #[fixture(value = 21, mult = 4)] 19 | pub fn mixed(value: u32, middle: u32, mult: u32) -> u32 { 20 | value * mult / middle 21 | } 22 | 23 | #[rstest] 24 | fn test_simple(simple: u32) { 25 | assert_eq!(simple, 42) 26 | } 27 | 28 | #[rstest(simple(21))] 29 | fn test_simple_changed(simple: u32) { 30 | assert_eq!(simple, 21) 31 | } 32 | 33 | #[rstest] 34 | fn test_double(double: u32) { 35 | assert_eq!(double, 42) 36 | } 37 | 38 | #[rstest(double(20, 3))] 39 | fn test_double_changed(double: u32) { 40 | assert_eq!(double, 60) 41 | } 42 | 43 | #[rstest] 44 | fn test_mixed(mixed: u32) { 45 | assert_eq!(mixed, 42) 46 | } 47 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/default_conversion.rs: -------------------------------------------------------------------------------- 1 | use rstest::{fixture, rstest}; 2 | use std::net::{Ipv4Addr, SocketAddr}; 3 | 4 | struct MyType(String); 5 | struct E; 6 | impl core::str::FromStr for MyType { 7 | type Err = E; 8 | 9 | fn from_str(s: &str) -> Result { 10 | match s { 11 | "error" => Err(E), 12 | inner => Ok(MyType(inner.to_owned())), 13 | } 14 | } 15 | } 16 | 17 | #[fixture] 18 | fn base(#[default("1.2.3.4")] ip: Ipv4Addr, #[default(r#"8080"#)] port: u16) -> SocketAddr { 19 | SocketAddr::new(ip.into(), port) 20 | } 21 | 22 | #[fixture] 23 | fn fail(#[default("error")] t: MyType) -> MyType { 24 | t 25 | } 26 | 27 | #[fixture] 28 | fn valid(#[default("some")] t: MyType) -> MyType { 29 | t 30 | } 31 | 32 | #[rstest] 33 | fn test_base(base: SocketAddr) { 34 | assert_eq!(base, "1.2.3.4:8080".parse().unwrap()); 35 | } 36 | 37 | #[fixture] 38 | fn byte_array(#[default(b"1234")] some: &[u8]) -> usize { 39 | some.len() 40 | } 41 | 42 | #[rstest] 43 | fn test_byte_array(byte_array: usize) { 44 | assert_eq!(4, byte_array); 45 | } 46 | 47 | #[rstest] 48 | fn test_convert_custom(valid: MyType) {} 49 | 50 | #[rstest] 51 | fn test_fail_conversion(fail: MyType) {} 52 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/default_in_attrs.rs: -------------------------------------------------------------------------------- 1 | use rstest::{fixture, rstest}; 2 | 3 | #[fixture] 4 | pub fn simple(#[default(42)] value: u32) -> u32 { 5 | value 6 | } 7 | 8 | #[fixture] 9 | pub fn double(#[default(20 + 1)] value: u32, #[default(1 + 1)] mult: u32) -> u32 { 10 | value * mult 11 | } 12 | 13 | #[fixture] 14 | pub fn middle() -> u32 { 15 | 2 16 | } 17 | 18 | #[fixture] 19 | pub fn mixed(#[default(21)] value: u32, middle: u32, #[default(2 + 2)] mult: u32) -> u32 { 20 | value * mult / middle 21 | } 22 | 23 | #[rstest] 24 | fn test_simple(simple: u32) { 25 | assert_eq!(simple, 42) 26 | } 27 | 28 | #[rstest(simple(21))] 29 | fn test_simple_changed(simple: u32) { 30 | assert_eq!(simple, 21) 31 | } 32 | 33 | #[rstest] 34 | fn test_double(double: u32) { 35 | assert_eq!(double, 42) 36 | } 37 | 38 | #[rstest(double(20, 3))] 39 | fn test_double_changed(double: u32) { 40 | assert_eq!(double, 60) 41 | } 42 | 43 | #[rstest] 44 | fn test_mixed(mixed: u32) { 45 | assert_eq!(mixed, 42) 46 | } 47 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/defined_return_type.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | pub fn i() -> u32 { 5 | 42 6 | } 7 | 8 | #[fixture] 9 | pub fn j() -> i32 { 10 | -42 11 | } 12 | 13 | #[fixture(::default>::partial_1>)] 14 | pub fn fx(i: I, j: J) -> impl Iterator { 15 | std::iter::once((i, j)) 16 | } 17 | 18 | #[test] 19 | fn resolve() { 20 | assert_eq!((42, -42), fx::default().next().unwrap()) 21 | } 22 | 23 | #[test] 24 | fn resolve_partial() { 25 | assert_eq!((42.0, -42), fx::partial_1(42.0).next().unwrap()) 26 | } 27 | 28 | #[fixture] 29 | #[default(impl Iterator)] 30 | #[partial_1(impl Iterator)] 31 | pub fn fx_attrs(i: I, j: J) -> impl Iterator { 32 | std::iter::once((i, j)) 33 | } 34 | 35 | #[test] 36 | fn resolve_attrs() { 37 | assert_eq!((42, -42), fx_attrs::default().next().unwrap()) 38 | } 39 | 40 | #[test] 41 | fn resolve_partial_attrs() { 42 | assert_eq!((42.0, -42), fx_attrs::partial_1(42.0).next().unwrap()) 43 | } -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/deny_docs.rs: -------------------------------------------------------------------------------- 1 | //! Crate with tests for missing docs. 2 | 3 | #![deny(missing_docs)] 4 | 5 | use rstest::{fixture, rstest}; 6 | 7 | /// Root fixture 8 | #[fixture] 9 | pub fn root() -> u32 { 10 | 21 11 | } 12 | 13 | /// Injection fixture 14 | #[fixture] 15 | pub fn injection(root: u32) -> u32 { 16 | 2 * root 17 | } 18 | 19 | /// Success test 20 | #[rstest] 21 | pub fn success(injection: u32) { 22 | assert_eq!(42, injection); 23 | } 24 | 25 | /// Fail test 26 | #[rstest] 27 | pub fn fail(injection: u32) { 28 | assert_eq!(41, injection); 29 | } 30 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/dyn.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn dyn_box() -> Box> { 5 | Box::new(std::iter::once(42)) 6 | } 7 | 8 | #[fixture] 9 | fn dyn_ref() -> &'static dyn ToString { 10 | &42 11 | } 12 | 13 | #[fixture] 14 | fn dyn_box_resolve(mut dyn_box: Box>) -> i32 { 15 | dyn_box.next().unwrap() 16 | } 17 | 18 | #[fixture] 19 | fn dyn_ref_resolve(dyn_ref: &dyn ToString) -> String { 20 | dyn_ref.to_string() 21 | } 22 | 23 | #[rstest] 24 | fn test_dyn_box(mut dyn_box: Box>) { 25 | assert_eq!(42, dyn_box.next().unwrap()) 26 | } 27 | 28 | #[rstest] 29 | fn test_dyn_ref(dyn_ref: &dyn ToString) { 30 | assert_eq!("42", dyn_ref.to_string()) 31 | } 32 | 33 | #[rstest] 34 | fn test_dyn_box_resolve(dyn_box_resolve: i32) { 35 | assert_eq!(42, dyn_box_resolve) 36 | } 37 | 38 | #[rstest] 39 | fn test_dyn_ref_resolve(dyn_ref_resolve: String) { 40 | assert_eq!("42", dyn_ref_resolve) 41 | } 42 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/errors.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | pub fn fixture() -> u32 { 5 | 42 6 | } 7 | 8 | #[fixture] 9 | fn error_inner(fixture: u32) { 10 | let a: u32 = ""; 11 | } 12 | 13 | #[fixture] 14 | fn error_cannot_resolve_fixture(no_fixture: u32) {} 15 | 16 | #[fixture] 17 | fn error_fixture_wrong_type(fixture: String) {} 18 | 19 | #[fixture(not_a_fixture(24))] 20 | fn error_inject_an_invalid_fixture(fixture: String) {} 21 | 22 | #[fixture] 23 | fn name() -> &'static str { 24 | "name" 25 | } 26 | 27 | #[fixture] 28 | fn f(name: &str) -> String { 29 | name.to_owned() 30 | } 31 | 32 | #[fixture(f("first"), f("second"))] 33 | fn error_inject_a_fixture_more_than_once(f: String) {} 34 | 35 | struct T(u32); 36 | 37 | #[fixture] 38 | fn structed() -> T { 39 | T(42) 40 | } 41 | 42 | #[fixture] 43 | fn structed_injectd(fixture: u32) -> T { 44 | T(fixture) 45 | } 46 | 47 | #[fixture] 48 | fn error_destruct_without_resolve(T(a): T) {} 49 | 50 | #[fixture] 51 | fn error_destruct_without_resolve_also_with(#[with(21)] T(a): T) {} 52 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/errors_once.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | #[once] 5 | async fn error_async_once_fixture() { 6 | } 7 | 8 | #[fixture] 9 | #[once] 10 | fn error_generics_once_fixture() -> T { 11 | 42 12 | } 13 | 14 | #[fixture] 15 | #[once] 16 | fn error_generics_once_fixture() -> impl Iterator { 17 | std::iter::once(42) 18 | } 19 | 20 | #[fixture] 21 | #[once] 22 | fn error_once_fixture_not_sync() -> std::cell::Cell { 23 | std::cell::Cell::new(42) 24 | } 25 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/fixture_struct.rs: -------------------------------------------------------------------------------- 1 | use rstest::fixture; 2 | 3 | trait Mult { 4 | fn mult(&self, n: u32) -> u32; 5 | } 6 | 7 | struct M(u32); 8 | 9 | impl Mult for M { 10 | fn mult(&self, n: u32) -> u32 { 11 | n * self.0 12 | } 13 | } 14 | 15 | #[fixture] 16 | fn my_fixture() -> u32 { 42 } 17 | 18 | #[fixture] 19 | fn multiplier() -> M { 20 | M(2) 21 | } 22 | 23 | #[fixture] 24 | fn my_fixture_injected(my_fixture: u32, multiplier: impl Mult) -> u32 { multiplier.mult(my_fixture) } 25 | 26 | #[test] 27 | fn resolve_new() { 28 | assert_eq!(42, my_fixture::get()); 29 | } 30 | 31 | #[test] 32 | fn resolve_default() { 33 | assert_eq!(42, my_fixture::default()); 34 | } 35 | 36 | #[test] 37 | fn injected_new() { 38 | assert_eq!(63, my_fixture_injected::get(21, M(3))); 39 | } 40 | 41 | #[test] 42 | fn injected_default() { 43 | assert_eq!(84, my_fixture_injected::default()); 44 | } 45 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/from_other_module.rs: -------------------------------------------------------------------------------- 1 | 2 | mod my_mod { 3 | use rstest::{fixture}; 4 | 5 | #[fixture] 6 | pub fn mod_fixture() -> u32 { 42 } 7 | } 8 | 9 | use my_mod::mod_fixture; 10 | 11 | #[test] 12 | fn struct_access() { 13 | assert_eq!(42, mod_fixture::default()); 14 | } 15 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/impl.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn fx_base_impl_return() -> impl Iterator { std::iter::once(42) } 5 | 6 | #[fixture] 7 | fn fx_base_impl_input(mut fx_base_impl_return: impl Iterator) -> u32 { 8 | fx_base_impl_return.next().unwrap() 9 | } 10 | 11 | #[rstest] 12 | fn base_impl_return(mut fx_base_impl_return: impl Iterator) { 13 | assert_eq!(42, fx_base_impl_return.next().unwrap()); 14 | } 15 | 16 | #[rstest] 17 | fn base_impl_input(mut fx_base_impl_input: u32) { 18 | assert_eq!(42, fx_base_impl_input); 19 | } 20 | 21 | #[fixture] 22 | fn fx_nested_impl_return() -> impl Iterator { std::iter::once(42) } 23 | 24 | #[fixture] 25 | fn fx_nested_impl_input(mut fx_nested_impl_return: impl Iterator) -> String { 26 | fx_nested_impl_return.next().unwrap().to_string() 27 | } 28 | 29 | #[rstest] 30 | fn nested_impl_return(mut fx_nested_impl_return: impl Iterator) { 31 | assert_eq!("42", fx_nested_impl_return.next().unwrap().to_string()); 32 | } 33 | 34 | #[rstest] 35 | fn nested_impl_input(mut fx_nested_impl_input: String) { 36 | assert_eq!("42", &fx_nested_impl_input); 37 | } 38 | 39 | #[fixture] 40 | fn fx_nested_multiple_impl_return() -> (impl Iterator, impl ToString) { 41 | (std::iter::once(42), 42i32) 42 | } 43 | 44 | #[fixture] 45 | fn fx_nested_multiple_impl_input(mut fx_nested_multiple_impl_return: (impl Iterator, impl ToString)) -> bool { 46 | fx_nested_multiple_impl_return.0.next().unwrap().to_string() == fx_nested_multiple_impl_return.1.to_string() 47 | } 48 | 49 | #[rstest] 50 | fn nested_multiple_impl_return(mut fx_nested_multiple_impl_return: (impl Iterator, impl ToString)) { 51 | assert_eq!(fx_nested_multiple_impl_return.0.next().unwrap().to_string(), fx_nested_multiple_impl_return.1.to_string()); 52 | } 53 | 54 | #[rstest] 55 | fn nested_multiple_impl_input(fx_nested_multiple_impl_input: bool) { 56 | assert!(fx_nested_multiple_impl_input); 57 | } 58 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/no_warning.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn val() -> i32 { 5 | 21 6 | } 7 | 8 | #[fixture] 9 | fn fortytwo(mut val: i32) -> i32 { 10 | val *= 2; 11 | val 12 | } 13 | 14 | #[rstest] 15 | fn the_test(fortytwo: i32) { 16 | assert_eq!(fortytwo, 42); 17 | } 18 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/once.rs: -------------------------------------------------------------------------------- 1 | use rstest::{fixture, rstest}; 2 | 3 | #[fixture] 4 | #[once] 5 | fn once_fixture() -> u32 { 6 | eprintln!("Exec fixture() just once"); 7 | 42 8 | } 9 | 10 | #[rstest] 11 | fn base(once_fixture: &u32) { 12 | assert_eq!(&42, once_fixture); 13 | } 14 | 15 | #[rstest] 16 | #[case(2)] 17 | #[case(3)] 18 | #[case(7)] 19 | fn cases(once_fixture: &u32, #[case] divisor: u32) { 20 | assert_eq!(0, *once_fixture % divisor); 21 | } 22 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/once_defined_type.rs: -------------------------------------------------------------------------------- 1 | use rstest::{fixture, rstest}; 2 | 3 | #[fixture] 4 | #[default(u32)] 5 | #[partial_1(u32)] 6 | #[once] 7 | fn once_fixture(#[default(())] a: (), #[default(())] b: ()) -> u32 { 8 | eprintln!("Exec fixture() just once"); 9 | 42 10 | } 11 | 12 | #[rstest] 13 | fn base(once_fixture: &u32) { 14 | assert_eq!(&42, once_fixture); 15 | } 16 | 17 | #[rstest] 18 | fn base_partial(#[with(())] once_fixture: &u32) { 19 | assert_eq!(&42, once_fixture); 20 | } 21 | 22 | #[rstest] 23 | fn base_complete(#[with((), ())] once_fixture: &u32) { 24 | assert_eq!(&42, once_fixture); 25 | } 26 | 27 | #[rstest] 28 | #[case(2)] 29 | #[case(3)] 30 | #[case(7)] 31 | fn cases(once_fixture: &u32, #[case] divisor: u32) { 32 | assert_eq!(0, *once_fixture % divisor); 33 | } 34 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/once_no_return.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | #[once] 5 | fn once_fixture() { 6 | eprintln!("Exec fixture() just once"); 7 | } 8 | 9 | #[rstest] 10 | fn base(_once_fixture: ()) { 11 | assert!(true); 12 | } 13 | 14 | #[rstest] 15 | #[case()] 16 | #[case()] 17 | #[case()] 18 | fn cases(_once_fixture: ()) { 19 | assert!(true); 20 | } 21 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/partial.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn f1() -> u32 { 0 } 5 | #[fixture] 6 | fn f2() -> u32 { 0 } 7 | #[fixture] 8 | fn f3() -> u32 { 0 } 9 | 10 | #[fixture] 11 | fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { f1 + 10 * f2 + 100 * f3 } 12 | 13 | #[fixture(fixture(7))] 14 | fn partial_1(fixture: u32) -> u32 { fixture } 15 | 16 | #[fixture(fixture(2, 4))] 17 | fn partial_2(fixture: u32) -> u32 { fixture } 18 | 19 | #[fixture(fixture(2, 4, 5))] 20 | fn complete(fixture: u32) -> u32 { fixture } 21 | 22 | #[rstest] 23 | fn default(fixture: u32) { 24 | assert_eq!(fixture, 0); 25 | } 26 | 27 | #[rstest] 28 | fn t_partial_1(partial_1: u32) { 29 | assert_eq!(partial_1, 7); 30 | } 31 | 32 | #[rstest] 33 | fn t_partial_2(partial_2: u32) { 34 | assert_eq!(partial_2, 42); 35 | } 36 | 37 | #[rstest] 38 | fn t_complete(complete: u32) { 39 | assert_eq!(complete, 542); 40 | } 41 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/partial_in_attr.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn f1() -> u32 { 5 | 0 6 | } 7 | #[fixture] 8 | fn f2() -> u32 { 9 | 0 10 | } 11 | #[fixture] 12 | fn f3() -> u32 { 13 | 0 14 | } 15 | 16 | #[fixture] 17 | fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { 18 | f1 + 10 * f2 + 100 * f3 19 | } 20 | 21 | #[fixture] 22 | fn partial_1(#[with(7)] fixture: u32) -> u32 { 23 | fixture 24 | } 25 | 26 | #[fixture] 27 | fn partial_2(#[with(2, 4)] fixture: u32) -> u32 { 28 | fixture 29 | } 30 | 31 | #[fixture] 32 | fn complete(#[with(2, 4, 5)] fixture: u32) -> u32 { 33 | fixture 34 | } 35 | 36 | #[rstest] 37 | fn default(fixture: u32) { 38 | assert_eq!(fixture, 0); 39 | } 40 | 41 | #[rstest] 42 | fn t_partial_1(partial_1: u32) { 43 | assert_eq!(partial_1, 7); 44 | } 45 | 46 | #[rstest] 47 | fn t_partial_2(partial_2: u32) { 48 | assert_eq!(partial_2, 42); 49 | } 50 | 51 | #[rstest] 52 | fn t_complete(complete: u32) { 53 | assert_eq!(complete, 542); 54 | } 55 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/rename.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn very_long_and_boring_name(#[default(42)] inject: u32) -> u32 { 5 | inject 6 | } 7 | 8 | mod sub_module { 9 | use super::*; 10 | 11 | #[fixture] 12 | pub fn mod_fixture() -> u32 { 13 | 42 14 | } 15 | } 16 | 17 | #[fixture(very_long_and_boring_name as foo)] 18 | fn compact(foo: u32) -> u32 { 19 | foo 20 | } 21 | 22 | #[fixture(very_long_and_boring_name(21) as foo)] 23 | fn compact_injected(foo: u32) -> u32 { 24 | foo 25 | } 26 | 27 | #[fixture(sub_module::mod_fixture as foo)] 28 | fn compact_from_mod(foo: u32) -> u32 { 29 | foo 30 | } 31 | 32 | #[fixture] 33 | fn attribute(#[from(very_long_and_boring_name)] foo: u32) -> u32 { 34 | foo 35 | } 36 | 37 | #[fixture] 38 | fn attribute_mod(#[from(sub_module::mod_fixture)] foo: u32) -> u32 { 39 | foo 40 | } 41 | 42 | #[fixture] 43 | fn attribute_injected( 44 | #[from(very_long_and_boring_name)] 45 | #[with(21)] 46 | foo: u32, 47 | ) -> u32 { 48 | foo 49 | } 50 | 51 | #[rstest] 52 | fn test( 53 | compact: u32, 54 | attribute: u32, 55 | attribute_mod: u32, 56 | compact_from_mod: u32, 57 | compact_injected: u32, 58 | attribute_injected: u32, 59 | ) { 60 | assert_eq!(compact, attribute); 61 | assert_eq!(attribute, attribute_mod); 62 | assert_eq!(attribute_mod, compact_from_mod); 63 | assert_eq!(compact_injected, attribute_injected); 64 | } 65 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/resolve.rs: -------------------------------------------------------------------------------- 1 | use rstest::{rstest, fixture}; 2 | 3 | pub trait Tr { 4 | fn get() -> Self; 5 | } 6 | 7 | impl Tr for i32 { 8 | fn get() -> Self { 9 | 42 10 | } 11 | } 12 | 13 | impl Tr for u32 { 14 | fn get() -> Self { 15 | 42 16 | } 17 | } 18 | 19 | #[fixture] 20 | pub fn f() -> T { 21 | T::get() 22 | } 23 | 24 | #[fixture] 25 | pub fn fu32(f: u32) -> u32 { 26 | f 27 | } 28 | 29 | #[fixture] 30 | pub fn fi32(f: i32) -> i32 { 31 | f 32 | } 33 | 34 | #[rstest] 35 | fn test_u32(fu32: u32) { 36 | assert_eq!(fu32, 42) 37 | } 38 | 39 | #[rstest] 40 | fn test_i32(fi32: i32) { 41 | assert_eq!(fi32, 42) 42 | } 43 | -------------------------------------------------------------------------------- /rstest/tests/resources/fixture/simple_injection.rs: -------------------------------------------------------------------------------- 1 | use rstest::{rstest, fixture}; 2 | 3 | #[fixture] 4 | fn root() -> u32 { 21 } 5 | 6 | #[fixture] 7 | fn injection(root: u32) -> u32 { 2 * root } 8 | 9 | #[rstest] 10 | fn success(injection: u32) { 11 | assert_eq!(42, injection); 12 | } 13 | 14 | #[rstest] 15 | fn fail(injection: u32) { 16 | assert_eq!(41, injection); 17 | } 18 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/by_ref.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use std::fs::File; 3 | use std::io::Read; 4 | use std::path::PathBuf; 5 | 6 | #[rstest] 7 | fn start_with_name( 8 | #[files("files/**/*.txt")] 9 | #[by_ref] 10 | path: &PathBuf, 11 | ) { 12 | let name = path.file_name().unwrap(); 13 | let mut f = File::open(&path).unwrap(); 14 | let mut contents = String::new(); 15 | f.read_to_string(&mut contents).unwrap(); 16 | 17 | assert!(contents.starts_with(name.to_str().unwrap())) 18 | } 19 | 20 | #[fixture] 21 | fn f() -> u32 { 22 | 42 23 | } 24 | 25 | #[rstest] 26 | #[case(42)] 27 | fn test( 28 | #[by_ref] f: &u32, 29 | #[case] 30 | #[by_ref] 31 | c: &u32, 32 | #[values(42, 142)] 33 | #[by_ref] 34 | v: &u32, 35 | ) { 36 | assert_eq!(f, c); 37 | assert_eq!(*c, *v % 100); 38 | } 39 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/args_with_no_cases.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest(one, two, three)] 4 | fn should_show_error_for_no_case(one: u32, two: u32, three: u32) {} 5 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/async.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[case::pass(42, async { 42 })] 5 | #[case::fail(42, async { 41 })] 6 | #[should_panic] 7 | #[case::pass_panic(42, async { 41 })] 8 | #[should_panic] 9 | #[case::fail_panic(42, async { 42 })] 10 | #[async_std::test] 11 | async fn my_async_test( 12 | #[case] expected: u32, 13 | #[case] 14 | #[future] 15 | value: u32, 16 | ) { 17 | assert_eq!(expected, value.await); 18 | } 19 | 20 | #[rstest] 21 | #[case::pass(42, async { 42 })] 22 | #[async_std::test] 23 | async fn my_async_test_revert( 24 | #[case] expected: u32, 25 | #[future] 26 | #[case] 27 | value: u32, 28 | ) { 29 | assert_eq!(expected, value.await); 30 | } 31 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/async_awt.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[case::pass(42, async { 42 })] 5 | #[case::fail(42, async { 41 })] 6 | #[should_panic] 7 | #[case::pass_panic(42, async { 41 })] 8 | #[should_panic] 9 | #[case::fail_panic(42, async { 42 })] 10 | #[async_std::test] 11 | async fn my_async_test( 12 | #[case] expected: u32, 13 | #[case] 14 | #[future(awt)] 15 | value: u32, 16 | ) { 17 | assert_eq!(expected, value); 18 | } 19 | 20 | #[rstest] 21 | #[case::pass(42, async { 42 })] 22 | #[async_std::test] 23 | async fn my_async_test_revert( 24 | #[case] expected: u32, 25 | #[future(awt)] 26 | #[case] 27 | value: u32, 28 | ) { 29 | assert_eq!(expected, value); 30 | } 31 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/async_awt_global.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[case::pass(42, async { 42 })] 5 | #[case::fail(42, async { 41 })] 6 | #[should_panic] 7 | #[case::pass_panic(42, async { 41 })] 8 | #[should_panic] 9 | #[case::fail_panic(42, async { 42 })] 10 | #[awt] 11 | #[async_std::test] 12 | async fn my_async_test( 13 | #[case] expected: u32, 14 | #[case] 15 | #[future] 16 | value: u32, 17 | ) { 18 | assert_eq!(expected, value); 19 | } 20 | 21 | #[rstest] 22 | #[case::pass(42, async { 42 })] 23 | #[awt] 24 | #[async_std::test] 25 | async fn my_async_test_revert( 26 | #[case] expected: u32, 27 | #[future] 28 | #[case] 29 | value: u32, 30 | ) { 31 | assert_eq!(expected, value); 32 | } 33 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/async_awt_mut.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[case::pass(async { 3 })] 5 | #[awt] 6 | #[async_std::test] 7 | async fn my_mut_test_global_awt( 8 | #[future] 9 | #[case] 10 | mut a: i32, 11 | ) { 12 | a = 4; 13 | assert_eq!(a, 4); 14 | } 15 | 16 | #[rstest] 17 | #[case::pass(async { 3 })] 18 | #[async_std::test] 19 | async fn my_mut_test_local_awt( 20 | #[future(awt)] 21 | #[case] 22 | mut a: i32, 23 | ) { 24 | a = 4; 25 | assert_eq!(a, 4); 26 | } 27 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/case_attributes.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest( 4 | val, 5 | case::no_panic(0), 6 | #[should_panic] 7 | case::panic(2), 8 | #[should_panic(expected="expected")] 9 | case::panic_with_message(3), 10 | case::no_panic_but_fail(1), 11 | #[should_panic] 12 | case::panic_but_fail(0), 13 | #[should_panic(expected="other")] 14 | case::panic_with_wrong_message(3), 15 | )] 16 | fn attribute_per_case(val: i32) { 17 | match val { 18 | 0 => assert!(true), 19 | 1 => assert!(false), 20 | 2 => panic!("No catch"), 21 | 3 => panic!("expected"), 22 | _ => panic!("Not defined"), 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/case_with_wrong_args.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[cfg(test)] 4 | #[rstest(a, b, case(42), case(1, 2), case(43))] 5 | fn error_less_arguments(a: u32, b: u32) {} 6 | 7 | #[cfg(test)] 8 | #[rstest(a, case(42, 43), case(12), case(24, 34))] 9 | fn error_too_much_arguments(a: u32) {} 10 | 11 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/description.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest( 4 | expected, 5 | case::user_test_description(true), 6 | case(true), 7 | case::user_test_description_fail(false) 8 | )] 9 | fn description(expected: bool) { 10 | assert!(expected); 11 | } 12 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/dump_just_one_case.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[case::first_no_dump("Please don't trace me")] 5 | #[trace] 6 | #[case::dump_me("Trace it!")] 7 | #[case::last_no_dump("Please don't trace me")] 8 | fn cases(#[case] s: &str) { 9 | assert!(false); 10 | } 11 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/inject.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use actix_rt; 3 | use std::future::Future; 4 | 5 | #[rstest(expected, value, 6 | case::pass(42, 42), 7 | #[should_panic] 8 | case::panic(41, 42), 9 | case::fail(1, 42) 10 | )] 11 | #[test] 12 | fn sync(expected: u32, value: u32) { assert_eq!(expected, value); } 13 | 14 | #[rstest(expected, value, 15 | case::pass(42, async { 42 }), 16 | #[should_panic] 17 | case::panic(41, async { 42 }), 18 | case::fail(1, async { 42 }) 19 | )] 20 | #[actix_rt::test] 21 | async fn fn_async(expected: u32, value: impl Future) { assert_eq!(expected, value.await); } 22 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/missed_argument.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[cfg(test)] 4 | #[rstest(f, case(42), case(24))] 5 | fn error_param_not_exist() {} 6 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/missed_some_arguments.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[cfg(test)] 4 | #[rstest(a,b,c, case(1,2,3), case(3,2,1))] 5 | fn error_param_not_exist(b: u32) {} 6 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/partial.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn f1() -> u32 { 5 | 0 6 | } 7 | #[fixture] 8 | fn f2() -> u32 { 9 | 0 10 | } 11 | #[fixture] 12 | fn f3() -> u32 { 13 | 0 14 | } 15 | 16 | #[fixture] 17 | fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { 18 | f1 + 10 * f2 + 100 * f3 19 | } 20 | 21 | #[rstest(expected, case(0), case(1000))] 22 | fn default(fixture: u32, expected: u32) { 23 | assert_eq!(fixture, expected); 24 | } 25 | 26 | #[rstest(fixture(7), expected, case(7), case(1000))] 27 | fn partial_1(fixture: u32, expected: u32) { 28 | assert_eq!(fixture, expected); 29 | } 30 | 31 | #[rstest(expected, case(7), case(1000))] 32 | fn partial_attr_1(#[with(7)] fixture: u32, expected: u32) { 33 | assert_eq!(fixture, expected); 34 | } 35 | 36 | #[rstest(fixture(2, 4), expected, case(42), case(1000))] 37 | fn partial_2(fixture: u32, expected: u32) { 38 | assert_eq!(fixture, expected); 39 | } 40 | 41 | #[rstest(expected, case(42), case(1000))] 42 | fn partial_attr_2(#[with(2, 4)] fixture: u32, expected: u32) { 43 | assert_eq!(fixture, expected); 44 | } 45 | 46 | #[rstest(fixture(2, 4, 5), expected, case(542), case(1000))] 47 | fn complete(fixture: u32, expected: u32) { 48 | assert_eq!(fixture, expected); 49 | } 50 | 51 | #[rstest(expected, case(542), case(1000))] 52 | fn complete_attr(#[with(2, 4, 5)] fixture: u32, expected: u32) { 53 | assert_eq!(fixture, expected); 54 | } 55 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/simple.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest( 4 | expected, input, 5 | case(4, "ciao"), 6 | case(3, "Foo") 7 | )] 8 | fn strlen_test(expected: usize, input: &str) { 9 | assert_eq!(expected, input.len()); 10 | } 11 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/cases/use_attr.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest] 4 | #[case::ciao(4, "ciao")] 5 | #[should_panic] 6 | #[case::panic(42, "Foo")] 7 | #[case::foo(3, "Foo")] 8 | fn all(#[case] expected: usize, #[case] input: &str) { 9 | assert_eq!(expected, input.len()); 10 | } 11 | 12 | #[rstest(expected, input)] 13 | #[case::ciao(4, "ciao")] 14 | #[case::foo(3, "Foo")] 15 | #[should_panic] 16 | #[case::panic(42, "Foo")] 17 | fn just_cases(expected: usize, input: &str) { 18 | assert_eq!(expected, input.len()); 19 | } 20 | 21 | #[rstest( 22 | case::ciao(4, "ciao"), 23 | case::foo(3, "Foo"), 24 | #[should_panic] 25 | case::panic(42, "Foo"), 26 | )] 27 | fn just_args(#[case] expected: usize, #[case] input: &str) { 28 | assert_eq!(expected, input.len()); 29 | } 30 | 31 | #[rstest] 32 | #[case(0, "ciao")] 33 | #[case(0, "Foo")] 34 | #[should_panic] 35 | fn all_panic(#[case] expected: usize, #[case] input: &str) { 36 | assert_eq!(expected, input.len()); 37 | } 38 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/context.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[case::description(42)] 5 | fn with_case(#[context] ctx: Context, #[case] _c: u32) { 6 | assert_eq!("with_case", ctx.name); 7 | assert_eq!(Some("description"), ctx.description); 8 | assert_eq!(Some(0), ctx.case); 9 | } 10 | 11 | #[rstest] 12 | fn without_case(#[context] ctx: Context) { 13 | assert_eq!("without_case", ctx.name); 14 | assert_eq!(None, ctx.description); 15 | assert_eq!(None, ctx.case); 16 | } 17 | 18 | mod first { 19 | mod inner { 20 | use rstest::*; 21 | 22 | #[rstest] 23 | fn test(#[context] ctx: Context) { 24 | assert!(ctx.module.ends_with("first::inner")); 25 | } 26 | } 27 | } 28 | 29 | #[rstest] 30 | fn measure_time(#[context] ctx: Context) { 31 | std::thread::sleep(std::time::Duration::from_millis(100)); 32 | assert!(ctx.start.elapsed() >= std::time::Duration::from_millis(100)); 33 | } 34 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/convert_string_literal.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use std::net::SocketAddr; 3 | 4 | #[rstest] 5 | #[case(true, "1.2.3.4:42")] 6 | #[case(true, r#"4.3.2.1:24"#)] 7 | #[case(false, "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443")] 8 | #[case(false, r#"[2aa1:db8:85a3:8af:1319:8a2e:375:4873]:344"#)] 9 | #[case(false, "this.is.not.a.socket.address")] 10 | #[case(false, r#"this.is.not.a.socket.address"#)] 11 | fn cases(#[case] expected: bool, #[case] addr: SocketAddr) { 12 | assert_eq!(expected, addr.is_ipv4()); 13 | } 14 | 15 | #[rstest] 16 | fn values( 17 | #[values( 18 | "1.2.3.4:42", 19 | r#"4.3.2.1:24"#, 20 | "this.is.not.a.socket.address", 21 | r#"this.is.not.a.socket.address"# 22 | )] 23 | addr: SocketAddr, 24 | ) { 25 | assert!(addr.is_ipv4()) 26 | } 27 | 28 | #[rstest] 29 | #[case(b"12345")] 30 | fn not_convert_byte_array(#[case] cases: &[u8], #[values(b"abc")] values: &[u8]) { 31 | assert_eq!(5, cases.len()); 32 | assert_eq!(3, values.len()); 33 | } 34 | 35 | trait MyTrait { 36 | fn my_trait(&self) -> u32 { 37 | 42 38 | } 39 | } 40 | 41 | impl MyTrait for &str {} 42 | 43 | #[rstest] 44 | #[case("impl", "nothing")] 45 | fn not_convert_impl(#[case] that_impl: impl MyTrait, #[case] s: &str) { 46 | assert_eq!(42, that_impl.my_trait()); 47 | assert_eq!(42, s.my_trait()); 48 | } 49 | 50 | #[rstest] 51 | #[case("1.2.3.4", "1.2.3.4:42")] 52 | #[case("1.2.3.4".to_owned(), "1.2.3.4:42")] 53 | fn not_convert_generics>(#[case] ip: S, #[case] addr: SocketAddr) { 54 | assert_eq!(addr.ip().to_string(), ip.as_ref()); 55 | } 56 | 57 | struct MyType(String); 58 | struct E; 59 | impl core::str::FromStr for MyType { 60 | type Err = E; 61 | 62 | fn from_str(s: &str) -> Result { 63 | match s { 64 | "error" => Err(E), 65 | inner => Ok(MyType(inner.to_owned())), 66 | } 67 | } 68 | } 69 | 70 | #[rstest] 71 | #[case("hello", "hello")] 72 | #[case("doesn't mater", "error")] 73 | fn convert_without_debug(#[case] expected: &str, #[case] converted: MyType) { 74 | assert_eq!(expected, converted.0); 75 | } 76 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/convert_string_literal_other_name.rs: -------------------------------------------------------------------------------- 1 | use other_name::*; 2 | use std::net::SocketAddr; 3 | 4 | #[rstest] 5 | #[case(true, "1.2.3.4:42")] 6 | #[case(true, r#"4.3.2.1:24"#)] 7 | #[case(false, "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443")] 8 | #[case(false, r#"[2aa1:db8:85a3:8af:1319:8a2e:375:4873]:344"#)] 9 | #[case(false, "this.is.not.a.socket.address")] 10 | #[case(false, r#"this.is.not.a.socket.address"#)] 11 | fn cases(#[case] expected: bool, #[case] addr: SocketAddr) { 12 | assert_eq!(expected, addr.is_ipv4()); 13 | } 14 | 15 | #[rstest] 16 | fn values( 17 | #[values( 18 | "1.2.3.4:42", 19 | r#"4.3.2.1:24"#, 20 | "this.is.not.a.socket.address", 21 | r#"this.is.not.a.socket.address"# 22 | )] 23 | addr: SocketAddr, 24 | ) { 25 | assert!(addr.is_ipv4()) 26 | } 27 | 28 | #[rstest] 29 | #[case(b"12345")] 30 | fn not_convert_byte_array(#[case] cases: &[u8], #[values(b"abc")] values: &[u8]) { 31 | assert_eq!(5, cases.len()); 32 | assert_eq!(3, values.len()); 33 | } 34 | 35 | trait MyTrait { 36 | fn my_trait(&self) -> u32 { 37 | 42 38 | } 39 | } 40 | 41 | impl MyTrait for &str {} 42 | 43 | #[rstest] 44 | #[case("impl", "nothing")] 45 | fn not_convert_impl(#[case] that_impl: impl MyTrait, #[case] s: &str) { 46 | assert_eq!(42, that_impl.my_trait()); 47 | assert_eq!(42, s.my_trait()); 48 | } 49 | 50 | #[rstest] 51 | #[case("1.2.3.4", "1.2.3.4:42")] 52 | #[case("1.2.3.4".to_owned(), "1.2.3.4:42")] 53 | fn not_convert_generics>(#[case] ip: S, #[case] addr: SocketAddr) { 54 | assert_eq!(addr.ip().to_string(), ip.as_ref()); 55 | } 56 | 57 | struct MyType(String); 58 | struct E; 59 | impl core::str::FromStr for MyType { 60 | type Err = E; 61 | 62 | fn from_str(s: &str) -> Result { 63 | match s { 64 | "error" => Err(E), 65 | inner => Ok(MyType(inner.to_owned())), 66 | } 67 | } 68 | } 69 | 70 | #[rstest] 71 | #[case("hello", "hello")] 72 | #[case("doesn't mater", "error")] 73 | fn convert_without_debug(#[case] expected: &str, #[case] converted: MyType) { 74 | assert_eq!(expected, converted.0); 75 | } 76 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/destruct.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | struct T { 4 | a: u32, 5 | b: u32, 6 | } 7 | 8 | impl T { 9 | fn new(a: u32, b: u32) -> Self { 10 | Self { a, b } 11 | } 12 | } 13 | 14 | struct S(u32, u32); 15 | 16 | #[fixture] 17 | fn fix() -> T { 18 | T::new(1, 42) 19 | } 20 | 21 | #[fixture] 22 | fn named() -> S { 23 | S(1, 42) 24 | } 25 | 26 | #[fixture] 27 | fn tuple() -> (u32, u32) { 28 | (1, 42) 29 | } 30 | 31 | #[fixture] 32 | fn swap(#[from(fix)] T { a, b }: T) -> T { 33 | T::new(b, a) 34 | } 35 | 36 | #[rstest] 37 | fn swapped(#[from(swap)] T { a, b }: T) { 38 | assert_eq!(a, 42); 39 | assert_eq!(b, 1); 40 | } 41 | 42 | #[rstest] 43 | #[case::two_times_twenty_one(T::new(2, 21))] 44 | #[case::six_times_seven(T{ a: 6, b: 7 })] 45 | fn cases_destruct( 46 | #[from(fix)] T { a, b }: T, 47 | #[case] T { a: c, b: d }: T, 48 | #[values(T::new(42, 1), T{ a: 3, b: 14})] T { a: e, b: f }: T, 49 | ) { 50 | assert_eq!(a * b, 42); 51 | assert_eq!(c * d, 42); 52 | assert_eq!(e * f, 42); 53 | } 54 | 55 | #[rstest] 56 | #[case::two_times_twenty_one(S(2, 21))] 57 | #[case::six_times_seven(S(6, 7))] 58 | fn cases_destruct_named_tuple( 59 | #[from(named)] S(a, b): S, 60 | #[case] S(c, d): S, 61 | #[values(S(42, 1), S(3, 14))] S(e, f): S, 62 | ) { 63 | assert_eq!(a * b, 42); 64 | assert_eq!(c * d, 42); 65 | assert_eq!(e * f, 42); 66 | } 67 | 68 | #[rstest] 69 | #[case::two_times_twenty_one((2, 21))] 70 | #[case::six_times_seven((6, 7))] 71 | fn cases_destruct_tuple( 72 | #[from(tuple)] (a, b): (u32, u32), 73 | #[case] (c, d): (u32, u32), 74 | #[values((42, 1), (3, 14))] (e, f): (u32, u32), 75 | ) { 76 | assert_eq!(a * b, 42); 77 | assert_eq!(c * d, 42); 78 | assert_eq!(e * f, 42); 79 | } 80 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/dump_debug.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[derive(Debug)] 4 | struct A {} 5 | 6 | #[fixture] 7 | fn fu32() -> u32 { 8 | 42 9 | } 10 | #[fixture] 11 | fn fstring() -> String { 12 | "A String".to_string() 13 | } 14 | #[fixture] 15 | fn ftuple() -> (A, String, i32) { 16 | (A {}, "A String".to_string(), -12) 17 | } 18 | 19 | #[rstest] 20 | #[trace] 21 | fn single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { 22 | assert!(false); 23 | } 24 | 25 | #[rstest] 26 | fn no_trace_single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { 27 | assert!(false); 28 | } 29 | 30 | #[rstest] 31 | #[case(42, "str", ("ss", -12))] 32 | #[case(24, "trs", ("tt", -24))] 33 | #[trace] 34 | fn cases_fail(#[case] u: u32, #[case] s: &str, #[case] t: (&str, i32)) { 35 | assert!(false); 36 | } 37 | 38 | #[rstest] 39 | #[case(42, "str", ("ss", -12))] 40 | #[case(24, "trs", ("tt", -24))] 41 | fn no_trace_cases_fail(#[case] u: u32, #[case] s: &str, #[case] t: (&str, i32)) { 42 | assert!(false); 43 | } 44 | 45 | #[rstest] 46 | #[trace] 47 | fn matrix_fail( 48 | #[values(1, 3)] u: u32, 49 | #[values("rst", "srt")] s: &str, 50 | #[values(("SS", -12), ("TT", -24))] t: (&str, i32), 51 | ) { 52 | assert!(false); 53 | } 54 | 55 | #[rstest] 56 | fn no_trace_matrix_fail( 57 | #[values(1, 3)] u: u32, 58 | #[values("rst", "srt")] s: &str, 59 | #[values(("SS", -12), ("TT", -24))] t: (&str, i32), 60 | ) { 61 | assert!(false); 62 | } 63 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/dump_debug_compact.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[derive(Debug)] 4 | struct A {} 5 | 6 | #[fixture] 7 | fn fu32() -> u32 { 8 | 42 9 | } 10 | #[fixture] 11 | fn fstring() -> String { 12 | "A String".to_string() 13 | } 14 | #[fixture] 15 | fn ftuple() -> (A, String, i32) { 16 | (A {}, "A String".to_string(), -12) 17 | } 18 | 19 | #[rstest(::trace)] 20 | fn single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { 21 | assert!(false); 22 | } 23 | 24 | #[rstest] 25 | fn no_trace_single_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { 26 | assert!(false); 27 | } 28 | 29 | #[rstest(u, s, t, 30 | case(42, "str", ("ss", -12)), 31 | case(24, "trs", ("tt", -24)) 32 | ::trace 33 | )] 34 | fn cases_fail(u: u32, s: &str, t: (&str, i32)) { 35 | assert!(false); 36 | } 37 | 38 | #[rstest(u, s, t, 39 | case(42, "str", ("ss", -12)), 40 | case(24, "trs", ("tt", -24)) 41 | )] 42 | fn no_trace_cases_fail(u: u32, s: &str, t: (&str, i32)) { 43 | assert!(false); 44 | } 45 | 46 | #[rstest( 47 | u => [1, 2], 48 | s => ["rst", "srt"], 49 | t => [("SS", -12), ("TT", -24)] 50 | ::trace 51 | )] 52 | fn matrix_fail(u: u32, s: &str, t: (&str, i32)) { 53 | assert!(false); 54 | } 55 | 56 | #[rstest( 57 | u => [1, 2], 58 | s => ["rst", "srt"], 59 | t => [("SS", -12), ("TT", -24)] 60 | )] 61 | fn no_trace_matrix_fail(u: u32, s: &str, t: (&str, i32)) { 62 | assert!(false); 63 | } 64 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/dump_exclude_some_inputs.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | struct A; 4 | struct B; 5 | #[derive(Debug)] 6 | struct D; 7 | 8 | #[fixture] 9 | fn fu32() -> u32 { 10 | 42 11 | } 12 | #[fixture] 13 | fn fb() -> B { 14 | B {} 15 | } 16 | #[fixture] 17 | fn fd() -> D { 18 | D {} 19 | } 20 | #[fixture] 21 | fn fa() -> A { 22 | A {} 23 | } 24 | 25 | #[rstest] 26 | #[trace] 27 | fn simple(fu32: u32, #[notrace] fa: A, #[notrace] fb: B, fd: D) { 28 | assert!(false); 29 | } 30 | 31 | #[rstest] 32 | #[trace] 33 | #[case(A{}, B{}, D{})] 34 | fn cases(fu32: u32, #[case] #[notrace] a: A, #[case] #[notrace] b: B, #[case] d: D) { 35 | assert!(false); 36 | } 37 | 38 | #[rstest] 39 | #[trace] 40 | fn matrix( 41 | fu32: u32, 42 | #[notrace] 43 | #[values(A{})] 44 | a: A, 45 | #[notrace] 46 | #[values(B{})] 47 | b: B, 48 | #[values(D{}) ] dd: D, 49 | ) { 50 | assert!(false); 51 | } 52 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/dump_exclude_some_inputs_compact.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | struct A; 4 | struct B; 5 | #[derive(Debug)] 6 | struct D; 7 | 8 | #[fixture] 9 | fn fu32() -> u32 { 42 } 10 | #[fixture] 11 | fn fb() -> B { B {} } 12 | #[fixture] 13 | fn fd() -> D { D {} } 14 | #[fixture] 15 | fn fa() -> A { A {} } 16 | 17 | 18 | #[rstest( 19 | ::trace::notrace(fa,fb)) 20 | ] 21 | fn simple(fu32: u32, fa: A, fb: B, fd: D) { 22 | assert!(false); 23 | } 24 | 25 | #[rstest(a,b,d, 26 | case(A{}, B{}, D{}) 27 | ::trace::notrace(a,b)) 28 | ] 29 | fn cases(fu32: u32, a: A, b: B, d: D) { 30 | assert!(false); 31 | } 32 | 33 | #[rstest( 34 | a => [A{}], 35 | b => [B{}], 36 | dd => [D{}], 37 | ::trace::notrace(a,b)) 38 | ] 39 | fn matrix(fu32: u32, a: A, b: B, dd: D) { 40 | assert!(false); 41 | } 42 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/dump_not_debug.rs: -------------------------------------------------------------------------------- 1 | struct S; 2 | #[rustfmt::skip] mod _skip_format { 3 | use rstest::*; use super::*; 4 | 5 | #[fixture] 6 | fn fixture() -> S { S {} } 7 | 8 | #[rstest] 9 | #[trace] 10 | fn single(fixture: S) {} 11 | 12 | #[rstest(s)] 13 | #[trace] 14 | #[case(S{})] 15 | fn cases(s: S) {} 16 | 17 | #[rstest( 18 | s => [S{}])] 19 | #[trace] 20 | fn matrix(s: S) {} 21 | } 22 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/dump_not_debug_compact.rs: -------------------------------------------------------------------------------- 1 | struct S; 2 | #[rustfmt::skip] mod _skip_format { 3 | use rstest::*; use super::*; 4 | 5 | #[fixture] 6 | fn fixture() -> S { S {} } 7 | 8 | #[rstest( 9 | ::trace)] 10 | fn single(fixture: S) {} 11 | 12 | #[rstest(s, 13 | case(S{}) 14 | ::trace)] 15 | fn cases(s: S) {} 16 | 17 | #[rstest( 18 | s => [S{}] 19 | ::trace)] 20 | fn matrix(s: S) {} 21 | } 22 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/errors.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | #[fixture] 3 | pub fn fixture() -> u32 { 4 | 42 5 | } 6 | 7 | #[rstest(f, case(42))] 8 | fn error_inner(f: i32) { 9 | let a: u32 = ""; 10 | } 11 | 12 | #[rstest(f, case(42))] 13 | fn error_cannot_resolve_fixture(no_fixture: u32, f: u32) {} 14 | 15 | #[rstest(f, case(42))] 16 | fn error_fixture_wrong_type(fixture: String, f: u32) {} 17 | 18 | #[rstest(f, case(42))] 19 | fn error_case_wrong_type(f: &str) {} 20 | 21 | #[rstest(condition, 22 | case(vec![1,2,3].contains(2))) 23 | ] 24 | fn error_in_arbitrary_rust_code_cases(condition: bool) { 25 | assert!(condition) 26 | } 27 | 28 | #[rstest(f, case(42), not_a_fixture(24))] 29 | fn error_inject_an_invalid_fixture(f: u32) {} 30 | 31 | #[fixture] 32 | fn n() -> u32 { 33 | 24 34 | } 35 | 36 | #[fixture] 37 | fn f(n: u32) -> u32 { 38 | 2 * n 39 | } 40 | 41 | #[rstest(f, f(42), case(12))] 42 | fn error_inject_a_fixture_that_is_already_a_case(f: u32) {} 43 | 44 | #[rstest(f(42), f, case(12))] 45 | fn error_define_case_that_is_already_an_injected_fixture(f: u32) {} 46 | 47 | #[rstest(v, f(42), f(42), case(12))] 48 | fn error_inject_a_fixture_more_than_once(v: u32, f: u32) {} 49 | 50 | #[rstest(f => [42])] 51 | fn error_matrix_wrong_type(f: &str) {} 52 | 53 | #[rstest(condition => [vec![1,2,3].contains(2)] )] 54 | fn error_arbitrary_rust_code_matrix(condition: bool) { 55 | assert!(condition) 56 | } 57 | 58 | #[rstest(empty => [])] 59 | fn error_empty_list(empty: &str) {} 60 | 61 | #[rstest(not_exist_1 => [42], 62 | not_exist_2 => [42])] 63 | fn error_no_match_args() {} 64 | 65 | #[rstest(f => [41, 42], f(42))] 66 | fn error_inject_a_fixture_that_is_already_a_value_list(f: u32) {} 67 | 68 | #[rstest(f(42), f => [41, 42])] 69 | fn error_define_a_value_list_that_is_already_an_injected_fixture(f: u32) {} 70 | 71 | #[rstest(a, case(42), a => [42])] 72 | fn error_define_a_value_list_that_is_already_a_case_arg(a: u32) {} 73 | 74 | #[rstest(a => [42], a, case(42))] 75 | fn error_define_a_case_arg_that_is_already_a_value_list(a: u32) {} 76 | 77 | #[rstest(a => [42, 24], a => [24, 42])] 78 | fn error_define_a_value_list_that_is_already_a_value_list(f: u32) {} 79 | 80 | #[rstest(a, a, case(42))] 81 | fn error_define_a_case_arg_that_is_already_a_case_arg(a: u32) {} 82 | 83 | struct S; 84 | #[rstest] 85 | #[case("donald duck")] 86 | fn error_convert_to_type_that_not_implement_from_str(#[case] s: S) {} 87 | 88 | #[rstest] 89 | #[case(async { "hello" } )] 90 | async fn error_future_on_impl_type( 91 | #[case] 92 | #[future] 93 | s: impl AsRef, 94 | ) { 95 | } 96 | 97 | #[rstest] 98 | #[case(async { 42 } )] 99 | async fn error_future_more_than_once( 100 | #[case] 101 | #[future] 102 | #[future] 103 | a: i32, 104 | ) { 105 | } 106 | 107 | #[rstest] 108 | #[timeout] 109 | fn error_timeout_without_arg() {} 110 | 111 | #[rstest] 112 | #[timeout(some -> strange -> invalid -> expression)] 113 | fn error_timeout_without_expression_arg() {} 114 | 115 | #[rstest] 116 | #[timeout(42)] 117 | fn error_timeout_without_duration() {} 118 | 119 | #[rstest] 120 | fn error_absolute_path_files(#[files("/tmp/tmp.Q81idVZYAV/*.txt")] path: std::path::PathBuf) {} 121 | 122 | struct T(u32, u32); 123 | 124 | #[rstest] 125 | #[case(T(3, 4))] 126 | fn wrong_destruct_fixture(T(a, b): T, #[with(42)] T(c, d): T) {} 127 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/files.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use std::fs::File; 3 | use std::io::Read; 4 | use std::path::PathBuf; 5 | 6 | #[rstest] 7 | fn start_with_name( 8 | #[files("files/**/*.txt")] 9 | #[exclude("exclude")] 10 | #[files("../files_test_sub_folder/**/*.txt")] 11 | path: PathBuf, 12 | ) { 13 | let name = path.file_name().unwrap(); 14 | let mut f = File::open(&path).unwrap(); 15 | let mut contents = String::new(); 16 | f.read_to_string(&mut contents).unwrap(); 17 | 18 | assert!(contents.starts_with(name.to_str().unwrap())) 19 | } 20 | 21 | #[rstest] 22 | fn start_with_name_file_mode( 23 | #[files("files/**/*.txt")] 24 | #[exclude("exclude")] 25 | #[files("../files_test_sub_folder/**/*.txt")] 26 | #[mode = path] 27 | path: PathBuf, 28 | ) { 29 | let name = path.file_name().unwrap(); 30 | let mut f = File::open(&path).unwrap(); 31 | let mut contents = String::new(); 32 | f.read_to_string(&mut contents).unwrap(); 33 | 34 | assert!(contents.starts_with(name.to_str().unwrap())) 35 | } 36 | 37 | #[rstest] 38 | fn start_with_name_with_include( 39 | #[files("files/**/*.txt")] 40 | #[exclude("exclude")] 41 | #[include_dot_files] 42 | path: PathBuf, 43 | ) { 44 | let name = path.file_name().unwrap(); 45 | let mut f = File::open(&path).unwrap(); 46 | let mut contents = String::new(); 47 | f.read_to_string(&mut contents).unwrap(); 48 | 49 | assert!(contents.starts_with(name.to_str().unwrap())) 50 | } 51 | 52 | #[rstest] 53 | fn ignore_directories_wildcard( 54 | #[files("folders/**/*")] 55 | path: PathBuf, 56 | ) { 57 | assert!(!path.is_dir()) 58 | } 59 | 60 | #[rstest] 61 | fn ignore_directories( 62 | #[files("folders/**/*.txt")] 63 | path: PathBuf, 64 | ) { 65 | assert!(!path.is_dir()) 66 | } 67 | 68 | #[rstest] 69 | fn include_directories_wildcard( 70 | #[files("folders/**/*")] 71 | #[dirs] 72 | path: PathBuf, 73 | ) { 74 | // Should be generated when the glob matches folders as well. 75 | } 76 | 77 | #[rstest] 78 | fn include_directories( 79 | #[files("folders/**/*.txt")] 80 | #[dirs] 81 | path: PathBuf, 82 | ) { 83 | // Should be generated when the glob matches folders as well. 84 | } 85 | 86 | #[rstest] 87 | fn ignore_missing_env_vars( 88 | #[ignore_missing_env_vars] 89 | #[files("files/**/${__SHOULD_NOT_BE_DECLARED__}*.txt")] 90 | #[exclude("exclude")] 91 | path: PathBuf, 92 | ) { 93 | let name = path.file_name().unwrap(); 94 | let mut f = File::open(&path).unwrap(); 95 | let mut contents = String::new(); 96 | f.read_to_string(&mut contents).unwrap(); 97 | 98 | assert!(contents.starts_with(name.to_str().unwrap())) 99 | } 100 | 101 | #[rstest] 102 | fn env_vars( 103 | #[files("${FILES_ENV_VAR}/**/*.txt")] 104 | #[exclude("exclude")] 105 | path: PathBuf, 106 | ) { 107 | let name = path.file_name().unwrap(); 108 | let mut f = File::open(&path).unwrap(); 109 | let mut contents = String::new(); 110 | f.read_to_string(&mut contents).unwrap(); 111 | 112 | assert!(contents.starts_with(name.to_str().unwrap())) 113 | } 114 | 115 | #[rstest] 116 | fn env_vars_unknown( 117 | #[files("${__UNKNOWN__:-files}/**/*.txt")] 118 | #[exclude("exclude")] 119 | path: PathBuf, 120 | ) { 121 | let name = path.file_name().unwrap(); 122 | let mut f = File::open(&path).unwrap(); 123 | let mut contents = String::new(); 124 | f.read_to_string(&mut contents).unwrap(); 125 | 126 | assert!(contents.starts_with(name.to_str().unwrap())) 127 | } 128 | 129 | #[rstest] 130 | fn env_vars_base_dir( 131 | #[files("**/*.txt")] 132 | #[base_dir = "files"] 133 | #[exclude("exclude")] 134 | path: PathBuf, 135 | ) { 136 | let name = path.file_name().unwrap(); 137 | let mut f = File::open(&path).unwrap(); 138 | let mut contents = String::new(); 139 | f.read_to_string(&mut contents).unwrap(); 140 | 141 | assert!(contents.starts_with(name.to_str().unwrap())) 142 | } 143 | 144 | #[rstest] 145 | fn include_str( 146 | #[files("files/**/*.txt")] 147 | #[exclude("exclude")] 148 | #[files("../files_test_sub_folder/**/*.txt")] 149 | #[mode = str] 150 | contents: &str, 151 | ) { 152 | assert!(contents.len() != 0) 153 | } 154 | 155 | #[rstest] 156 | fn include_bytes( 157 | #[files("files/**/*.txt")] 158 | #[exclude("exclude")] 159 | #[files("../files_test_sub_folder/**/*.txt")] 160 | #[mode = bytes] 161 | contents: &[u8], 162 | ) { 163 | assert!(contents.len() != 0) 164 | } 165 | 166 | mod module { 167 | #[rstest::rstest] 168 | fn pathbuf_need_not_be_in_scope( 169 | #[files("files/**/*.txt")] 170 | #[exclude("exclude")] 171 | #[include_dot_files] 172 | path: std::path::PathBuf, 173 | ) { 174 | let _ = path; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/generic.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn fixture() -> String { "str".to_owned() } 5 | 6 | #[rstest] 7 | fn simple>(fixture: S) { 8 | assert_eq!(3, fixture.as_ref().len()); 9 | } 10 | 11 | #[rstest( 12 | expected, input, 13 | case(4, String::from("ciao")), 14 | case(3, "Foo") 15 | )] 16 | fn strlen_test>(expected: usize, input: S) { 17 | assert_eq!(expected, input.as_ref().len()); 18 | } 19 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/happy_path.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn inject() -> u32 { 5 | 0 6 | } 7 | 8 | #[fixture] 9 | fn ex() -> u32 { 10 | 42 11 | } 12 | 13 | #[fixture] 14 | fn fix(inject: u32, ex: u32) -> bool { 15 | (inject * 2) == ex 16 | } 17 | 18 | #[rstest( 19 | fix(21), 20 | a, 21 | case(21, 2), 22 | expected => [4, 2*3-2], 23 | )] 24 | #[case::second(14, 3)] 25 | fn happy( 26 | fix: bool, 27 | a: u32, 28 | #[case] b: u32, 29 | expected: usize, 30 | #[values("ciao", "buzz")] input: &str, 31 | ) { 32 | assert!(fix); 33 | assert_eq!(a * b, 42); 34 | assert_eq!(expected, input.len()); 35 | } 36 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/ignore_args.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[case(42, 2)] 5 | #[case(43, 3)] 6 | fn test(#[case] _ignore1: u32, #[case] _ignore2: u32, #[values(1, 2, 3, 4)] _ignore3: u32) {} 7 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/ignore_attributes_args_if_any.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | use sqlx::SqlitePool; 4 | 5 | fn sum(a: i32, b: i32, c: i32) -> i32 { 6 | a + b + c 7 | } 8 | 9 | #[rstest] 10 | #[case(1, 2)] 11 | #[case(2, 3)] 12 | #[sqlx::test] 13 | fn test_sum(#[case] a: i32, #[case] b: i32, #[values(1,2)] c: i32, #[ignore] pool: SqlitePool) { 14 | assert_eq!(sum(a, b, c), a + b + c); 15 | } -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/impl_param.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn fixture() -> String { "str".to_owned() } 5 | 6 | #[rstest] 7 | fn simple(fixture: impl AsRef) { 8 | assert_eq!(3, fixture.as_ref().len()); 9 | } 10 | 11 | #[rstest( 12 | expected, input, 13 | case(4, String::from("ciao")), 14 | case(3, "Foo") 15 | )] 16 | fn strlen_test(expected: usize, input: impl AsRef) { 17 | assert_eq!(expected, input.as_ref().len()); 18 | } 19 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/lifetimes.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | enum E<'a> { 4 | A(bool), 5 | B(&'a std::cell::Cell>), 6 | } 7 | 8 | #[rstest] 9 | #[case(E::A(true))] 10 | fn case<'a>(#[case] e: E<'a>) {} 11 | 12 | #[rstest] 13 | fn values<'a>(#[values(E::A(true))] e: E<'a>) {} 14 | 15 | #[fixture] 16 | fn e<'a>() -> E<'a> { 17 | E::A(true) 18 | } 19 | 20 | #[rstest] 21 | fn fixture<'a>(e: E<'a>) {} 22 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/local_lifetime.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | 3 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 4 | enum E<'a> { 5 | A(bool), 6 | B(&'a Cell>), 7 | } 8 | 9 | fn make_e_from_bool<'a>(_bump: &'a (), b: bool) -> E<'a> { 10 | E::A(b) 11 | } 12 | 13 | #[cfg(test)] 14 | mod tests { 15 | use rstest::*; 16 | 17 | use super::*; 18 | 19 | #[fixture] 20 | fn bump() -> () {} 21 | 22 | #[rstest] 23 | #[case(true, E::A(true))] 24 | fn it_works<'a>(#[by_ref] bump: &'a (), #[case] b: bool, #[case] expected: E<'a>) { 25 | let actual = make_e_from_bool(&bump, b); 26 | assert_eq!(actual, expected); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/matrix/async.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[async_std::test] 5 | async fn my_async_test( 6 | #[future] 7 | #[values(async { 1 }, async { 2 })] 8 | first: u32, 9 | #[values(42, 21)] second: u32, 10 | ) { 11 | assert_eq!(42, first.await * second); 12 | } 13 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/matrix/async_awt.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[async_std::test] 5 | async fn my_async_test( 6 | #[future(awt)] 7 | #[values(async { 1 }, async { 2 })] 8 | first: u32, 9 | #[values(42, 21)] second: u32, 10 | ) { 11 | assert_eq!(42, first * second); 12 | } 13 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/matrix/async_awt_global.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[rstest] 4 | #[async_std::test] 5 | #[awt] 6 | async fn my_async_test( 7 | #[future] 8 | #[values(async { 1 }, async { 2 })] 9 | first: u32, 10 | #[values(42, 21)] second: u32, 11 | ) { 12 | assert_eq!(42, first * second); 13 | } 14 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/matrix/inject.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use actix_rt; 3 | use std::future::Future; 4 | 5 | #[rstest( 6 | first => [1, 2], 7 | second => [2, 1], 8 | )] 9 | #[test] 10 | fn sync(first: u32, second: u32) { assert_eq!(2, first * second); } 11 | 12 | #[rstest( 13 | first => [async { 1 }, async { 2 }], 14 | second => [2, 1], 15 | )] 16 | #[actix_rt::test] 17 | async fn fn_async(first: impl Future, second: u32) { assert_eq!(2, first.await * second); } 18 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/matrix/partial.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn f1() -> u32 { 5 | 0 6 | } 7 | #[fixture] 8 | fn f2() -> u32 { 9 | 0 10 | } 11 | #[fixture] 12 | fn f3() -> u32 { 13 | 0 14 | } 15 | 16 | #[fixture] 17 | fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { 18 | f1 + f2 + 2 * f3 19 | } 20 | 21 | #[rstest(a => [0, 1], b => [0, 2])] 22 | fn default(fixture: u32, a: u32, b: u32) { 23 | assert_eq!(fixture, a * b); 24 | } 25 | 26 | #[rstest(a => [0, 1], b => [0, 2], fixture(1))] 27 | fn partial_1(fixture: u32, a: u32, b: u32) { 28 | assert_eq!(fixture, a * b); 29 | } 30 | 31 | #[rstest(a => [0, 1], b => [0, 2])] 32 | fn partial_attr_1(#[with(1)] fixture: u32, a: u32, b: u32) { 33 | assert_eq!(fixture, a * b); 34 | } 35 | 36 | #[rstest(a => [0, 1], b => [0, 2], fixture(0, 2))] 37 | fn partial_2(fixture: u32, a: u32, b: u32) { 38 | assert_eq!(fixture, a * b); 39 | } 40 | 41 | #[rstest(a => [0, 1], b => [0, 2])] 42 | fn partial_attr_2(#[with(0, 2)] fixture: u32, a: u32, b: u32) { 43 | assert_eq!(fixture, a * b); 44 | } 45 | 46 | #[rstest(a => [0, 1], b => [0, 2], fixture(0, 0, 1))] 47 | fn complete(fixture: u32, a: u32, b: u32) { 48 | assert_eq!(fixture, a * b); 49 | } 50 | 51 | #[rstest(a => [0, 1], b => [0, 2])] 52 | fn complete_attr(#[with(0, 0, 1)] fixture: u32, a: u32, b: u32) { 53 | assert_eq!(fixture, a * b); 54 | } 55 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/matrix/simple.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest( 4 | expected => [4, 2*3-2], 5 | input => ["ciao", "buzz"], 6 | )] 7 | fn strlen_test(expected: usize, input: &str) { 8 | assert_eq!(expected, input.len()); 9 | } 10 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/matrix/use_attr.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest] 4 | fn both(#[values(4, 2*3-2)] expected: usize, #[values("ciao", "buzz")] input: &str) { 5 | assert_eq!(expected, input.len()); 6 | } 7 | 8 | #[rstest( 9 | input => ["ciao", "buzz"] 10 | )] 11 | fn first(#[values(4, 2*3-2)] expected: usize, input: &str) { 12 | assert_eq!(expected, input.len()); 13 | } 14 | 15 | #[rstest( 16 | expected => [4, 2*3-2] 17 | )] 18 | fn second(expected: usize, #[values("ciao", "buzz")] input: &str) { 19 | assert_eq!(expected, input.len()); 20 | } 21 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/mut.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | pub fn fixture() -> u32 { 42 } 5 | 6 | #[rstest] 7 | fn should_success(mut fixture: u32) { 8 | fixture += 1; 9 | assert_eq!(fixture, 43); 10 | } 11 | 12 | #[rstest] 13 | fn should_fail(mut fixture: u32) { 14 | fixture += 1; 15 | assert_ne!(fixture, 43); 16 | } 17 | 18 | #[rstest( 19 | expected, val, 20 | case(45, 1), 21 | case(46, 2), 22 | case(47, 2) 23 | )] 24 | fn add_test(mut fixture: u32, expected: u32, mut val: u32) { 25 | fixture += 1; 26 | val += fixture + 1; 27 | 28 | assert_eq!(expected, val); 29 | } 30 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/no_std.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | 3 | use rstest::{fixture, rstest}; 4 | 5 | #[fixture] 6 | #[once] 7 | fn once_fixture() -> u64 { 8 | 42 9 | } 10 | 11 | #[fixture] 12 | #[once] 13 | fn empty_once_fixture() {} 14 | 15 | #[fixture] 16 | async fn async_fixture() -> u64 { 17 | 42 18 | } 19 | 20 | pub fn add(left: u64, right: u64) -> u64 { 21 | left + right 22 | } 23 | 24 | #[rstest] 25 | #[case("2", "2", "4")] 26 | fn it_works(#[case] left: u64, #[case] right: u64, #[case] expected: u64) { 27 | assert_eq!(add(left, right), expected); 28 | } 29 | 30 | #[rstest] 31 | #[async_std::test] 32 | async fn async_works(#[future] async_fixture: u64) { 33 | assert_eq!(42, async_fixture.await); 34 | } 35 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/panic.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | pub fn fixture() -> u32 { 42 } 5 | 6 | #[rstest] 7 | #[should_panic] 8 | fn should_success(fixture: u32) { 9 | assert_ne!(fixture, 42); 10 | } 11 | 12 | #[rstest] 13 | #[should_panic] 14 | fn should_fail(fixture: u32) { 15 | assert_eq!(fixture, 42); 16 | } 17 | 18 | #[rstest( 19 | expected, input, 20 | case(4, 5), 21 | case(3, 2), 22 | case(3, 3) 23 | )] 24 | #[should_panic] 25 | fn fail(expected: i32, input: i32) { 26 | assert_eq!(expected, input); 27 | } 28 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/reject_no_item_function.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest] 4 | struct Foo; 5 | 6 | #[rstest] 7 | impl Foo {} 8 | 9 | #[rstest] 10 | mod mod_baz {} 11 | 12 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/remove_underscore.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn can_be_ignored() {} 5 | 6 | #[rstest] 7 | fn ignore_input(_can_be_ignored: ()) { 8 | assert!(true); 9 | } 10 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/rename.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn very_long_and_boring_name(#[default(42)] inject: u32) -> u32 { 5 | inject 6 | } 7 | 8 | mod sub_module { 9 | use super::*; 10 | 11 | #[fixture] 12 | pub fn mod_fixture() -> u32 { 13 | 42 14 | } 15 | } 16 | 17 | #[rstest(very_long_and_boring_name as foo)] 18 | fn compact(foo: u32) { 19 | assert!(42 == foo); 20 | } 21 | 22 | #[rstest(sub_module::mod_fixture as foo)] 23 | fn compact_mod(foo: u32) { 24 | assert!(42 == foo); 25 | } 26 | 27 | #[rstest(very_long_and_boring_name(21) as foo)] 28 | fn compact_injected(foo: u32) { 29 | assert!(21 == foo); 30 | } 31 | 32 | #[rstest] 33 | fn attribute(#[from(very_long_and_boring_name)] foo: u32) { 34 | assert!(42 == foo); 35 | } 36 | 37 | #[rstest] 38 | fn attribute_mod(#[from(sub_module::mod_fixture)] foo: u32) { 39 | assert!(42 == foo); 40 | } 41 | 42 | #[rstest] 43 | fn attribute_injected( 44 | #[from(very_long_and_boring_name)] 45 | #[with(21)] 46 | foo: u32, 47 | ) { 48 | assert!(21 == foo); 49 | } 50 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/return_result.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | 3 | #[rstest] 4 | fn should_success() -> Result<(), &'static str> { 5 | Ok(()) 6 | } 7 | 8 | #[rstest] 9 | fn should_fail() -> Result<(), &'static str> { 10 | Err("Return Error") 11 | } 12 | 13 | #[rstest(ret, 14 | case::should_success(Ok(())), 15 | case::should_fail(Err("Return Error")) 16 | )] 17 | fn return_type(ret: Result<(), &'static str>) -> Result<(), &'static str> { 18 | ret 19 | } 20 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/async.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | async fn fixture() -> u32 { 5 | 42 6 | } 7 | 8 | #[rstest] 9 | #[async_std::test] 10 | async fn should_pass(#[future] fixture: u32) { 11 | assert_eq!(fixture.await, 42); 12 | } 13 | 14 | #[rstest] 15 | #[async_std::test] 16 | async fn should_fail(#[future] fixture: u32) { 17 | assert_ne!(fixture.await, 42); 18 | } 19 | 20 | #[rstest] 21 | #[async_std::test] 22 | #[should_panic] 23 | async fn should_panic_pass(#[future] fixture: u32) { 24 | panic!(format!("My panic -> fixture = {}", fixture.await)); 25 | } 26 | 27 | #[rstest] 28 | #[async_std::test] 29 | #[should_panic] 30 | async fn should_panic_fail(#[future] fixture: u32) { 31 | assert_eq!(fixture.await, 42); 32 | } 33 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/async_awt.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | async fn fixture() -> u32 { 5 | 42 6 | } 7 | 8 | #[rstest] 9 | #[async_std::test] 10 | async fn should_pass(#[future(awt)] fixture: u32) { 11 | assert_eq!(fixture, 42); 12 | } 13 | 14 | #[rstest] 15 | #[async_std::test] 16 | async fn should_fail(#[future(awt)] fixture: u32) { 17 | assert_ne!(fixture, 42); 18 | } 19 | 20 | #[rstest] 21 | #[async_std::test] 22 | #[should_panic] 23 | async fn should_panic_pass(#[future(awt)] fixture: u32) { 24 | panic!(format!("My panic -> fixture = {}", fixture)); 25 | } 26 | 27 | #[rstest] 28 | #[async_std::test] 29 | #[should_panic] 30 | async fn should_panic_fail(#[future(awt)] fixture: u32) { 31 | assert_eq!(fixture, 42); 32 | } 33 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/async_awt_global.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | async fn fixture() -> u32 { 5 | 42 6 | } 7 | 8 | #[rstest] 9 | #[async_std::test] 10 | #[awt] 11 | async fn should_pass(#[future] fixture: u32) { 12 | assert_eq!(fixture, 42); 13 | } 14 | 15 | #[rstest] 16 | #[async_std::test] 17 | #[awt] 18 | async fn should_fail(#[future] fixture: u32) { 19 | assert_ne!(fixture, 42); 20 | } 21 | 22 | #[rstest] 23 | #[async_std::test] 24 | #[awt] 25 | #[should_panic] 26 | async fn should_panic_pass(#[future] fixture: u32) { 27 | panic!(format!("My panic -> fixture = {}", fixture)); 28 | } 29 | 30 | #[rstest] 31 | #[async_std::test] 32 | #[awt] 33 | #[should_panic] 34 | async fn should_panic_fail(#[future] fixture: u32) { 35 | assert_eq!(fixture, 42); 36 | } 37 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/dump_debug.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[derive(Debug)] 4 | struct A {} 5 | 6 | #[fixture] 7 | fn fu32() -> u32 { 42 } 8 | #[fixture] 9 | fn fstring() -> String { "A String".to_string() } 10 | #[fixture] 11 | fn ftuple() -> (A, String, i32) { (A{}, "A String".to_string(), -12) } 12 | 13 | #[rstest(::trace)] 14 | fn should_fail(fu32: u32, fstring: String, ftuple: (A, String, i32)) { 15 | assert!(false); 16 | } 17 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/inject.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use actix_rt; 3 | 4 | #[fixture] 5 | fn a() -> u32 { 6 | 42 7 | } 8 | 9 | #[rstest] 10 | #[test] 11 | fn sync_case(a: u32) {} 12 | 13 | #[rstest] 14 | #[test] 15 | #[should_panic] 16 | fn sync_case_panic(a: u32) { panic!("panic") } 17 | 18 | #[rstest] 19 | #[test] 20 | fn sync_case_fail(a: u32) { assert_eq!(2, a); } 21 | 22 | #[rstest] 23 | #[test] 24 | fn sync_case_panic_fail(a: u32) { panic!("panic") } 25 | 26 | #[rstest] 27 | #[actix_rt::test] 28 | async fn async_case(a: u32) {} 29 | 30 | #[rstest] 31 | #[actix_rt::test] 32 | async fn async_case_fail(a: u32) { assert_eq!(2, a); } 33 | 34 | #[rstest] 35 | #[actix_rt::test] 36 | #[should_panic] 37 | async fn async_case_panic(a: u32) { panic!("panic") } 38 | 39 | #[rstest] 40 | #[actix_rt::test] 41 | async fn async_case_panic_fail(a: u32) { panic!("panic") } -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/partial.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn f1() -> u32 { 5 | 0 6 | } 7 | #[fixture] 8 | fn f2() -> u32 { 9 | 0 10 | } 11 | #[fixture] 12 | fn f3() -> u32 { 13 | 0 14 | } 15 | 16 | #[fixture] 17 | fn fixture(f1: u32, f2: u32, f3: u32) -> u32 { 18 | f1 + 10 * f2 + 100 * f3 19 | } 20 | 21 | #[rstest] 22 | fn default(fixture: u32) { 23 | assert_eq!(fixture, 0); 24 | } 25 | 26 | #[rstest(fixture(7))] 27 | fn partial_1(fixture: u32) { 28 | assert_eq!(fixture, 7); 29 | } 30 | 31 | #[rstest] 32 | fn partial_attr_1(#[with(7)] fixture: u32) { 33 | assert_eq!(fixture, 7); 34 | } 35 | 36 | #[rstest(fixture(2, 4))] 37 | fn partial_2(fixture: u32) { 38 | assert_eq!(fixture, 42); 39 | } 40 | 41 | #[rstest] 42 | fn partial_attr_2(#[with(2, 4)] fixture: u32) { 43 | assert_eq!(fixture, 42); 44 | } 45 | 46 | #[rstest(fixture(2, 4, 5))] 47 | fn complete(fixture: u32) { 48 | assert_eq!(fixture, 542); 49 | } 50 | 51 | #[rstest] 52 | fn complete_attr(#[with(2, 4, 5)] fixture: u32) { 53 | assert_eq!(fixture, 542); 54 | } 55 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/resolve.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | pub trait Tr { 4 | fn get() -> Self; 5 | } 6 | 7 | impl Tr for i32 { 8 | fn get() -> Self { 9 | 42 10 | } 11 | } 12 | 13 | impl Tr for u32 { 14 | fn get() -> Self { 15 | 42 16 | } 17 | } 18 | 19 | #[fixture] 20 | pub fn fgen() -> T { 21 | T::get() 22 | } 23 | 24 | #[rstest] 25 | fn generics_u32(fgen: u32) { 26 | assert_eq!(fgen, 42u32); 27 | } 28 | 29 | #[rstest] 30 | fn generics_i32(fgen: i32) { 31 | assert_eq!(fgen, 42i32); 32 | } 33 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/single/simple.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | pub fn fixture() -> u32 { 42 } 5 | 6 | #[rstest] 7 | fn should_success(fixture: u32) { 8 | assert_eq!(fixture, 42); 9 | } 10 | 11 | #[rstest] 12 | fn should_fail(fixture: u32) { 13 | assert_ne!(fixture, 42); 14 | } 15 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/timeout_async.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | use std::time::Duration; 3 | 4 | fn ms(ms: u32) -> Duration { 5 | Duration::from_millis(ms.into()) 6 | } 7 | 8 | async fn delayed_sum(a: u32, b: u32, delay: Duration) -> u32 { 9 | async_std::task::sleep(delay).await; 10 | a + b 11 | } 12 | 13 | #[rstest] 14 | #[async_std::test] 15 | #[timeout(ms(80))] 16 | async fn single_pass() { 17 | assert_eq!(4, delayed_sum(2, 2, ms(10)).await); 18 | } 19 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/timeout_other_name.rs: -------------------------------------------------------------------------------- 1 | use other_name::*; 2 | use std::time::Duration; 3 | 4 | fn ms(ms: u32) -> Duration { 5 | Duration::from_millis(ms.into()) 6 | } 7 | 8 | mod thread { 9 | use super::*; 10 | 11 | fn delayed_sum(a: u32, b: u32, delay: Duration) -> u32 { 12 | std::thread::sleep(delay); 13 | a + b 14 | } 15 | 16 | #[rstest] 17 | #[timeout(ms(80))] 18 | fn single_pass() { 19 | assert_eq!(4, delayed_sum(2, 2, ms(10))); 20 | } 21 | 22 | #[rstest] 23 | #[timeout(ms(100))] 24 | fn single_fail_value() { 25 | assert_eq!(5, delayed_sum(2, 2, ms(1))); 26 | } 27 | 28 | #[rstest] 29 | #[timeout(ms(1000))] 30 | #[should_panic = "user message"] 31 | fn fail_with_user_message() { 32 | panic!("user message"); 33 | } 34 | 35 | #[rstest] 36 | #[timeout(ms(10))] 37 | fn single_fail_timeout() { 38 | assert_eq!(4, delayed_sum(2, 2, ms(80))); 39 | } 40 | 41 | #[rstest] 42 | #[timeout(ms(80))] 43 | #[case(ms(10))] 44 | fn one_pass(#[case] delay: Duration) { 45 | assert_eq!(4, delayed_sum(2, 2, delay)); 46 | } 47 | 48 | #[rstest] 49 | #[timeout(ms(10))] 50 | #[case(ms(80))] 51 | fn one_fail_timeout(#[case] delay: Duration) { 52 | assert_eq!(4, delayed_sum(2, 2, delay)); 53 | } 54 | 55 | #[rstest] 56 | #[timeout(ms(100))] 57 | #[case(ms(1))] 58 | fn one_fail_value(#[case] delay: Duration) { 59 | assert_eq!(5, delayed_sum(2, 2, delay)); 60 | } 61 | 62 | #[rstest] 63 | #[case::pass(ms(1), 4)] 64 | #[case::fail_timeout(ms(80), 4)] 65 | #[case::fail_value(ms(1), 5)] 66 | #[timeout(ms(40))] 67 | fn group_same_timeout(#[case] delay: Duration, #[case] expected: u32) { 68 | assert_eq!(expected, delayed_sum(2, 2, delay)); 69 | } 70 | 71 | #[rstest] 72 | #[timeout(ms(100))] 73 | #[case::pass(ms(1), 4)] 74 | #[timeout(ms(30))] 75 | #[case::fail_timeout(ms(70), 4)] 76 | #[timeout(ms(100))] 77 | #[case::fail_value(ms(1), 5)] 78 | fn group_single_timeout(#[case] delay: Duration, #[case] expected: u32) { 79 | assert_eq!(expected, delayed_sum(2, 2, delay)); 80 | } 81 | 82 | #[rstest] 83 | #[case::pass(ms(1), 4)] 84 | #[timeout(ms(10))] 85 | #[case::fail_timeout(ms(60), 4)] 86 | #[case::fail_value(ms(1), 5)] 87 | #[timeout(ms(100))] 88 | fn group_one_timeout_override(#[case] delay: Duration, #[case] expected: u32) { 89 | assert_eq!(expected, delayed_sum(2, 2, delay)); 90 | } 91 | 92 | struct S {} 93 | 94 | #[rstest] 95 | #[case(S{})] 96 | fn compile_with_no_copy_arg(#[case] _s: S) { 97 | assert!(true); 98 | } 99 | 100 | #[fixture] 101 | fn no_copy() -> S { 102 | S {} 103 | } 104 | 105 | #[rstest] 106 | fn compile_with_no_copy_fixture(no_copy: S) { 107 | assert!(true); 108 | } 109 | 110 | #[rstest] 111 | fn default_timeout_failure() { 112 | assert_eq!(4, delayed_sum(2, 2, ms(1100))); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/use_mutable_fixture_in_parametric_arguments.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | #[fixture] 4 | fn f() -> String { 5 | "f".to_owned() 6 | } 7 | 8 | fn append(s: &mut String, a: &str) -> String { 9 | s.push_str("-"); 10 | s.push_str(a); 11 | s.clone() 12 | } 13 | 14 | #[rstest] 15 | #[case(append(&mut f, "a"), "f-a", "f-a-b")] 16 | fn use_mutate_fixture( 17 | mut f: String, 18 | #[case] a: String, 19 | #[values(append(&mut f, "b"))] b: String, 20 | #[case] expected_a: &str, 21 | #[case] expected_b: &str, 22 | ) { 23 | assert_eq!(expected_a, a); 24 | assert_eq!(expected_b, b); 25 | } 26 | -------------------------------------------------------------------------------- /rstest/tests/resources/rstest/values_tests_name.rs: -------------------------------------------------------------------------------- 1 | use rstest::*; 2 | 3 | enum Application { 4 | Python, 5 | Node, 6 | Go, 7 | } 8 | 9 | enum Method { 10 | GET, 11 | POST, 12 | PUT, 13 | HEAD, 14 | } 15 | 16 | #[rstest] 17 | fn name_values( 18 | #[values(Application::Python, Application::Node, Application::Go)] _val: Application, 19 | #[values(Method::GET, Method::POST, Method::PUT, Method::HEAD)] _method: Method, 20 | ) { 21 | } 22 | -------------------------------------------------------------------------------- /rstest_fixtures/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rstest_fixtures" 3 | version = "0.1.0" 4 | authors = ["Michele d'Amico "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | -------------------------------------------------------------------------------- /rstest_fixtures/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /rstest_fixtures/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /rstest_fixtures/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | pub trait TearDown { 4 | fn tear_down(self); 5 | } 6 | 7 | #[derive(Default)] 8 | pub struct EmptyGuard {} 9 | 10 | impl TearDown for EmptyGuard { 11 | fn tear_down(self) {} 12 | } 13 | 14 | impl TearDown for (A, B) { 15 | fn tear_down(self) { 16 | self.0.tear_down(); 17 | self.1.tear_down(); 18 | } 19 | } 20 | 21 | pub struct Fixture { 22 | inner: Option, 23 | guard: Option, 24 | } 25 | 26 | impl Fixture { 27 | pub fn new(inner: T, guard: G) -> Self { 28 | Fixture { inner: Some(inner), guard: Some(guard) } 29 | } 30 | 31 | pub fn take(&mut self) -> T { 32 | self.inner.take().unwrap() 33 | } 34 | 35 | pub fn guard(&mut self) -> G { 36 | self.guard.take().unwrap() 37 | } 38 | 39 | pub fn compose(mut self, guard: OTHER) -> Fixture { 40 | Fixture::new(self.take(), (self.guard(), guard)) 41 | } 42 | } 43 | 44 | impl Debug for Fixture { 45 | fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 46 | write!(f, "Fixture<{:?}>", self.inner) 47 | } 48 | } 49 | 50 | impl Drop for Fixture { 51 | fn drop(&mut self) { 52 | self.guard.take().map(|g| g.tear_down()); 53 | } 54 | } 55 | 56 | impl From for Fixture { 57 | fn from(inner: T) -> Self { 58 | Fixture::new(inner, Default::default()) 59 | } 60 | } 61 | 62 | pub struct TearDownClosure ()>(F); 63 | 64 | impl ()> TearDown for TearDownClosure { 65 | fn tear_down(self) { 66 | self.0() 67 | } 68 | } 69 | 70 | impl()> From for TearDownClosure { 71 | fn from(closure: F) -> Self { 72 | TearDownClosure(closure) 73 | } 74 | } 75 | 76 | #[cfg(test)] 77 | mod test { 78 | use super::*; 79 | use std::cell::RefCell; 80 | use std::rc::Rc; 81 | 82 | #[test] 83 | fn fixture_should_wrap_value_and_run_guard_when_destroyed() { 84 | let mut guard = RefCell::new(vec![]); 85 | { 86 | let _fixture = Fixture::new(42, TearDownClosure( 87 | || guard.get_mut().push("destroyed")) 88 | ); 89 | // _fixture will be dropped here and tear_down() executed 90 | } 91 | 92 | assert_eq!(*guard.borrow(), vec!["destroyed"]); 93 | } 94 | 95 | #[test] 96 | fn tear_down_closure_should_can_move_all_needed_data() { 97 | let guard = Rc::new(RefCell::new(vec![])); 98 | { 99 | let inner_guard = guard.clone(); 100 | let _fixture = Fixture::new("some", TearDownClosure( 101 | move || inner_guard.borrow_mut().push("destroyed")) 102 | ); 103 | // _fixture will be dropped here and tear_down() executed 104 | } 105 | 106 | assert_eq!(*guard.borrow(), vec!["destroyed"]); 107 | } 108 | 109 | 110 | 111 | #[test] 112 | fn fixture_composition_use_case() { 113 | // Take a fixture `f` that use two other fixtures `f1`, `f2` and an it's own tear_down `t` 114 | // => destroy f should call first `t.tear_down()` then `f2.tear_down()` and finally `f1.tear_down()` 115 | // In other words should finally its self and then its arguments in stack reverse order. 116 | 117 | let guard = RefCell::new(vec![]); 118 | let mut f1 = Fixture::new((), TearDownClosure( 119 | || guard.borrow_mut().push("destroyed_f1")) 120 | ); 121 | let mut f2 = Fixture::new((), TearDownClosure( 122 | || guard.borrow_mut().push("destroyed_f2")) 123 | ); 124 | 125 | { 126 | let _f = Fixture::new((), 127 | TearDownClosure(|| guard.borrow_mut().push("destroyed_f"))) 128 | .compose(f2.guard()) 129 | .compose(f1.guard()); 130 | } 131 | 132 | assert_eq!(*guard.borrow(), vec!["destroyed_f","destroyed_f2","destroyed_f1"]); 133 | } 134 | 135 | #[test] 136 | fn after_moved_the_guard_fixture_can_be_released_without_invoke_tear_down() { 137 | let guard = RefCell::new(vec![]); 138 | let mut f = Fixture::new((), TearDownClosure( 139 | || guard.borrow_mut().push("destroyed_f1")) 140 | ); 141 | { 142 | let _inner_guard = f.guard(); 143 | { 144 | // Here we move the fixture to release it 145 | let _local_f = f; 146 | } 147 | assert_eq!(*guard.borrow(), Vec::<&str>::new()); 148 | // Here we drop inner guard but again this dosn't invoke tear_down() trait 149 | } 150 | assert_eq!(*guard.borrow(), Vec::<&str>::new()); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /rstest_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Michele d'Amico "] 3 | categories = ["development-tools::testing"] 4 | description = """ 5 | Rust fixture based test framework. It use procedural macro 6 | to implement fixtures and table based tests. 7 | """ 8 | edition = "2021" 9 | homepage = "https://github.com/la10736/rstest" 10 | keywords = ["test", "fixture"] 11 | license = "MIT OR Apache-2.0" 12 | name = "rstest_macros" 13 | repository = "https://github.com/la10736/rstest" 14 | rust-version = "1.70.0" 15 | version = "0.25.0-dev" 16 | 17 | [lib] 18 | proc-macro = true 19 | 20 | [features] 21 | async-timeout = [] 22 | default = ["async-timeout", "crate-name"] 23 | crate-name = ["dep:proc-macro-crate"] 24 | 25 | [dependencies] 26 | cfg-if = "1.0.0" 27 | glob = "0.3.1" 28 | proc-macro2 = "1.0.86" 29 | quote = "1.0.37" 30 | regex = "1.10.6" 31 | relative-path = "1.9.3" 32 | syn = { version = "2.0.79", features = [ 33 | "full", 34 | "parsing", 35 | "extra-traits", 36 | "visit", 37 | "visit-mut", 38 | ] } 39 | unicode-ident = "1.0.13" 40 | proc-macro-crate = { version = "3.2.0", optional = true } 41 | 42 | [dev-dependencies] 43 | actix-rt = "2.9.0" 44 | async-std = { version = "1.13.0", features = ["attributes"] } 45 | maplit = "1.0.2" 46 | pretty_assertions = "1.4.1" 47 | rstest = { version = "0.25.0", default-features = false } 48 | rstest_reuse = { path = "../rstest_reuse" } 49 | rstest_test = { path = "../rstest_test" } 50 | 51 | [build-dependencies] 52 | rustc_version = "0.4.1" 53 | -------------------------------------------------------------------------------- /rstest_macros/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /rstest_macros/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /rstest_macros/README.md: -------------------------------------------------------------------------------- 1 | [![Crate][crate-image]][crate-link] 2 | [![Docs][docs-image]][docs-link] 3 | [![Status][test-action-image]][test-action-link] 4 | [![Apache 2.0 Licensed][license-apache-image]][license-apache-link] 5 | [![MIT Licensed][license-mit-image]][license-mit-link] 6 | 7 | # `rstest`'s Macros Crate 8 | 9 | See [`rstest`][crate-link]. 10 | 11 | [crate-image]: https://img.shields.io/crates/v/rstest.svg 12 | [crate-link]: https://crates.io/crates/rstest 13 | [docs-image]: https://docs.rs/rstest/badge.svg 14 | [docs-link]: https://docs.rs/rstest/ 15 | [test-action-image]: https://github.com/la10736/rstest/workflows/Test/badge.svg 16 | [test-action-link]: https://github.com/la10736/rstest/actions?query=workflow:Test 17 | [license-apache-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg 18 | [license-mit-image]: https://img.shields.io/badge/license-MIT-blue.svg 19 | [license-apache-link]: http://www.apache.org/licenses/LICENSE-2.0 20 | [license-MIT-link]: http://opensource.org/licenses/MIT 21 | [reuse-crate-link]: https://crates.io/crates/rstest_reuse 22 | -------------------------------------------------------------------------------- /rstest_macros/build.rs: -------------------------------------------------------------------------------- 1 | use rustc_version::{version, version_meta, Channel}; 2 | 3 | fn allow_features() -> Option> { 4 | std::env::var("CARGO_ENCODED_RUSTFLAGS").ok().map(|args| { 5 | args.split('\u{001f}') 6 | .filter(|arg| arg.starts_with("-Zallow-features=")) 7 | .map(|arg| arg.split('=').nth(1).unwrap()) 8 | .flat_map(|features| features.split(',')) 9 | .map(|f| f.to_owned()) 10 | .collect() 11 | }) 12 | } 13 | 14 | fn can_enable_proc_macro_diagnostic() -> bool { 15 | allow_features() 16 | .map(|f| f.iter().any(|f| f == "proc_macro_diagnostic")) 17 | .unwrap_or(true) 18 | } 19 | 20 | fn main() { 21 | let ver = version().unwrap(); 22 | assert!(ver.major >= 1); 23 | 24 | match version_meta().unwrap().channel { 25 | Channel::Nightly | Channel::Dev if can_enable_proc_macro_diagnostic() => { 26 | println!("cargo:rustc-cfg=use_proc_macro_diagnostic"); 27 | } 28 | _ => {} 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rstest_macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::test_attr_in_doctest)] 2 | #![allow(unexpected_cfgs)] 3 | #![cfg_attr(use_proc_macro_diagnostic, feature(proc_macro_diagnostic))] 4 | extern crate proc_macro; 5 | 6 | // Test utility module 7 | #[cfg(test)] 8 | pub(crate) mod test; 9 | 10 | #[macro_use] 11 | mod error; 12 | mod parse; 13 | mod refident; 14 | mod render; 15 | mod resolver; 16 | mod utils; 17 | 18 | use syn::{parse_macro_input, ItemFn}; 19 | 20 | use crate::parse::{fixture::FixtureInfo, rstest::RsTestInfo}; 21 | use parse::ExtendWithFunctionAttrs; 22 | use quote::ToTokens; 23 | 24 | #[allow(missing_docs)] 25 | #[proc_macro_attribute] 26 | pub fn fixture( 27 | args: proc_macro::TokenStream, 28 | input: proc_macro::TokenStream, 29 | ) -> proc_macro::TokenStream { 30 | let mut info: FixtureInfo = parse_macro_input!(args as FixtureInfo); 31 | let mut fixture = parse_macro_input!(input as ItemFn); 32 | 33 | let extend_result = info.extend_with_function_attrs(&mut fixture); 34 | 35 | let mut errors = error::fixture(&fixture, &info); 36 | 37 | if let Err(attrs_errors) = extend_result { 38 | attrs_errors.to_tokens(&mut errors); 39 | } 40 | 41 | if errors.is_empty() { 42 | render::fixture(fixture, info) 43 | } else { 44 | errors 45 | } 46 | .into() 47 | } 48 | 49 | #[allow(missing_docs)] 50 | #[proc_macro_attribute] 51 | pub fn rstest( 52 | args: proc_macro::TokenStream, 53 | input: proc_macro::TokenStream, 54 | ) -> proc_macro::TokenStream { 55 | let mut test = parse_macro_input!(input as ItemFn); 56 | let mut info = parse_macro_input!(args as RsTestInfo); 57 | 58 | let extend_result = info.extend_with_function_attrs(&mut test); 59 | 60 | let mut errors = error::rstest(&test, &info); 61 | 62 | if let Err(attrs_errors) = extend_result { 63 | attrs_errors.to_tokens(&mut errors); 64 | } 65 | 66 | if errors.is_empty() { 67 | if info.data.has_list_values() { 68 | render::matrix(test, info) 69 | } else if info.data.has_cases() { 70 | render::parametrize(test, info) 71 | } else { 72 | render::single(test, info) 73 | } 74 | } else { 75 | errors 76 | } 77 | .into() 78 | } 79 | -------------------------------------------------------------------------------- /rstest_macros/src/parse/by_ref.rs: -------------------------------------------------------------------------------- 1 | use syn::{visit_mut::VisitMut, ItemFn, Pat}; 2 | 3 | use crate::error::ErrorsVec; 4 | 5 | use super::just_once::JustOnceFnArgAttributeExtractor; 6 | 7 | pub(crate) fn extract_by_ref(item_fn: &mut ItemFn) -> Result, ErrorsVec> { 8 | let mut extractor = JustOnceFnArgAttributeExtractor::from("by_ref"); 9 | extractor.visit_item_fn_mut(item_fn); 10 | extractor.take() 11 | } 12 | 13 | #[cfg(test)] 14 | mod should { 15 | use super::*; 16 | use crate::test::{assert_eq, *}; 17 | use rstest_test::assert_in; 18 | 19 | #[rstest] 20 | #[case("fn simple(a: u32) {}")] 21 | #[case("fn more(a: u32, b: &str) {}")] 22 | #[case("fn gen>(a: u32, b: S) {}")] 23 | #[case("fn attr(#[case] a: u32, #[values(1,2)] b: i32) {}")] 24 | fn not_change_anything_if_no_by_ref_attribute_found(#[case] item_fn: &str) { 25 | let mut item_fn: ItemFn = item_fn.ast(); 26 | let orig = item_fn.clone(); 27 | 28 | let by_refs = extract_by_ref(&mut item_fn).unwrap(); 29 | 30 | assert_eq!(orig, item_fn); 31 | assert!(by_refs.is_empty()); 32 | } 33 | 34 | #[rstest] 35 | #[case::simple("fn f(#[by_ref] a: &u32) {}", "fn f(a: &u32) {}", &["a"])] 36 | #[case::more_than_one( 37 | "fn f(#[by_ref] a: &u32, #[by_ref] b: &String, #[by_ref] c: &std::collection::HashMap) {}", 38 | r#"fn f(a: &u32, 39 | b: &String, 40 | c: &std::collection::HashMap) {}"#, 41 | &["a", "b", "c"])] 42 | fn extract(#[case] item_fn: &str, #[case] expected: &str, #[case] expected_refs: &[&str]) { 43 | let mut item_fn: ItemFn = item_fn.ast(); 44 | let expected: ItemFn = expected.ast(); 45 | 46 | let by_refs = extract_by_ref(&mut item_fn).unwrap(); 47 | 48 | assert_eq!(expected, item_fn); 49 | assert_eq!(by_refs, to_pats!(expected_refs)); 50 | } 51 | 52 | #[rstest] 53 | #[case::no_more_than_one("fn f(#[by_ref] #[by_ref] a: u32) {}", "more than once")] 54 | fn raise_error(#[case] item_fn: &str, #[case] message: &str) { 55 | let mut item_fn: ItemFn = item_fn.ast(); 56 | 57 | let err = extract_by_ref(&mut item_fn).unwrap_err(); 58 | 59 | assert_in!(format!("{:?}", err), message); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rstest_macros/src/parse/context.rs: -------------------------------------------------------------------------------- 1 | use syn::{visit_mut::VisitMut, ItemFn, Pat}; 2 | 3 | use crate::error::ErrorsVec; 4 | 5 | use super::just_once::JustOnceFnArgAttributeExtractor; 6 | 7 | pub(crate) fn extract_context(item_fn: &mut ItemFn) -> Result, ErrorsVec> { 8 | let mut extractor = JustOnceFnArgAttributeExtractor::from("context"); 9 | extractor.visit_item_fn_mut(item_fn); 10 | extractor.take() 11 | } 12 | 13 | #[cfg(test)] 14 | mod should { 15 | use super::*; 16 | use crate::test::{assert_eq, *}; 17 | use rstest_test::assert_in; 18 | 19 | #[rstest] 20 | #[case("fn simple(a: u32) {}")] 21 | #[case("fn more(a: u32, b: &str) {}")] 22 | #[case("fn gen>(a: u32, b: S) {}")] 23 | #[case("fn attr(#[case] a: u32, #[values(1,2)] b: i32) {}")] 24 | fn not_change_anything_if_no_ignore_attribute_found(#[case] item_fn: &str) { 25 | let mut item_fn: ItemFn = item_fn.ast(); 26 | let orig = item_fn.clone(); 27 | 28 | let by_refs = extract_context(&mut item_fn).unwrap(); 29 | 30 | assert_eq!(orig, item_fn); 31 | assert!(by_refs.is_empty()); 32 | } 33 | 34 | #[rstest] 35 | #[case::simple("fn f(#[context] a: u32) {}", "fn f(a: u32) {}", &["a"])] 36 | #[case::more_than_one( 37 | "fn f(#[context] a: u32, #[context] b: String, #[context] c: std::collection::HashMap) {}", 38 | r#"fn f(a: u32, 39 | b: String, 40 | c: std::collection::HashMap) {}"#, 41 | &["a", "b", "c"])] 42 | fn extract(#[case] item_fn: &str, #[case] expected: &str, #[case] expected_refs: &[&str]) { 43 | let mut item_fn: ItemFn = item_fn.ast(); 44 | let expected: ItemFn = expected.ast(); 45 | 46 | let by_refs = extract_context(&mut item_fn).unwrap(); 47 | 48 | assert_eq!(expected, item_fn); 49 | assert_eq!(by_refs, to_pats!(expected_refs)); 50 | } 51 | 52 | #[test] 53 | fn raise_error() { 54 | let mut item_fn: ItemFn = "fn f(#[context] #[context] a: u32) {}".ast(); 55 | 56 | let err = extract_context(&mut item_fn).unwrap_err(); 57 | 58 | assert_in!(format!("{:?}", err), "more than once"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /rstest_macros/src/parse/expressions.rs: -------------------------------------------------------------------------------- 1 | use syn::{ 2 | parse::{Parse, ParseStream, Result}, 3 | Expr, Token, 4 | }; 5 | 6 | pub(crate) struct Expressions(Vec); 7 | 8 | impl Expressions { 9 | pub(crate) fn take(self) -> Vec { 10 | self.0 11 | } 12 | } 13 | 14 | impl Parse for Expressions { 15 | fn parse(input: ParseStream) -> Result { 16 | let values = input 17 | .parse_terminated(Parse::parse, Token![,])? 18 | .into_iter() 19 | .collect(); 20 | Ok(Self(values)) 21 | } 22 | } 23 | 24 | impl From for Vec { 25 | fn from(expressions: Expressions) -> Self { 26 | expressions.0 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /rstest_macros/src/parse/ignore.rs: -------------------------------------------------------------------------------- 1 | use syn::{visit_mut::VisitMut, ItemFn, Pat}; 2 | 3 | use crate::error::ErrorsVec; 4 | 5 | use super::just_once::JustOnceFnArgAttributeExtractor; 6 | 7 | pub(crate) fn extract_ignores(item_fn: &mut ItemFn) -> Result, ErrorsVec> { 8 | let mut extractor = JustOnceFnArgAttributeExtractor::from("ignore"); 9 | extractor.visit_item_fn_mut(item_fn); 10 | extractor.take() 11 | } 12 | 13 | #[cfg(test)] 14 | mod should { 15 | use super::*; 16 | use crate::test::{assert_eq, *}; 17 | use rstest_test::assert_in; 18 | 19 | #[rstest] 20 | #[case("fn simple(a: u32) {}")] 21 | #[case("fn more(a: u32, b: &str) {}")] 22 | #[case("fn gen>(a: u32, b: S) {}")] 23 | #[case("fn attr(#[case] a: u32, #[values(1,2)] b: i32) {}")] 24 | fn not_change_anything_if_no_ignore_attribute_found(#[case] item_fn: &str) { 25 | let mut item_fn: ItemFn = item_fn.ast(); 26 | let orig = item_fn.clone(); 27 | 28 | let by_refs = extract_ignores(&mut item_fn).unwrap(); 29 | 30 | assert_eq!(orig, item_fn); 31 | assert!(by_refs.is_empty()); 32 | } 33 | 34 | #[rstest] 35 | #[case::simple("fn f(#[ignore] a: u32) {}", "fn f(a: u32) {}", &["a"])] 36 | #[case::more_than_one( 37 | "fn f(#[ignore] a: u32, #[ignore] b: String, #[ignore] c: std::collection::HashMap) {}", 38 | r#"fn f(a: u32, 39 | b: String, 40 | c: std::collection::HashMap) {}"#, 41 | &["a", "b", "c"])] 42 | fn extract(#[case] item_fn: &str, #[case] expected: &str, #[case] expected_refs: &[&str]) { 43 | let mut item_fn: ItemFn = item_fn.ast(); 44 | let expected: ItemFn = expected.ast(); 45 | 46 | let by_refs = extract_ignores(&mut item_fn).unwrap(); 47 | 48 | assert_eq!(expected, item_fn); 49 | assert_eq!(by_refs, to_pats!(expected_refs)); 50 | } 51 | 52 | #[test] 53 | fn raise_error() { 54 | let mut item_fn: ItemFn = "fn f(#[ignore] #[ignore] a: u32) {}".ast(); 55 | 56 | let err = extract_ignores(&mut item_fn).unwrap_err(); 57 | 58 | assert_in!(format!("{:?}", err), "more than once"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /rstest_macros/src/parse/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! wrap_attributes { 2 | ($ident:ident) => { 3 | #[derive(Default, Debug, PartialEq, Clone)] 4 | pub(crate) struct $ident { 5 | inner: Attributes, 6 | } 7 | 8 | impl From for $ident { 9 | fn from(inner: Attributes) -> Self { 10 | $ident { inner } 11 | } 12 | } 13 | 14 | impl $ident { 15 | fn iter(&self) -> impl Iterator { 16 | self.inner.attributes.iter() 17 | } 18 | } 19 | 20 | impl $ident { 21 | #[allow(dead_code)] 22 | pub(crate) fn append(&mut self, attr: Attribute) { 23 | self.inner.attributes.push(attr) 24 | } 25 | } 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /rstest_macros/src/parse/testcase.rs: -------------------------------------------------------------------------------- 1 | use syn::{ 2 | parse::{Error, Parse, ParseStream, Result}, 3 | punctuated::Punctuated, 4 | Attribute, Expr, Ident, Token, 5 | }; 6 | 7 | use proc_macro2::TokenStream; 8 | use quote::ToTokens; 9 | 10 | #[derive(PartialEq, Debug, Clone)] 11 | /// A test case instance data. Contains a list of arguments. It is parsed by parametrize 12 | /// attributes. 13 | pub(crate) struct TestCase { 14 | pub(crate) args: Vec, 15 | pub(crate) attrs: Vec, 16 | pub(crate) description: Option, 17 | } 18 | 19 | impl Parse for TestCase { 20 | fn parse(input: ParseStream) -> Result { 21 | let attrs = Attribute::parse_outer(input)?; 22 | let case: Ident = input.parse()?; 23 | if case == "case" { 24 | let mut description = None; 25 | if input.peek(Token![::]) { 26 | let _ = input.parse::(); 27 | description = Some(input.parse()?); 28 | } 29 | let content; 30 | let _ = syn::parenthesized!(content in input); 31 | let args = Punctuated::::parse_terminated(&content)? 32 | .into_iter() 33 | .collect(); 34 | Ok(TestCase { 35 | args, 36 | attrs, 37 | description, 38 | }) 39 | } else { 40 | Err(Error::new(case.span(), "expected a test case")) 41 | } 42 | } 43 | } 44 | 45 | impl ToTokens for TestCase { 46 | fn to_tokens(&self, tokens: &mut TokenStream) { 47 | self.args.iter().for_each(|c| c.to_tokens(tokens)) 48 | } 49 | } 50 | 51 | #[cfg(test)] 52 | mod should { 53 | use super::*; 54 | use crate::test::{assert_eq, *}; 55 | 56 | fn parse_test_case>(test_case: S) -> TestCase { 57 | parse_meta(test_case) 58 | } 59 | 60 | #[test] 61 | fn two_literal_args() { 62 | let test_case = parse_test_case(r#"case(42, "value")"#); 63 | let args = test_case.args(); 64 | 65 | let expected = to_args!(["42", r#""value""#]); 66 | 67 | assert_eq!(expected, args); 68 | } 69 | 70 | #[test] 71 | fn some_literals() { 72 | let args_expressions = literal_expressions_str(); 73 | let test_case = parse_test_case(&format!("case({})", args_expressions.join(", "))); 74 | let args = test_case.args(); 75 | 76 | assert_eq!(to_args!(args_expressions), args); 77 | } 78 | 79 | #[test] 80 | fn accept_arbitrary_rust_code() { 81 | let test_case = parse_test_case(r#"case(vec![1,2,3])"#); 82 | let args = test_case.args(); 83 | 84 | assert_eq!(to_args!(["vec![1, 2, 3]"]), args); 85 | } 86 | 87 | #[test] 88 | #[should_panic] 89 | fn raise_error_on_invalid_rust_code() { 90 | parse_test_case(r#"case(some:<>(1,2,3))"#); 91 | } 92 | 93 | #[test] 94 | fn get_description_if_any() { 95 | let test_case = parse_test_case(r#"case::this_test_description(42)"#); 96 | let args = test_case.args(); 97 | 98 | assert_eq!( 99 | "this_test_description", 100 | &test_case.description.unwrap().to_string() 101 | ); 102 | assert_eq!(to_args!(["42"]), args); 103 | } 104 | 105 | #[test] 106 | fn get_description_also_with_more_args() { 107 | let test_case = parse_test_case(r#"case :: this_test_description (42, 24)"#); 108 | let args = test_case.args(); 109 | 110 | assert_eq!( 111 | "this_test_description", 112 | &test_case.description.unwrap().to_string() 113 | ); 114 | assert_eq!(to_args!(["42", "24"]), args); 115 | } 116 | 117 | #[test] 118 | fn parse_arbitrary_rust_code_as_expression() { 119 | let test_case = parse_test_case( 120 | r##" 121 | case(42, -42, 122 | pippo("pluto"), 123 | Vec::new(), 124 | String::from(r#"prrr"#), 125 | { 126 | let mut sum=0; 127 | for i in 1..3 { 128 | sum += i; 129 | } 130 | sum 131 | }, 132 | vec![1,2,3] 133 | )"##, 134 | ); 135 | 136 | let args = test_case.args(); 137 | 138 | assert_eq!( 139 | to_args!([ 140 | "42", 141 | "-42", 142 | r#"pippo("pluto")"#, 143 | "Vec::new()", 144 | r##"String::from(r#"prrr"#)"##, 145 | r#"{let mut sum=0;for i in 1..3 {sum += i;}sum}"#, 146 | "vec![1,2,3]" 147 | ]), 148 | args 149 | ); 150 | } 151 | 152 | #[test] 153 | fn save_attributes() { 154 | let test_case = parse_test_case(r#"#[should_panic]#[other_attr(x)]case(42)"#); 155 | 156 | let content = format!("{:?}", test_case.attrs); 157 | 158 | assert_eq!(2, test_case.attrs.len()); 159 | assert!(content.contains("should_panic")); 160 | assert!(content.contains("other_attr")); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /rstest_macros/src/parse/vlist.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::ToTokens; 3 | use syn::{ 4 | parse::{Parse, ParseStream, Result}, 5 | Expr, Ident, Pat, Token, 6 | }; 7 | 8 | use crate::refident::IntoPat; 9 | 10 | use super::expressions::Expressions; 11 | 12 | #[derive(Debug, PartialEq, Clone)] 13 | pub(crate) struct Value { 14 | pub(crate) expr: Expr, 15 | pub(crate) description: Option, 16 | } 17 | 18 | impl Value { 19 | pub(crate) fn new(expr: Expr, description: Option) -> Self { 20 | Self { expr, description } 21 | } 22 | 23 | pub(crate) fn description(&self) -> String { 24 | self.description 25 | .clone() 26 | .unwrap_or_else(|| self.expr.to_token_stream().to_string()) 27 | } 28 | } 29 | 30 | impl From for Value { 31 | fn from(expr: Expr) -> Self { 32 | Self::new(expr, None) 33 | } 34 | } 35 | 36 | #[derive(Debug, PartialEq, Clone)] 37 | pub(crate) struct ValueList { 38 | pub(crate) arg: Pat, 39 | pub(crate) values: Vec, 40 | } 41 | 42 | impl Parse for ValueList { 43 | fn parse(input: ParseStream) -> Result { 44 | let ident: Ident = input.parse()?; 45 | let _to: Token![=>] = input.parse()?; 46 | let content; 47 | let paren = syn::bracketed!(content in input); 48 | let values: Expressions = content.parse()?; 49 | 50 | let ret = Self { 51 | arg: ident.into_pat(), 52 | values: values.take().into_iter().map(|e| e.into()).collect(), 53 | }; 54 | if ret.values.is_empty() { 55 | Err(syn::Error::new( 56 | paren.span.join(), 57 | "Values list should not be empty", 58 | )) 59 | } else { 60 | Ok(ret) 61 | } 62 | } 63 | } 64 | 65 | impl ToTokens for ValueList { 66 | fn to_tokens(&self, tokens: &mut TokenStream) { 67 | self.arg.to_tokens(tokens) 68 | } 69 | } 70 | 71 | #[cfg(test)] 72 | mod should { 73 | use crate::test::{assert_eq, *}; 74 | 75 | use super::*; 76 | 77 | mod parse_values_list { 78 | use super::assert_eq; 79 | use super::*; 80 | 81 | fn parse_values_list>(values_list: S) -> ValueList { 82 | parse_meta(values_list) 83 | } 84 | 85 | #[test] 86 | fn some_literals() { 87 | let literals = literal_expressions_str(); 88 | let name = "argument"; 89 | 90 | let values_list = parse_values_list(format!( 91 | r#"{} => [{}]"#, 92 | name, 93 | literals 94 | .iter() 95 | .map(ToString::to_string) 96 | .collect::>() 97 | .join(", ") 98 | )); 99 | 100 | assert_eq!(name, &values_list.arg.display_code()); 101 | assert_eq!(values_list.args(), to_args!(literals)); 102 | } 103 | 104 | #[test] 105 | fn raw_code() { 106 | let values_list = parse_values_list(r#"no_mater => [vec![1,2,3]]"#); 107 | 108 | assert_eq!(values_list.args(), to_args!(["vec![1, 2, 3]"])); 109 | } 110 | 111 | #[test] 112 | #[should_panic] 113 | fn raw_code_with_parsing_error() { 114 | parse_values_list(r#"other => [some:<>(1,2,3)]"#); 115 | } 116 | 117 | #[test] 118 | #[should_panic(expected = r#"expected square brackets"#)] 119 | fn forget_brackets() { 120 | parse_values_list(r#"other => 42"#); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /rstest_macros/src/refident.rs: -------------------------------------------------------------------------------- 1 | /// Provide `RefIdent` and `MaybeIdent` traits that give a shortcut to extract identity reference 2 | /// (`syn::Ident` struct). 3 | use proc_macro2::Ident; 4 | use syn::{FnArg, Pat, PatType, Type}; 5 | 6 | pub trait RefIdent { 7 | /// Return the reference to ident if any 8 | fn ident(&self) -> &Ident; 9 | } 10 | 11 | pub trait MaybeIdent { 12 | /// Return the reference to ident if any 13 | fn maybe_ident(&self) -> Option<&Ident>; 14 | } 15 | 16 | impl MaybeIdent for I { 17 | fn maybe_ident(&self) -> Option<&Ident> { 18 | Some(self.ident()) 19 | } 20 | } 21 | 22 | impl RefIdent for Ident { 23 | fn ident(&self) -> &Ident { 24 | self 25 | } 26 | } 27 | 28 | impl RefIdent for &'_ Ident { 29 | fn ident(&self) -> &Ident { 30 | self 31 | } 32 | } 33 | 34 | impl MaybeIdent for FnArg { 35 | fn maybe_ident(&self) -> Option<&Ident> { 36 | match self { 37 | FnArg::Typed(pat) => pat.maybe_ident(), 38 | _ => None, 39 | } 40 | } 41 | } 42 | 43 | impl MaybeIdent for PatType { 44 | fn maybe_ident(&self) -> Option<&Ident> { 45 | self.pat.maybe_ident() 46 | } 47 | } 48 | 49 | impl MaybeIdent for Pat { 50 | fn maybe_ident(&self) -> Option<&Ident> { 51 | match self { 52 | Pat::Ident(ident) => Some(&ident.ident), 53 | _ => None, 54 | } 55 | } 56 | } 57 | 58 | impl MaybeIdent for Type { 59 | fn maybe_ident(&self) -> Option<&Ident> { 60 | match self { 61 | Type::Path(tp) if tp.qself.is_none() => tp.path.get_ident(), 62 | _ => None, 63 | } 64 | } 65 | } 66 | 67 | pub trait MaybeType { 68 | /// Return the reference to type if any 69 | fn maybe_type(&self) -> Option<&Type>; 70 | } 71 | 72 | impl MaybeType for FnArg { 73 | fn maybe_type(&self) -> Option<&Type> { 74 | match self { 75 | FnArg::Typed(PatType { ty, .. }) => Some(ty.as_ref()), 76 | _ => None, 77 | } 78 | } 79 | } 80 | 81 | impl MaybeIdent for syn::GenericParam { 82 | fn maybe_ident(&self) -> Option<&Ident> { 83 | match self { 84 | syn::GenericParam::Type(syn::TypeParam { ident, .. }) 85 | | syn::GenericParam::Const(syn::ConstParam { ident, .. }) => Some(ident), 86 | syn::GenericParam::Lifetime(syn::LifetimeParam { lifetime, .. }) => { 87 | Some(&lifetime.ident) 88 | } 89 | } 90 | } 91 | } 92 | 93 | impl MaybeIdent for crate::parse::Attribute { 94 | fn maybe_ident(&self) -> Option<&Ident> { 95 | use crate::parse::Attribute::*; 96 | match self { 97 | Attr(ident) | Tagged(ident, _) | Type(ident, _) => Some(ident), 98 | } 99 | } 100 | } 101 | 102 | pub trait RefPat { 103 | /// Return the reference to ident if any 104 | fn pat(&self) -> &Pat; 105 | } 106 | 107 | pub trait MaybePatIdent { 108 | fn maybe_patident(&self) -> Option<&syn::PatIdent>; 109 | } 110 | 111 | impl MaybePatIdent for FnArg { 112 | fn maybe_patident(&self) -> Option<&syn::PatIdent> { 113 | match self { 114 | FnArg::Typed(PatType { pat, .. }) => match pat.as_ref() { 115 | Pat::Ident(ident) => Some(ident), 116 | _ => None, 117 | }, 118 | _ => None, 119 | } 120 | } 121 | } 122 | 123 | impl MaybePatIdent for Pat { 124 | fn maybe_patident(&self) -> Option<&syn::PatIdent> { 125 | match self { 126 | Pat::Ident(ident) => Some(ident), 127 | _ => None, 128 | } 129 | } 130 | } 131 | 132 | pub trait MaybePatType { 133 | fn maybe_pat_type(&self) -> Option<&syn::PatType>; 134 | } 135 | 136 | impl MaybePatType for FnArg { 137 | fn maybe_pat_type(&self) -> Option<&syn::PatType> { 138 | match self { 139 | FnArg::Typed(pt) => Some(pt), 140 | _ => None, 141 | } 142 | } 143 | } 144 | 145 | pub trait MaybePatTypeMut { 146 | fn maybe_pat_type_mut(&mut self) -> Option<&mut syn::PatType>; 147 | } 148 | 149 | impl MaybePatTypeMut for FnArg { 150 | fn maybe_pat_type_mut(&mut self) -> Option<&mut syn::PatType> { 151 | match self { 152 | FnArg::Typed(pt) => Some(pt), 153 | _ => None, 154 | } 155 | } 156 | } 157 | 158 | pub trait MaybePat { 159 | fn maybe_pat(&self) -> Option<&syn::Pat>; 160 | } 161 | 162 | impl MaybePat for FnArg { 163 | fn maybe_pat(&self) -> Option<&syn::Pat> { 164 | match self { 165 | FnArg::Typed(PatType { pat, .. }) => Some(pat.as_ref()), 166 | _ => None, 167 | } 168 | } 169 | } 170 | 171 | pub trait RemoveMutability { 172 | fn remove_mutability(&mut self); 173 | } 174 | 175 | impl RemoveMutability for FnArg { 176 | fn remove_mutability(&mut self) { 177 | if let FnArg::Typed(PatType { pat, .. }) = self { 178 | if let Pat::Ident(ident) = pat.as_mut() { 179 | ident.mutability = None 180 | } 181 | }; 182 | } 183 | } 184 | 185 | pub trait IntoPat { 186 | fn into_pat(self) -> Pat; 187 | } 188 | 189 | impl IntoPat for Ident { 190 | fn into_pat(self) -> Pat { 191 | Pat::Ident(syn::PatIdent { 192 | attrs: vec![], 193 | by_ref: None, 194 | mutability: None, 195 | ident: self, 196 | subpat: None, 197 | }) 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /rstest_macros/src/render/crate_resolver.rs: -------------------------------------------------------------------------------- 1 | use syn::parse_quote; 2 | 3 | pub fn crate_name() -> syn::Path { 4 | cfg_if::cfg_if! { 5 | if #[cfg(feature = "crate-name")] { 6 | use proc_macro_crate::FoundCrate; 7 | use quote::format_ident; 8 | 9 | match proc_macro_crate::crate_name("rstest").expect("rstest is present in `Cargo.toml` qed") 10 | { 11 | FoundCrate::Itself => parse_quote! { rstest }, 12 | FoundCrate::Name(name) => { 13 | let myself = format_ident!("{name}"); 14 | parse_quote! { #myself } 15 | } 16 | } 17 | } else { 18 | parse_quote! { rstest } 19 | } 20 | } 21 | } 22 | 23 | pub fn std_path() -> syn::Path { 24 | let rstest = crate_name(); 25 | parse_quote! { #rstest::__std } 26 | } 27 | -------------------------------------------------------------------------------- /rstest_macros/src/render/wrapper.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::{quote, ToTokens}; 3 | use syn::Ident; 4 | 5 | pub(crate) trait WrapByModule { 6 | fn wrap_by_mod(&self, mod_name: &Ident) -> TokenStream; 7 | } 8 | 9 | impl WrapByModule for T { 10 | fn wrap_by_mod(&self, mod_name: &Ident) -> TokenStream { 11 | quote! { 12 | mod #mod_name { 13 | use super::*; 14 | 15 | #self 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /rstest_reuse/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Michele d'Amico "] 3 | categories = ["development-tools::testing"] 4 | description = """ 5 | Reuse rstest attributes: create a set of tests and apply it 6 | to every scenario you want to test. 7 | """ 8 | edition = "2021" 9 | homepage = "https://github.com/la10736/rstest" 10 | keywords = ["test", "fixture"] 11 | license = "MIT OR Apache-2.0" 12 | name = "rstest_reuse" 13 | readme = "README.md" 14 | repository = "https://github.com/la10736/rstest" 15 | rust-version = "1.63.0" 16 | version = "0.7.0" 17 | 18 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 19 | 20 | [lib] 21 | proc-macro = true 22 | 23 | [dependencies] 24 | quote = "1.0.37" 25 | rand = "0.8.5" 26 | syn = { version = "2.0.79", features = ["full", "extra-traits"] } 27 | 28 | [dev-dependencies] 29 | lazy_static = "1.5.0" 30 | rstest_test = { path = "../rstest_test" } 31 | temp_testdir = "0.2.3" 32 | # To compile doc tests 33 | rstest = { version = "0.23.0" } 34 | -------------------------------------------------------------------------------- /rstest_reuse/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /rstest_reuse/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /rstest_reuse/checkoutlist.md: -------------------------------------------------------------------------------- 1 | # TODO list 2 | 3 | - [ ] Update rustup 4 | - [ ] Update dependency `cargo upgrade` 5 | - [ ] Run all test 6 | - [ ] Stable: `RSTEST_TEST_CHANNEL=stable cargo +${RSTEST_TEST_CHANNEL} test` 7 | - [ ] Beta: `RSTEST_TEST_CHANNEL=beta cargo +${RSTEST_TEST_CHANNEL} test` 8 | - [ ] Nightly: `RSTEST_TEST_CHANNEL=nightly cargo +${RSTEST_TEST_CHANNEL} test` 9 | - [ ] Check Cargo.toml version 10 | - [ ] Check README 11 | - [ ] prepare deploy `cargo publish --dry-run` 12 | - [ ] deploy `cargo publish` 13 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/copy_args_attributes_from_template.rs: -------------------------------------------------------------------------------- 1 | use rstest_reuse; 2 | 3 | mod cases { 4 | use rstest::rstest; 5 | use rstest_reuse::*; 6 | 7 | #[template] 8 | #[rstest] 9 | #[case(2, 2)] 10 | #[case(4/2, 2)] 11 | fn copy_cases(#[case] a: u32, #[case] b: u32) {} 12 | 13 | #[apply(copy_cases)] 14 | fn it_works(a: u32, b: u32) { 15 | assert!(a == b); 16 | } 17 | 18 | #[apply(copy_cases)] 19 | fn should_not_copy_attributes_if_already_present(#[case] a: u32, b: u32) { 20 | assert!(a == b); 21 | } 22 | 23 | #[apply(copy_cases)] 24 | #[case::more(8/4, 2)] 25 | fn add_a_case(a: u32, b: u32) { 26 | assert!(a == b); 27 | } 28 | 29 | #[apply(copy_cases)] 30 | fn add_values(a: u32, b: u32, #[values(1, 2, 3)] _add_some_tests: u32) { 31 | assert!(a == b); 32 | } 33 | 34 | #[apply(copy_cases)] 35 | fn should_copy_cases_also_from_underscored_attrs(_a: u32, _b: u32) {} 36 | } 37 | 38 | mod values { 39 | use rstest::rstest; 40 | use rstest_reuse::*; 41 | 42 | #[template] 43 | #[rstest] 44 | fn copy_values(#[values(1, 2)] cases: u32) {} 45 | 46 | #[apply(copy_values)] 47 | fn it_works(cases: u32) { 48 | assert!([1, 2].contains(&cases)); 49 | } 50 | 51 | #[apply(copy_values)] 52 | #[case::more(8/4, 2)] 53 | fn add_a_case(#[case] a: u32, #[case] b: u32, cases: u32) { 54 | assert!([1, 2].contains(&cases)); 55 | assert!(a == b); 56 | } 57 | 58 | #[apply(copy_values)] 59 | fn add_values(#[values(3, 4)] a: u32, cases: u32) { 60 | assert!([1, 2].contains(&cases)); 61 | assert!([3, 4].contains(&a)); 62 | } 63 | 64 | #[apply(copy_values)] 65 | fn should_copy_values_also_from_underscored_attrs(_cases: u32) {} 66 | } 67 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/deny_docs.rs: -------------------------------------------------------------------------------- 1 | #![deny(missing_docs)] 2 | 3 | //! We should provide also a docs for the crate itself if we set `#![deny(missing_docs)]`. 4 | 5 | use rstest::rstest; 6 | use rstest_reuse::{self, *}; 7 | 8 | #[template] 9 | #[rstest(a, b, case(2, 2), case(4/2, 2))] 10 | fn two_simple_cases(a: u32, b: u32) {} 11 | 12 | #[apply(two_simple_cases)] 13 | fn it_works(a: u32, b: u32) { 14 | assert!(a == b); 15 | } 16 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/export_not_used.rs: -------------------------------------------------------------------------------- 1 | mod foo { 2 | use rstest_reuse::template; 3 | 4 | #[template] 5 | #[export] 6 | #[rstest] 7 | #[case("bar")] 8 | fn not_used(#[case] s: &str) {} 9 | } 10 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/export_template.rs: -------------------------------------------------------------------------------- 1 | use rstest_reuse; 2 | 3 | mod foo { 4 | pub(crate) mod bar { 5 | use rstest::rstest; 6 | use rstest_reuse::{self, *}; 7 | 8 | #[template] 9 | #[export] 10 | #[rstest] 11 | #[case("bar")] 12 | fn my_template(#[case] s: &str) {} 13 | 14 | #[apply(my_template)] 15 | fn test(#[case] s: &str) { 16 | assert_eq!("bar", s); 17 | } 18 | } 19 | } 20 | 21 | use rstest::rstest; 22 | use rstest_reuse::*; 23 | 24 | #[apply(foo::bar::my_template)] 25 | fn test_path(#[case] s: &str) { 26 | assert_eq!("bar", s); 27 | } 28 | 29 | use foo::bar::my_template; 30 | #[apply(my_template)] 31 | fn test_import(#[case] s: &str) { 32 | assert_eq!("bar", s); 33 | } 34 | 35 | #[template] 36 | #[export] 37 | #[rstest] 38 | #[case("bar")] 39 | fn root_level(#[case] s: &str) {} 40 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/export_template_root.rs: -------------------------------------------------------------------------------- 1 | pub use rstest_reuse; 2 | use rstest_reuse::template; 3 | 4 | #[template] 5 | #[export] 6 | #[rstest] 7 | #[case("bar")] 8 | fn root_level(#[case] s: &str) {} 9 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/import_template.rs: -------------------------------------------------------------------------------- 1 | use export_template_root::root_level; 2 | use rstest::*; 3 | use rstest_reuse::apply; 4 | 5 | #[apply(root_level)] 6 | fn test(#[case] s: &str) { 7 | assert_eq!("bar", s); 8 | } 9 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/in_mod.rs: -------------------------------------------------------------------------------- 1 | use rstest_reuse; 2 | 3 | mod sub { 4 | use rstest::rstest; 5 | use rstest_reuse::*; 6 | 7 | #[template] 8 | #[rstest(a, b, case(2, 2), case(4/2, 2))] 9 | fn two_simple_cases(a: u32, b: u32) {} 10 | 11 | #[apply(two_simple_cases)] 12 | fn it_works(a: u32, b: u32) { 13 | assert!(a == b); 14 | } 15 | 16 | #[apply(two_simple_cases)] 17 | fn it_fail(a: u32, b: u32) { 18 | assert!(a != b); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/no_local_macro_should_not_compile.rs: -------------------------------------------------------------------------------- 1 | use rstest_reuse; 2 | 3 | mod foo { 4 | use rstest_reuse::{self, *}; 5 | 6 | #[template] 7 | #[rstest] 8 | #[case("bar")] 9 | fn my_template(#[case] s: &str) {} 10 | } 11 | use rstest::rstest; 12 | use rstest_reuse::apply; 13 | 14 | #[apply(my_template)] 15 | fn test(#[case] s: &str) { 16 | assert_eq!("bar", s); 17 | } 18 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/not_used.rs: -------------------------------------------------------------------------------- 1 | mod foo { 2 | use rstest_reuse::template; 3 | 4 | #[template] 5 | #[rstest] 6 | #[case("bar")] 7 | fn not_used(#[case] s: &str) {} 8 | } 9 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/qualify_template_use.rs: -------------------------------------------------------------------------------- 1 | use rstest_reuse; 2 | 3 | mod template { 4 | use rstest::rstest; 5 | use rstest_reuse::template; 6 | 7 | #[template] 8 | #[rstest(a, b, case(2, 2), case(4/2, 2))] 9 | fn two_simple_cases(a: u32, b: u32) {} 10 | } 11 | 12 | mod user { 13 | use rstest::rstest; 14 | use rstest_reuse::apply; 15 | use crate::template::two_simple_cases; 16 | 17 | #[apply(two_simple_cases)] 18 | fn it_works(a: u32, b: u32) { 19 | assert!(a == b); 20 | } 21 | } 22 | 23 | mod qualify { 24 | use rstest::rstest; 25 | use rstest_reuse::apply; 26 | 27 | #[apply(crate::template::two_simple_cases)] 28 | fn it_works(a: u32, b: u32) { 29 | assert!(a == b); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/rstest_reuse_not_in_crate_root.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | use rstest_reuse::apply; 3 | use rstest_reuse::template; 4 | 5 | #[template] 6 | #[rstest] 7 | #[case(42)] 8 | fn test_template(#[case] n: u32) {} 9 | 10 | #[apply(test_template)] 11 | fn test(#[case] n: u32) { 12 | assert_eq!(n, 42); 13 | } 14 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/simple_example.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | use rstest_reuse::*; 3 | 4 | #[template] 5 | #[rstest(a, b, case(2, 2), case(4/2, 2))] 6 | fn two_simple_cases(a: u32, b: u32) {} 7 | 8 | #[apply(two_simple_cases)] 9 | fn it_works(a: u32, b: u32) { 10 | assert!(a == b); 11 | } 12 | 13 | #[apply(two_simple_cases)] 14 | fn it_fail(a: u32, b: u32) { 15 | assert!(a != b); 16 | } 17 | 18 | #[apply(two_simple_cases)] 19 | #[should_panic] 20 | fn it_fail_but_ok(a: u32, b: u32) { 21 | assert!(a != b); 22 | } 23 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/templates_with_same_name.rs: -------------------------------------------------------------------------------- 1 | use rstest_reuse; 2 | 3 | mod inner1 { 4 | use rstest::rstest; 5 | use rstest_reuse::*; 6 | 7 | #[template] 8 | #[rstest(a, b, case(2, 2), case(4/2, 2))] 9 | fn my_template(a: u32, b: u32) {} 10 | 11 | #[apply(my_template)] 12 | fn it_works(a: u32, b: u32) { 13 | assert!(a == b); 14 | } 15 | } 16 | 17 | mod inner2 { 18 | use rstest::rstest; 19 | use rstest_reuse::*; 20 | 21 | #[template] 22 | #[rstest(a, case(2), case(4))] 23 | fn my_template(a: u32) {} 24 | 25 | #[apply(my_template)] 26 | fn it_works(a: u32) {} 27 | } 28 | -------------------------------------------------------------------------------- /rstest_reuse/tests/resources/use_before_define.rs: -------------------------------------------------------------------------------- 1 | use rstest::rstest; 2 | use rstest_reuse::{self, *}; 3 | 4 | #[apply(two_simple_cases)] 5 | fn it_works(a: u32, b: u32) { 6 | assert!(a == b); 7 | } 8 | 9 | #[template] 10 | #[rstest(a, b, case(2, 2), case(4/2, 2))] 11 | fn two_simple_cases(a: u32, b: u32) {} 12 | -------------------------------------------------------------------------------- /rstest_test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["Michele d'Amico "] 3 | categories = ["development-tools::testing"] 4 | description = """ 5 | Provides some utilities used by to write rstest crate's tests. 6 | """ 7 | edition = "2021" 8 | homepage = "https://github.com/la10736/rstest" 9 | keywords = ["test"] 10 | license = "MIT OR Apache-2.0" 11 | name = "rstest_test" 12 | readme = "README.md" 13 | repository = "https://github.com/la10736/rstest" 14 | rust-version = "1.69.0" 15 | version = "0.14.0" 16 | 17 | [dependencies] 18 | rand = "0.9.0" 19 | regex = "1.10.6" 20 | toml_edit = "=0.21.0" 21 | 22 | [dev-dependencies] 23 | lazy_static = "1.5.0" 24 | rstest = { version = "0.23.0", default-features = false } 25 | temp_testdir = "0.2.3" 26 | -------------------------------------------------------------------------------- /rstest_test/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /rstest_test/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /rstest_test/README.md: -------------------------------------------------------------------------------- 1 | [![Crate][crate-image]][crate-link] 2 | [![Status][test-action-image]][test-action-link] 3 | [![Apache 2.0 Licensed][license-apache-image]][license-apache-link] 4 | [![MIT Licensed][license-mit-image]][license-mit-link] 5 | 6 | # Helper crate for testing `rstest` crate 7 | 8 | This crate provides a little framework for writing end-to-end test. You can create rust 9 | project, add workspace modules and code file. Run `build` and `test` actions and write 10 | assertions based on passed and failed tests. 11 | 12 | Moreover give some utilities on assertions, strings manipulations and test name. 13 | 14 | This crate isn't designed for general purpose use but just as `rstest` develop helper crate. 15 | 16 | ## License 17 | 18 | Licensed under either of 19 | 20 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or 21 | [license-apache-link]) 22 | 23 | * MIT license [LICENSE-MIT](LICENSE-MIT) or [license-MIT-link] 24 | at your option. 25 | 26 | [//]: # (links) 27 | 28 | [crate-image]: https://img.shields.io/crates/v/rstest_test.svg 29 | [crate-link]: https://crates.io/crates/rstest_test 30 | [test-action-image]: https://github.com/la10736/rstest/workflows/Test/badge.svg 31 | [test-action-link]: https://github.com/la10736/rstest/actions?query=workflow:Test 32 | [license-apache-image]: https://img.shields.io/badge/license-Apache2.0-blue.svg 33 | [license-mit-image]: https://img.shields.io/badge/license-MIT-blue.svg 34 | [license-apache-link]: http://www.apache.org/licenses/LICENSE-2.0 35 | [license-MIT-link]: http://opensource.org/licenses/MIT 36 | -------------------------------------------------------------------------------- /rstest_test/checkoutlist.md: -------------------------------------------------------------------------------- 1 | # TODO list 2 | 3 | - [ ] Update rustup 4 | - [ ] Update dependency `cargo upgrade` 5 | - [ ] Run all test 6 | - [ ] Stable: `RSTEST_TEST_CHANNEL=stable cargo +${RSTEST_TEST_CHANNEL} test` 7 | - [ ] Beta: `RSTEST_TEST_CHANNEL=beta cargo +${RSTEST_TEST_CHANNEL} test` 8 | - [ ] Nightly: `RSTEST_TEST_CHANNEL=nightly cargo +${RSTEST_TEST_CHANNEL} test` 9 | - [ ] Change next version 10 | - [ ] `Cargo.toml` 11 | - [ ] prepare deploy `cargo publish --dry-run` 12 | - [ ] deploy `cargo publish` 13 | -------------------------------------------------------------------------------- /rstest_test/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use regex; 2 | 3 | pub mod prj; 4 | pub mod utils; 5 | 6 | pub use prj::Project; 7 | pub use utils::*; 8 | -------------------------------------------------------------------------------- /rstest_test/tests/macros.rs: -------------------------------------------------------------------------------- 1 | use rstest_test::{assert_all_in, assert_in, assert_not_in, assert_regex}; 2 | 3 | #[test] 4 | fn assert_in_should_find_string() { 5 | assert_in!( 6 | "messege that firtspart 7 | continue. 8 | some other", 9 | "part 10 | cont" 11 | ); 12 | } 13 | 14 | #[test] 15 | #[should_panic] 16 | fn assert_in_should_panic_if_no_string_in_message() { 17 | assert_in!( 18 | "messege that firtspart 19 | continue. 20 | some other", 21 | "something else" 22 | ); 23 | } 24 | 25 | #[test] 26 | #[should_panic] 27 | fn assert_in_should_panic_if_empty() { 28 | assert_in!("", "a"); 29 | } 30 | 31 | #[test] 32 | #[should_panic(expected = "supercalifragili")] 33 | fn assert_in_should_yield_text_if_fail() { 34 | assert_in!("supercalifragili", "x"); 35 | } 36 | 37 | #[test] 38 | #[should_panic(expected = "xxx")] 39 | fn assert_in_should_yield_message_if_fail() { 40 | assert_in!("supercalifragili", "xxx"); 41 | } 42 | 43 | #[test] 44 | fn assert_all_in_should_check_all_clause() { 45 | assert_all_in!("supercalifragili", "ercal", "alifrag", "percal"); 46 | } 47 | 48 | #[test] 49 | #[should_panic(expected = "xxx")] 50 | fn assert_all_in_should_check_all_clause_and_fail() { 51 | assert_all_in!("supercalifragili", "ercal", "alifrag", "xxx"); 52 | } 53 | 54 | #[test] 55 | #[should_panic(expected = "xxx")] 56 | fn assert_all_in_should_raise_the_first_that_didnt_match() { 57 | assert_all_in!("supercalifragili", "ercal", "xxx", "yyy", "lifragi"); 58 | } 59 | 60 | #[test] 61 | #[should_panic] 62 | fn assert_not_in_should_find_string() { 63 | assert_not_in!( 64 | "messege that firtspart 65 | continue. 66 | some other", 67 | "part 68 | cont" 69 | ); 70 | } 71 | 72 | #[test] 73 | fn assert_not_in_pass_if_no_string_in_message() { 74 | assert_not_in!( 75 | "messege that firtspart 76 | continue. 77 | some other", 78 | "something else" 79 | ); 80 | } 81 | 82 | #[test] 83 | fn assert_not_in_should_pass_if_empty() { 84 | assert_not_in!("", "a"); 85 | } 86 | 87 | #[test] 88 | #[should_panic(expected = "supercalifragili")] 89 | fn assert_not_in_should_yield_text_if_fail() { 90 | assert_not_in!("supercalifragili", "rcal"); 91 | } 92 | 93 | #[test] 94 | #[should_panic(expected = "rcal")] 95 | fn assert_not_in_should_yield_message_if_fail() { 96 | assert_not_in!("supercalifragili", "rcal"); 97 | } 98 | 99 | #[test] 100 | fn assert_regex_should_find_string() { 101 | assert_regex!( 102 | "ege .+ firts", 103 | "messege that firtspart 104 | continue. 105 | some other" 106 | ); 107 | } 108 | 109 | #[test] 110 | #[should_panic] 111 | fn assert_regex_should_panic_if_message_dont_match() { 112 | assert_regex!("ege .*", "something else"); 113 | } 114 | 115 | #[test] 116 | #[should_panic(expected = "supercalifragili")] 117 | fn assert_regex_should_yield_text_if_fail() { 118 | assert_regex!("x", "supercalifragili"); 119 | } 120 | 121 | #[test] 122 | #[should_panic(expected = "xxx")] 123 | fn assert_regex_should_yield_regex_if_fail() { 124 | assert_regex!("xxx", "supercalifragili"); 125 | } 126 | --------------------------------------------------------------------------------