{"id":16113471,"url":"https://github.com/dzejkop/catchr","last_synced_at":"2025-09-13T21:07:00.524Z","repository":{"id":48852561,"uuid":"240798518","full_name":"Dzejkop/catchr","owner":"Dzejkop","description":"A testing framework for Rust inspired by Catch!","archived":false,"fork":false,"pushed_at":"2022-07-23T12:49:55.000Z","size":36,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-28T08:43:02.763Z","etag":null,"topics":["bdd","bdd-tests","rust","rust-crate","rust-lang","testing","testing-framework"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dzejkop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-15T22:45:51.000Z","updated_at":"2023-11-06T16:08:06.000Z","dependencies_parsed_at":"2022-08-19T13:41:13.827Z","dependency_job_id":null,"html_url":"https://github.com/Dzejkop/catchr","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dzejkop%2Fcatchr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dzejkop%2Fcatchr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dzejkop%2Fcatchr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dzejkop%2Fcatchr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dzejkop","download_url":"https://codeload.github.com/Dzejkop/catchr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243918526,"owners_count":20368745,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bdd","bdd-tests","rust","rust-crate","rust-lang","testing","testing-framework"],"created_at":"2024-10-09T20:11:50.942Z","updated_at":"2025-03-18T09:31:20.154Z","avatar_url":"https://github.com/Dzejkop.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Rust](https://github.com/Dzejkop/catchr/workflows/Rust/badge.svg)\n[![Crates.io](https://img.shields.io/crates/d/catchr.svg)](https://crates.io/crates/catchr)\n\n# Catchr\n\n_Experimental: Might eat your laundry!_\n\nA testing framework for Rust inspired by [Catch for C++](https://github.com/catchorg/Catch2).\n\n## Quickstart\n\n### Add `catchr = \"0.3.0\"` to your `Cargo.toml`\n\n### Write tests:\n\n```rust\n#[cfg(test)]\nmod tests {\n    catchr::describe! {\n        section \"my tests\" {\n            given \"x is equal to 1\" {\n                let mut x = 1;\n\n                when \"1 is added to x\" {\n                    x += 1;\n\n                    then \"x should equal 2\" {\n                        assert_eq!(2, x);\n                    }\n                }\n\n                when \"2 is added to x\" {\n                    x += 2;\n\n                    then \"x should equal 3\" {\n                        assert_eq!(3, x);\n                    }\n                }\n\n                // for all code paths\n                assert!(x \u003e= 2);\n            }\n        }\n    }\n}\n```\n\n### `cargo test`\n\n```\nrunning 2 tests\ntest tests::section_my_tests::given_x_is_equal_to_1::when_2_is_added_to_x::then_x_should_equal_3 ... ok\ntest tests::section_my_tests::given_x_is_equal_to_1::when_1_is_added_to_x::then_x_should_equal_2 ... ok\n\ntest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out\n```\n\n## Sections\n\nEach test section consists of a keyword, a description and a body.\n\n```rust\nkeyword \"description\" {\n    // body\n}\n```\n\nFor the moment the following keywords are supported: `section`, `case`, `when`, `then`, `given`.\n\nSections 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:\n\n```rust\nwhen \"something\" {\n    let x = 1;\n\n    then \"anything\" {\n        let y = 1;\n        assert_eq!(x, y);\n    }\n\n    then \"whatever\" {\n        assert!(true);\n    }\n}\n```\n\nThe `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.\n\nFurthermore the scoping rules are preserved, so that inner test cases can borrow mutably without violating the borrow checker rules.\n\nConsider the following example:\n\n```rust\ncase \"a\" {\n    let mut tmp = tempfile().unwrap();\n\n    case \"should write some data\" {\n        let mut writer = BufWriter::new(\u0026mut tmp);\n        writer.write_all(\u0026[1, 2, 3]).unwrap();\n    }\n\n    tmp.seek(SeekFrom::Start(0)).unwrap();\n    let bytes_in_tmp_file = tmp.seek(SeekFrom::End(0)).unwrap();\n\n    assert_eq!(bytes_in_tmp_file, 3);\n}\n```\n\nif the test case was expanded without scoping, we'd get\n\n```rust\nlet mut tmp = tempfile().unwrap();\n\nlet mut writer = BufWriter::new(\u0026mut tmp);\nwriter.write_all(\u0026[1, 2, 3]).unwrap();\n\ntmp.seek(SeekFrom::Start(0)).unwrap();\nlet bytes_in_tmp_file = tmp.seek(SeekFrom::End(0)).unwrap();\n\nassert_eq!(bytes_in_tmp_file, 3);\n```\n\nwhich fails to compile!\n\nso `catchr` will expand this test case into\n\n```rust\nlet mut tmp = tempfile().unwrap();\n\n{\n    let mut writer = BufWriter::new(\u0026mut tmp);\n    writer.write_all(\u0026[1, 2, 3]).unwrap();\n}\n\ntmp.seek(SeekFrom::Start(0)).unwrap();\nlet bytes_in_tmp_file = tmp.seek(SeekFrom::End(0)).unwrap();\n\nassert_eq!(bytes_in_tmp_file, 3);\n```\n\n## Async support\n\nYou can also use the `describe_tokio` macro to generate async tests that work with the tokio runtime.\nFirst 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]\"`.\n\nNext just write\n\n```rust\ncatchr::describe_tokio! {\n    when \"Something\" {\n        then \"Something\" {\n            // it's possible to `.await` here\n            assert!(true);\n        }\n    }\n}\n```\n\n## How does it work?\n\nThe code from the [**Quickstart**](##Quickstart) section will expand into something like this:\n\n```rust\n#[cfg(test)]\nmod tests {\n    mod section_my_tests {\n        use super::*;\n\n        mod given_x_is_equal_to_1 {\n            use super::*;\n\n            mod when_1_is_added_to_x {\n                use super::*;\n\n                #[test]\n                fn then_x_should_equal_2() {\n                    {\n                        let mut x = 1;\n                        {\n                            x += 1;\n                            {\n                                assert_eq!(2, x);\n                            }\n                        }\n                        assert!(x \u003e= 2);\n                    }\n                }\n            }\n\n            mod when_2_is_added_to_x {\n                use super::*;\n\n                #[test]\n                fn then_x_should_equal_3() {\n                    {\n                        let mut x = 1;\n                        {\n                            x += 2;\n                            {\n                                assert_eq!(3, x);\n                            }\n                        }\n                        assert!(x \u003e= 2);\n                    }\n                }\n            }\n        }\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdzejkop%2Fcatchr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdzejkop%2Fcatchr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdzejkop%2Fcatchr/lists"}