cargo_is_tested/
lib.rs

1//!<h1 align="center">cargo-is-tested</h1>
2//!<div align="center">
3//!	<a href="https://github.com/blyxyas/cargo-is-tested">
4//!		<img src="https://img.shields.io/badge/github--9cf?style=for-the-badge&logo=github" />
5//!	</a>
6//!	<a href="https://crates.io/crates/cargo-is-tested">
7//!		<img src="https://img.shields.io/badge/Crates.io--fc8d62?style=for-the-badge&labelColor=555555&logo=rust">
8//!	</a>
9//!	<a href="https://docs.rs/cargo-is-tested">
10//!		<img src="https://img.shields.io/badge/Docs.rs--66c2a5?style=for-the-badge&logo=docs.rs">
11//!	</a>
12//! <a href="https://blyxyas.github.io/cargo-is-tested">
13//!	<img src="https://img.shields.io/badge/Book--B597FC?style=for-the-badge&logo=mdbook">
14//!	</a>
15//!</div>
16//!<br>
17//!
18//!`cargo-is-tested` is a way to check which of your items are tested in which aren't, very configurable and with a scripting-friendly API ready to use with your Git hooks.
19//!
20//!Also, is uses *✨ pretty colors ✨* for error reporting.
21//! 
22//! #### You can also [read the book](https://blyxyas.github.io/cargo-is-tested) for a more user-friendly guide.
23//!
24//!## Example
25//!
26//!To check if all functions are tested in the current directory.
27//!
28//!```bash
29//!$ cargo is-tested .
30//!```
31//!
32//!```toml
33//!# Cargo.toml
34//!# [...]
35//!
36//![dependencies]
37//!is_tested = "0.1.1" # Check crates.io for the current version of the crate.
38//!
39//!# [...]
40//!```
41//!
42//!```rust, ignore
43//!// src/main.rs
44//!
45//!#! is-tested emptiness
46//!// Yes, it uses shebangs to enable testing and flags!
47//!
48//!use is_tested::is_tested;
49//!
50//!#[is_tested("test/myfunction_testing_path.rs")]
51//!fn my_function() {
52//!	// [...]
53//!}
54//!```
55//!
56//!Then, it will check if `test/myfunction_testing_path.rs` exists, if it doesn't, it will output an error.
57//!
58//!If the file exists, the program checks all lints against your test, assuring the best quality possible.
59//!
60//!<div align="center">
61//!<img src="./assets/output-screenshot.png" height="300" width="auto" />
62//!</div>
63//!
64//!## Installation and usage
65//!
66//!##### ⚠️ Installation isn't currently possible because the project isn't published yet.
67//!
68//!To get started using `cargo-is-tested`, install the binary.
69//!
70//!```bash
71//!$ cargo install cargo-is-tested
72//!```
73//!
74//!Now [document yourself](https://docs.rs/cargo-is-tested/latest/cargo-is-tested/lints) about all the lints you can apply to your tests.
75//!
76//!* *strict* (Activates all lints, default)
77//!* [*emptiness*](https://docs.rs/cargo-is-tested/latest/cargo-is-tested/lints/emptiness)
78//!* [*validness*](https://docs.rs/cargo-is-tested/latest/cargo-is-tested/lints/validness)
79//!
80//!More lints will be added with time.
81//!
82//!---
83//!
84//!Once you know the lints you want to apply, import the attribute `is_tested`, then choose a struct, function or any item that you want to test, and add to that item the attribute `#[is_tested("<path to the test>.rs")]`
85//!
86//!The result should be something like:
87//!
88//!```rust, ignore
89//!#! is-tested strict
90//!
91//!use is_tested::is_tested;
92//!
93//!#[is_tested("tests/mystruct.rs")]
94//!struct MyStruct<'a> {
95//!	string: &'a str
96//!}
97//!```
98//!
99//!Don't worry, the attribute won't change anything in your code, it's just a marker for a later-parser to know that you're testing the item.
100//!
101//!---
102//!
103//!It's time to run the parser, it will read check that all tested items are tested, and with the correct code quality dicted using the lints.
104//!
105//!```rust, ignore
106//!// tests/mystruct.rs
107//!
108//!use mycrate::MyStruct;
109//!
110//!fn main() {
111//!	// [...]
112//!}
113//!```
114//!
115//!```bash
116//!$ cargo is-tested .
117//!```
118//!
119//!This will check that all tests are well written. You can use flags to customize your experience, for example, use `--structs` to check that all structs have tests associated, or use `--test` to, if all tests are confirmed, run `cargo test` automatically.
120
121pub mod error;
122pub mod flags;
123pub mod lints;
124
125#[cfg(feature = "suggestions")]
126pub fn did_you_mean<'a, T, I>(field: &str, alternatives: I) -> Option<String>
127where
128    T: AsRef<str> + 'a,
129    I: IntoIterator<Item = &'a T>,
130{
131    let mut candidate: Option<(f64, &str)> = None;
132    for pv in alternatives {
133        let confidence = ::strsim::jaro_winkler(field, pv.as_ref());
134        if confidence > 0.8 && (candidate.is_none() || (candidate.as_ref().unwrap().0 < confidence))
135        {
136            candidate = Some((confidence, pv.as_ref()));
137        }
138    }
139    candidate.map(|(_, candidate)| candidate.into())
140}
141
142#[cfg(not(feature = "suggestions"))]
143pub fn did_you_mean<'a, T, I>(field: &str, alternatives: I) -> Option<String>
144where
145    T: AsRef<str> + 'a,
146    I: IntoIterator<Item = &'a T>,
147{
148    None
149}
150
151#[macro_export]
152macro_rules! impl_warn {
153    ($ty: ty) => {
154        impl ::miette::ReportHandler for $ty {
155            fn debug(
156                &self,
157                error: &(dyn Diagnostic),
158                f: &mut core::fmt::Formatter<'_>,
159            ) -> core::fmt::Result {
160                if f.alternate() {
161                    return core::fmt::Debug::fmt(error, f);
162                }
163                write!(f, "{}", error)?;
164                Ok(())
165            }
166        }
167    };
168}
169
170#[macro_export]
171macro_rules! maybe_warn {
172    ($e: expr, $args: expr) => {
173        if $e.severity() == Some(Severity::Warning) && !$args.deny_warnings {
174			println!("WARN: {:?}", $e);
175        } else {
176            return Err($e);
177        }
178    };
179}