6个版本 (1个稳定版)

使用旧Rust 2015

1.0.0 2021年2月6日
1.0.0-beta.42017年9月1日
1.0.0-beta.32016年12月18日
1.0.0-beta.22016年7月30日
0.1.0 2016年7月22日

106测试 中排名

Download history 183/week @ 2024-04-23 148/week @ 2024-04-30 158/week @ 2024-05-07 213/week @ 2024-05-14 168/week @ 2024-05-21 243/week @ 2024-05-28 190/week @ 2024-06-04 166/week @ 2024-06-11 199/week @ 2024-06-18 154/week @ 2024-06-25 121/week @ 2024-07-02 165/week @ 2024-07-09 217/week @ 2024-07-16 255/week @ 2024-07-23 258/week @ 2024-07-30 172/week @ 2024-08-06

927 每月下载量
12 个crate中使用 12 crates

MPL-2.0 许可证

97KB
2K SLoC

rspec - 一个与稳定Rust一起工作的BDD测试框架

Build Status Coverage Status Crates.io Crates.io

当你喜欢BDD,并喜欢使用嵌套的describe/context/it方式测试时,但你同时也喜欢每天都能编译代码 👌。

如果你不知道Rust是什么,或者对BDD、TDD等术语感到困惑,或者只是想获得一个温和的入门介绍,请访问入门部分

最新的稳定文档可在docs.rs/rspec查阅。

如何使用

在您的Cargo.toml中添加以下内容:

[dev_dependencies]
rspec = "1.0"

并在您的src/lib.rssrc/main.rs中添加以下内容:

#[cfg(test)]
extern crate rspec;

您可以在examples/目录中查看完整的示例。

extern crate rspec;

pub fn main() {
    // Use a local struct to provide the test contexts with an environment.
    // The environment will contain the subject that is to be tested
    // along with any additional data you might need during the test run:
    #[derive(Clone, Default, Debug)]
    struct Environment {
        // ...
    }

    // `rspec::run(…)` is a convenience wrapper that takes care of setting up
    // a runner, logger, configuration and running the test suite for you.
    // If you want more direct control, you can manually set up those things, too.
    rspec::run(&rspec::describe("rspec, a BDD testing framework", Environment::default(), |ctx| {
        // `describe`, or any of its equivalents, opens the root context
        // of your test suite. Within you can then either define test examples:
        ctx.it("can define top-level tests", |_| true);

        // or make use of sub-contexts to add some structure to your test suite:
        ctx.specify("contexts give your tests structure and reduce redundancy", |ctx| {
            ctx.before(|_| {
                // Executed once, before any of the contexts/examples is entered.
            });

            ctx.after(|_| {
                // Executed once, after all of the contexts/examples have been exited.
            });

            ctx.specify("rspec can handle results", |ctx| {
                ctx.it("passes if the return is_ok()", |_| Ok(()) as Result<(),()>);
                ctx.it("failes if the return is_err()", |_| Err(()) as Result<(),()>);
            });

            ctx.specify("rspec can handle bools", |ctx| {
                ctx.it("should pass if true", |_| true);
                ctx.it("should fail if false", |_| false);
                ctx.it("is convenient for comparisons", |_| (42 % 37 + 2) > 3);
            });

            ctx.specify("rspec can handle units", |ctx| {
                ctx.it("should pass if the return is ()", |_| {});
            });

            ctx.specify("rspec can handle panics", |ctx| {
                ctx.it("is convenient for asserts", |_| assert_eq!(1, 1));
            });
        });
    })); // exits the process with a failure code if one of the tests failed.
}

套件、上下文和示例

rspec为每个结构元素提供三种变体

变体A 变体B 变体C
套件 套件 describe given
上下文 上下文 specify when
示例 example it then

注意:虽然建议每个测试套件只使用一种变体,但可以在变体之间自由混合结构元素。

变体A:suitecontextexample

runner.run(&rspec::suite("opens a suite", /* environment */, |ctx| {
    ctx.context("opens a context", |ctx| {
        ctx.example("opens an example", |env| /* test condition */ );
    });
}));

变体B:describespecifyit

runner.run(&rspec::describe("opens a suite", /* environment */, |ctx| {
    ctx.specify("opens a context", |ctx| {
        ctx.it("opens an example", |env| /* test condition */ );
    });
}));

变体C:givenwhenthen

