6个版本 (1个稳定版)
使用旧Rust 2015
1.0.0 | 2021年2月6日 |
---|---|
1.0.0-beta.4 | 2017年9月1日 |
1.0.0-beta.3 | 2016年12月18日 |
1.0.0-beta.2 | 2016年7月30日 |
0.1.0 | 2016年7月22日 |
106 在 测试 中排名
927 每月下载量
在 12 个crate中使用 12 crates
97KB
2K SLoC
rspec - 一个与稳定Rust一起工作的BDD测试框架
当你喜欢BDD,并喜欢使用嵌套的describe/context/it
方式测试时,但你同时也喜欢每天都能编译代码 👌。
如果你不知道Rust是什么,或者对BDD、TDD等术语感到困惑,或者只是想获得一个温和的入门介绍,请访问入门部分。
最新的稳定文档可在docs.rs/rspec查阅。
如何使用
在您的Cargo.toml
中添加以下内容:
[dev_dependencies]
rspec = "1.0"
并在您的src/lib.rs
或src/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:suite
,context
和example
runner.run(&rspec::suite("opens a suite", /* environment */, |ctx| {
ctx.context("opens a context", |ctx| {
ctx.example("opens an example", |env| /* test condition */ );
});
}));
变体B:describe
,specify
和it
runner.run(&rspec::describe("opens a suite", /* environment */, |ctx| {
ctx.specify("opens a context", |ctx| {
ctx.it("opens an example", |env| /* test condition */ );
});
}));
变体C:given
,when
和then
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_each
和 after_each
块在每个给定上下文的子上下文或示例之前各执行一次。
更多示例
同样,您可以在 examples/
目录中查看完整的示例。
文档
最新的稳定文档可在 https://docs.rs/rspec 查阅。
贡献
... 非常欢迎!贡献遵循标准的 Github 工作流程,具体如下:
- 分支此存储库
- 创建一个功能分支
- 在此分支内编写代码并提交。我个人偏好小而独立的提交,但这不是硬性规定。
- 确保您已经为您的功能编写了测试。如果您不知道如何做,请将 PR 标题中的
[WIP]
添加,我们将乐意帮助您。 - 当测试通过,并且您的功能/错误修复得到覆盖时,我们将一起审查代码,共同改进。
- 当所有人都同意代码正确,并且测试通过时,您将享有合并您的 PR 的特权,成为强大的贡献者。恭喜。
如果您不知道如何帮助,请查看 问题。有些问题是有人指导的!
贡献者
- Thomas WICKHAM @mackwic
- Pascal HERTLEIF @killercup
- Matthias BOURG @pol0nium
- Vincent ESCHE @regexident
初学者
关于 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,遗留代码受限,您的构建始终是绿色的,您没有回归。
这是一个奇妙而神奇的地方,是一个精心保管的秘密,只有最优秀的人才能进入,这些人不会在质量上妥协,因为他们知道质量缺失的成本。这些人知道过度质量是无意义的。
以下是一些有用的链接
- Uncle Bob 的 TDD 3 条规则
- 敏捷的艺术:测试驱动开发
- TDD 还通过减少您在每个步骤中必须做出的决策数量,使简单和涌现式设计成为可能。
关于 BDD
行为驱动开发(BDD),简称BDD,是测试驱动开发(TDD)的一种变体;有些人认为BDD其实就是TDD,但更加精细。
BDD认为测试不是方法论的核心。它们是最有用的工具之一,但我们不应过分看重它们。重要的是它们所签署的合同,即描述的行为。
因此,当struct
的行为被充分描述时,就有足够的测试。从行为的角度思考有两个好处
-
在进行TDD时,这有助于逐步进行。只需编写如何使用函数的示例,并使这个示例通过,然后进行下一个示例。您的测试将自然有一个清晰的目的,因此在重构时也容易调试/依赖。这是describe/it方法,该项目希望填补这一空白。
-
通过描述行为,我们正在对我们的程序进行分析。这种分析非常有用!比如...用户故事。给定作为X,当Y,我想Z的正式化,您可以分配描述单元高级行为的场景。Gherkin正式化通常用于此,它使用给定X,当Y,然后Z结构。该项目并不旨在帮助高级BDD,有关Rust的Gherkin请参阅cucumber。
使用Gherkin正式化编写的BDD确实可以受益于一层DDD(领域驱动开发),但这是另一个故事...。
许可
Mozilla公共许可证2.0。请参阅存储库根目录下的LICENCE文件。
在非法律术语中,这意味着
- 如果您修复了一个错误,您必须返回修复代码(这是公平的,请参阅贡献部分)。
- 如果您更改/扩展了API,您必须返回您更改的MPL2下的文件中的代码。贡献部分可以帮助您。
- 您不能因为任何关于这段代码的事情起诉本项目的作者
- 除此之外,您可以几乎做任何您想做的事情。请参阅LICENCE文件以获取详细信息。
本节不取代也不完善许可文件。许可文件是定义本项目许可的唯一地方。
依赖项
~4–14MB
~131K SLoC