Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dzejkop/catchr
A testing framework for Rust inspired by Catch!
https://github.com/dzejkop/catchr
bdd bdd-tests rust rust-crate rust-lang testing testing-framework
Last synced: about 2 months ago
JSON representation
A testing framework for Rust inspired by Catch!
- Host: GitHub
- URL: https://github.com/dzejkop/catchr
- Owner: Dzejkop
- License: mit
- Created: 2020-02-15T22:45:51.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2022-07-23T12:49:55.000Z (over 2 years ago)
- Last Synced: 2024-10-09T20:12:12.655Z (3 months ago)
- Topics: bdd, bdd-tests, rust, rust-crate, rust-lang, testing, testing-framework
- Language: Rust
- Homepage:
- Size: 35.2 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
![Rust](https://github.com/Dzejkop/catchr/workflows/Rust/badge.svg)
[![Crates.io](https://img.shields.io/crates/d/catchr.svg)](https://crates.io/crates/catchr)# Catchr
_Experimental: Might eat your laundry!_
A testing framework for Rust inspired by [Catch for C++](https://github.com/catchorg/Catch2).
## Quickstart
### Add `catchr = "0.3.0"` to your `Cargo.toml`
### Write tests:
```rust
#[cfg(test)]
mod tests {
catchr::describe! {
section "my tests" {
given "x is equal to 1" {
let mut x = 1;when "1 is added to x" {
x += 1;then "x should equal 2" {
assert_eq!(2, x);
}
}when "2 is added to x" {
x += 2;then "x should equal 3" {
assert_eq!(3, x);
}
}// for all code paths
assert!(x >= 2);
}
}
}
}
```### `cargo test`
```
running 2 tests
test tests::section_my_tests::given_x_is_equal_to_1::when_2_is_added_to_x::then_x_should_equal_3 ... ok
test tests::section_my_tests::given_x_is_equal_to_1::when_1_is_added_to_x::then_x_should_equal_2 ... oktest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```## Sections
Each test section consists of a keyword, a description and a body.
```rust
keyword "description" {
// body
}
```For the moment the following keywords are supported: `section`, `case`, `when`, `then`, `given`.
Sections without any nested section will become test cases. Sections function like scopes - that is statements from the outer section are available in the inner section:
```rust
when "something" {
let x = 1;then "anything" {
let y = 1;
assert_eq!(x, y);
}then "whatever" {
assert!(true);
}
}
```The `let x = 1;` can be used in the `then "anything"` section. But `let y = 1;` from the `then "anything"` section, cannot be used in the `then "whatever"` section.
Furthermore the scoping rules are preserved, so that inner test cases can borrow mutably without violating the borrow checker rules.
Consider the following example:
```rust
case "a" {
let mut tmp = tempfile().unwrap();case "should write some data" {
let mut writer = BufWriter::new(&mut tmp);
writer.write_all(&[1, 2, 3]).unwrap();
}tmp.seek(SeekFrom::Start(0)).unwrap();
let bytes_in_tmp_file = tmp.seek(SeekFrom::End(0)).unwrap();assert_eq!(bytes_in_tmp_file, 3);
}
```if the test case was expanded without scoping, we'd get
```rust
let mut tmp = tempfile().unwrap();let mut writer = BufWriter::new(&mut tmp);
writer.write_all(&[1, 2, 3]).unwrap();tmp.seek(SeekFrom::Start(0)).unwrap();
let bytes_in_tmp_file = tmp.seek(SeekFrom::End(0)).unwrap();assert_eq!(bytes_in_tmp_file, 3);
```which fails to compile!
so `catchr` will expand this test case into
```rust
let mut tmp = tempfile().unwrap();{
let mut writer = BufWriter::new(&mut tmp);
writer.write_all(&[1, 2, 3]).unwrap();
}tmp.seek(SeekFrom::Start(0)).unwrap();
let bytes_in_tmp_file = tmp.seek(SeekFrom::End(0)).unwrap();assert_eq!(bytes_in_tmp_file, 3);
```## Async support
You can also use the `describe_tokio` macro to generate async tests that work with the tokio runtime.
First you need to make sure that you have `tokio` in your dependencies and it has the required features - my recommendation is to use `features = ["full]"`.Next just write
```rust
catchr::describe_tokio! {
when "Something" {
then "Something" {
// it's possible to `.await` here
assert!(true);
}
}
}
```## How does it work?
The code from the [**Quickstart**](##Quickstart) section will expand into something like this:
```rust
#[cfg(test)]
mod tests {
mod section_my_tests {
use super::*;mod given_x_is_equal_to_1 {
use super::*;mod when_1_is_added_to_x {
use super::*;#[test]
fn then_x_should_equal_2() {
{
let mut x = 1;
{
x += 1;
{
assert_eq!(2, x);
}
}
assert!(x >= 2);
}
}
}mod when_2_is_added_to_x {
use super::*;#[test]
fn then_x_should_equal_3() {
{
let mut x = 1;
{
x += 2;
{
assert_eq!(3, x);
}
}
assert!(x >= 2);
}
}
}
}
}
}
```