runner.run(&rspec::given("opens a suite", /* environment */, |ctx| {
    ctx.when("opens a context", |ctx| {
        ctx.then("opens an example", |env| /* test condition */ );
    });
}));

前后

所有 每个
before before/before_all 每个测试之前
之后 after /after_all 每个测试之后

所有

在进入(或退出,分别)给定上下文时,将执行 before 和 after 块的 "All" 变体。

每个

before_eachafter_each 块在每个给定上下文的子上下文或示例之前各执行一次。

更多示例

同样,您可以在 examples/ 目录中查看完整的示例。

文档

最新的稳定文档可在 https://docs.rs/rspec 查阅。

贡献

... 非常欢迎!贡献遵循标准的 Github 工作流程,具体如下:

  1. 分支此存储库
  2. 创建一个功能分支
  3. 在此分支内编写代码并提交。我个人偏好小而独立的提交,但这不是硬性规定。
  4. 确保您已经为您的功能编写了测试。如果您不知道如何做,请将 PR 标题中的 [WIP] 添加,我们将乐意帮助您。
  5. 当测试通过,并且您的功能/错误修复得到覆盖时,我们将一起审查代码,共同改进。
  6. 当所有人都同意代码正确,并且测试通过时,您将享有合并您的 PR 的特权,成为强大的贡献者。恭喜。

如果您不知道如何帮助,请查看 问题。有些问题是有人指导的!

贡献者

初学者

关于 Rust

欢迎来到 Rust 社区!以下是一些可能有帮助的链接

  • Rust 是一种系统编程语言。检查 rust-lang 链接以获取详细说明,您可以使用 rustup 安装它 with rustup
  • 新手Rust by Example 是一个出色的资源,可以帮助您入门并掌握大多数 Rust 语义。查看它!
  • 中级Rust Book 是学习 Rust 的最佳资源。
  • 高级Learning Rust with too many linked lists 是一本很好的书,通过示例和详细的解释,解释了所有权系统以及如何使用它。《Rustonomicon》是另一个有助于理解编译器如何思考的资源,可以帮助您快速编写可编译的代码。

关于 TDD

TDD,即测试驱动开发,是一种开发方法,其中您的代码始终处于工作状态,重构变得容易,并且您可以确切地知道代码做了什么 和没有做什么

使用 TDD,遗留代码受限,您的构建始终是绿色的,您没有回归。

这是一个奇妙而神奇的地方,是一个精心保管的秘密,只有最优秀的人才能进入,这些人不会在质量上妥协,因为他们知道质量缺失的成本。这些人知道过度质量是无意义的。

以下是一些有用的链接

关于 BDD

行为驱动开发(BDD),简称BDD,是测试驱动开发(TDD)的一种变体;有些人认为BDD其实就是TDD,但更加精细。

BDD认为测试不是方法论的核心。它们是最有用的工具之一,但我们不应过分看重它们。重要的是它们所签署的合同,即描述的行为

因此,当struct的行为被充分描述时,就有足够的测试。从行为的角度思考有两个好处

  • 在进行TDD时,这有助于逐步进行。只需编写如何使用函数的示例,并使这个示例通过,然后进行下一个示例。您的测试将自然有一个清晰的目的,因此在重构时也容易调试/依赖。这是describe/it方法,该项目希望填补这一空白。

  • 通过描述行为,我们正在对我们的程序进行分析。这种分析非常有用!比如...用户故事。给定作为X,当Y,我想Z的正式化,您可以分配描述单元高级行为的场景。Gherkin正式化通常用于此,它使用给定X,当Y,然后Z结构。该项目并不旨在帮助高级BDD,有关Rust的Gherkin请参阅cucumber

BDD的基础在此处有很好的解释这里这里

使用Gherkin正式化编写的BDD确实可以受益于一层DDD(领域驱动开发),但这是另一个故事...

许可

Mozilla公共许可证2.0。请参阅存储库根目录下的LICENCE文件。

在非法律术语中,这意味着

  • 如果您修复了一个错误,您必须返回修复代码(这是公平的,请参阅贡献部分)。
  • 如果您更改/扩展了API,您必须返回您更改的MPL2下的文件中的代码。贡献部分可以帮助您。
  • 您不能因为任何关于这段代码的事情起诉本项目的作者
  • 除此之外,您可以几乎做任何您想做的事情。请参阅LICENCE文件以获取详细信息。

本节不取代也不完善许可文件。许可文件是定义本项目许可的唯一地方。

依赖项

~4–14MB
~131K SLoC