#testing #test-framework #catch #section

catchr

受C++中的Catch启发的测试框架

6个版本

0.3.0 2022年7月23日
0.2.3 2022年5月10日
0.2.2 2020年2月20日
0.1.0 2020年2月15日

#762 in 进程宏

Download history 18/week @ 2024-04-02

每月下载量:52

MIT 许可证

30KB
733

Catchr Rust

实验性:可能会吃掉你的衣服!

一个受C++中Catch启发的Rust测试框架。

快速入门

将以下代码添加到您的 Cargo.toml 文件中:

编写测试

#[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);
            }
        }
    }
}

cargotest

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 ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

部分

每个测试部分由一个关键字、一个描述和一个主体组成。

keyword "description" {
    // body
}

目前支持的以下关键字: sectioncasewhenthengiven

没有嵌套部分的测试部分将成为测试用例。部分的作用类似于作用域 - 也就是说,外部部分中的语句在内部部分中可用

when "something" {
    let x = 1;

    then "anything" {
        let y = 1;
        assert_eq!(x, y);
    }

    then "whatever" {
        assert!(true);
    }
}

可以使用 let x = 1;then "anything" 部分中使用。但来自 then "anything" 部分的 let y = 1; 则不能在 then "whatever" 部分中使用。

此外,作用域规则得到保留,因此内部测试用例可以借用而不违反借用检查规则。

考虑以下示例

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);
}

如果测试用例未展开作用域,我们会得到

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);

这将无法编译!

因此,catchr 会将此测试用例展开为

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);

它是如何工作的?

来自 快速入门 部分的代码将展开为类似以下的内容

#[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);
                    }
                }
            }
        }
    }
}

依赖项

~2MB
~44K SLoC