testify/lib.rs
1//! This library provides an extended test suite that allows better and easier organization and
2//! management of your tests. It has support for async tests with tokio out of the box.
3//!
4//! # Setup
5//!
6//! To set up the testify test suite, you'll need to add `testify-rs` to your project's
7//! dependencies, and to install `testify` via `cargo install testify-rs`. The last one will only
8//! set up the `cargo testify` command, which you'll use to run your tests from now on.
9//!
10//! ## Features
11//!
12//! These are the features you can enable in your project:
13//! - `async-tokio`: Enable support for async tests using tokio as the runtime.
14//!
15//! # Usage
16//!
17//! To set up the tests runner, wrap your `main()` function with `#[testify::main]`. This'll expand
18//! to (roughly)
19//! ```
20//! fn main() {
21//! if std::env::var("DO_NOT_MANUALLY_SET_TESTIFY_ARE_TESTS_BEING_RUN").is_ok() {
22//! testify::run();
23//! } else {
24//! /* YOUR CODE */
25//! }
26//! }
27//! ```
28//!
29//! > *This means that the testing code will be built into your binary from now onwards.
30//! > Suggestions and PRs are welcome to solve this issue.*
31//!
32//! After wrapping your main function with testify's main macro, you're ready to go. In case you
33//! already have any tests set up in your project, replace `#[test]` with `#[testify::test]` and
34//! that will be enough for your code to run in most cases.
35//!
36//! ## The `#[testify::test]` macro
37//!
38//! As you've seen in the previous section, replacing `#[test]` with `#[testify::test]` should be
39//! enough to get you started in most cases. Testify's test macro supports a wider set of features
40//! than the default one.
41//!
42//! ### Test Metadata
43//!
44//! You can organize your tests better by passing some keyword arguments to the test macro (all
45//! optional):
46//! - `name`: A string literal, which allows you to rename the test function to something prettier
47//! to be outputted in the console when running the tests.
48//! - `case`: A string literal, it allows you to specify different cases of the same unit being
49//! tested.
50//! - `tags`: An array of string literals, it allows you to tag your tests for easier filtering
51//! when running your tests with `cargo testify`, opposed to rust's default test suite with its
52//! substring filtering.
53//! - `should_panic`: As the name says, passing this argument to the test macro will make the test
54//! execution being expected to panic, and failing if it does not.
55//! - `should_fail`: Similar to `should_panic`, but for the return types of the test function. In
56//! this case, `TestTermination.success()` will be expected to return `false`.
57//!
58//! #### Example
59//!
60//! ```
61//! // All of the arguments passed to the macro are optional.
62//! #[testify::test(
63//! name = "Register User",
64//! case = "Weak Password",
65//! tags = ["api", "auth"],
66//! should_fail
67//! )]
68//! fn my_test() -> Result<(), String> {
69//! /* RUN YOUR CODE */
70//! Err("The password was too weak.".into())
71//! }
72//! ```
73//!
74//! ### Async Support
75//!
76//! Tests support async functions out of the box with the `async-tokio` feature. It's as easy as
77//! making your test async for it to run in a tokio runtime.
78//!
79//! ```
80//! #[testify::test]
81//! async fn my_async_test() {
82//! /* RUN YOUR CODE */
83//! }
84//! ```
85//!
86//! ### The `TestTermination` Trait
87//!
88//! All your tests' return type must implement `TestTermination`. It's a simple trait that only has
89//! one method, `success() -> bool`, which returns whether the test has failed or not. There are
90//! some provided default implementations, but you're free to implement yours if the default
91//! options do not fit your use case.
92//!
93//! #### Default Implementations
94//!
95//! The trait is implemented by default for:
96//!
97//! - `Result<T: TestTermination, E>`: This'll fail in case of an error, otherwise run `.success()`
98//! for the returned value and return it.
99//! - `Option<T: TestTermination>`: This'll fail if `None`, otherwise run `.success()` for the
100//! returned value and return it.
101//! - `()`: This will always return true.
102//!
103//! #### Example
104//!
105//! ```
106//! use testify::TestTermination;
107//!
108//! // This is how the trait is implemented for this type internally.
109//! impl<T: TestTermination, E> TestTermination for Result<T, E> {
110//! fn success(&self) -> bool {
111//! match self {
112//! Ok(inner) => inner.success(),
113//! Err(_) => false
114//! }
115//! }
116//! }
117//! ```
118//!
119//! ## The `#[testify::setup]` and `#[testify::cleanup]` Macros
120//!
121//! These two macros allow you to set up the test environment before the execution of the tests,
122//! and to clean it up after the tests have passed.
123//!
124//! ### Example
125//!
126//! ```
127//! #[testify::main]
128//! fn main() {}
129//!
130//! #[testify::test]
131//! async fn test_db() {
132//! /* CODE THAT REQUIRES A DB */
133//! }
134//!
135//! #[testify::setup]
136//! async fn setup() {
137//! backup_dev_db_and_setup_test_one().await;
138//! }
139//!
140//! #[testify::cleanup]
141//! async fn cleanup() {
142//! destroy_test_db_and_restore_dev_db_backup().await;
143//! }
144//! ```
145//!
146//! There's no need to have both a setup and a cleanup function either. You may use them
147//! individually. Both `setup` and `cleanup` functions support both sync and async (with the
148//! `async-tokio` feature enabled).
149//!
150//! ## Using `cargo testify`
151//!
152//! Tests are run using the testify command `cargo testify-rs`. It's a command line tool that allows
153//! you to configure the way in which your tests are run. In case you haven't installed it yet, run
154//! `cargo install testify` to set it up.
155//!
156//! ```
157//! $ cargo testify --help
158//! ```
159//!
160//! ### Filtering by Name
161//!
162//! The default `cargo test` command allows you to filter your tests by a substring of the test's
163//! name. Testify goes a bit further by allowing you to use glob pattern matching to filter by
164//! name.
165//!
166//! ```
167//! $ cargo testify hello*
168//! ```
169//!
170//! ### Filtering by Tag
171//!
172//! You can also filter by the tags you've set in your tests by passing the `--tag` argument to the
173//! `cargo testify` command.
174//!
175//! ```
176//! // Both --tag and -t do the same
177//! $ cargo testify --tag auth -t api
178//! ```
179//!
180//! You can also exclude tags by passing the `--exclude-tag` argument:
181//!
182//! ```
183//! $ cargo testify --exclude-tag db
184//! // -e for the shortcut
185//! ```
186//!
187//! ### Fast Failing
188//!
189//! If you only care about whether all tests pass or not, you can pass the `--fail-fast` argument.
190//! This'll stop testing on the first test that fails. You'll see a `Failed! Aborted.` next to the
191//! failing test, in case there's any.
192
193#[doc(hidden)]
194pub use testify_core::*;
195
196pub use testify_macros::*;
197
198#[doc(hidden)]
199pub use ctor;