1 个不稳定版本
0.1.0 | 2023年2月9日 |
---|
#512 在 测试
31KB
544 行
Cogno
内容
是什么?
TL;DR 用于创建 RFC 规范测试的测试框架。
它提供
- 特殊断言,如
must_eq
和should_eq!
,以匹配语言 RFC 使用的格式,并自动转换为测试结果。 - 不会引发恐慌的测试,这样所有断言都应运行。这确保测试通过或失败是出于预期的原因。
- 规范标识符作为测试的元数据,以便可以灵活地测试多个 RFC 的符合性。
- 断言标识符,以便规范可以演变。这允许在代码之外明确地更改断言,以适应需求的变化。
快速入门
使用以下命令创建新的二进制软件包
$ cargo init --bin <package-name>
$ cd <package-name>
好的软件包名称应指定要测试的 RFC 内容。例如,使用 cogno-spec-dns
来测试 DNS,而不是使用 cogno-spec-rfc-1034
。
添加对 cogno
测试框架的依赖
$ cargo add --features console cogno
安装 Cargo 插件
$ cargo install cargo-cogno --locked
在 src/main.rs
中添加您的应用程序的示例代码
#[macro_use]
extern crate cogno;
#[cogno_test(spec = "<my-rfc-id>")]
fn test() {
should_eq!("<my-assertion-id>", 'a', 'a');
}
#[cogno_main]
fn main() {}
这将按原样编译和运行,或者您可以更新尖括号中的值以匹配您的项目。
现在您可以运行测试了
$ cargo cogno --spec '<my-rfc-id>'
您应该看到 ✓ - test
作为输出。
就是这样。您可以开始编写测试,或者您可以查看以下更详细的文档。
使用说明
以下是一些使用 Cogno 的建议和限制,以获得最佳效果
- 必须将软件包作为二进制文件使用
cogno_main
和cogno_test
属性,如文档所述。 - 所有源代码必须位于软件包的
src
目录中。您可以按任何方式组织代码,但从工作区或其他地方导入的其他本地软件包的测试将无法找到。 - 尽可能少地引发恐慌。框架应捕获并处理恐慌,但当然,您的测试将无法完成。这不是所希望的,最好避免。
- 因为提供的断言不会引发恐慌,所以退出测试而不引发恐慌与测试成功不同。您应该始终确保在测试中包含至少一个断言。目前这并不强制执行,但将来可能会至少变成一个警告。
- 使用集成开发环境(IDE)来编写代码。宏中的Rust源代码生成不完美,会被语法错误所困扰。对于语法和Cogno宏错误,您得到的编译器错误可能不如通常由Rust编译器报告的那样好。对于这些问题,请依靠您的IDE。对于其他类型的错误,编译器错误应该如预期那样出现。
使用修饰符演变规范
随着规范的演变,许多要求仍然有效,而其他一些则需要进行更改。测试本身不应更改,因为它们应该继续描述原始规范。
给定两个测试规范 1234
(原始规范)和 1235
(新规范)
#[cogno_test(spec = "1234")]
fn test_original() {
must_eq!("rfc_1234_assertion_id", 'a', 'a');
}
#[cogno_test(spec = "1235")]
fn test_new() {
must_eq!("rfc_1235_assertion_id", 'b', 'b');
}
其中 1235
的规范不再将 rfc_1234_assertion_id
作为强制要求。实现应该继续支持该功能,但有效的 1235
实现不需要 rfc_1234_assertion_id
。
您可以提供一个 修饰符 配置来描述这一点
[[spec_modifiers]]
spec_id = "1234"
test_modifiers = [
{ test_id = "test_original", assertion_modifiers = [
{ assertion_id = "rfc_1234_assertion_id", assertion_type = "Should" },
] },
]
这被保存为一个名为需要它们的规范名称的文件,例如 modifier-rfc-1235.toml
。然后在测试 1235
的合规性时提供给 cogno
$ cargo cogno --spec 1234 --spec 1235 --modifier modifier-rfc-1235.toml
原始断言的结果将被转换为在原地应用 Should
断言代替 Must
断言。
创建测试和修饰符的建议
您的测试最终用户需要实现哪些规范以及如何使用您的测试和修饰符,这取决于您。因此,您应该力求使您的测试灵活。
您应该力求将预期将针对同一程序或库运行的测试分组在一起。例如,DNS
规范由许多规范组成,其中预期将有 name server
和 resolver
组件。这可以写成一个或两个测试套件。而 HTTP
也由多个规范组成,版本1、2和3,程序只实现其中之一是完全合理的。在这种情况下,可能有必要按HTTP划分测试套件。
同样,对于修饰符,您应该力求灵活性。在可能的情况下,提供独立的修饰符是可取的。假设规范 1234
由 1235
和 1236
更新,那么您应该提供不更新相同断言的 modifier-rfc-1235.toml
和 modifier-rfc-1236.toml
。Cogno会检测到这一点,并停止有问题的测试。如果 1236
与 1235
冲突或是对其进行了更新,那么您应该在 1236
的修饰符toml中包含与 1235
相关的修饰符,并为您用户提供文档,说明他们应该使用 cargo cogno --spec 1234 --spec 1235 --modifier modifier-rfc-1235.toml
或 cargo cogno --spec 1234 --spec 1235 --spec 1236 --modifier modifier-rfc-1236.toml
。
灵活性和文档很重要,但最终目标是提供尽可能广泛使用的测试。目标应该是尽可能完整地描述规范,而不是比规范更严格。
关于滥用的说明
该crate暴露的功能比作为库严格应该暴露的要多。这样做有很好的理由 - 通过由 cogno_main
和 cogno_test
属性生成的代码,将功能暴露给您的测试。
以下代码将编译并运行
#[cogno_test]
fn test() {
should_eq!("test_assertion_id", 'a', 'a');
controller_thread_ref.lock().unwrap().register("naughty", "test");
}
请不要这样做!通常没有必要与生成的代码交互。如果您遇到bug,请将问题提交到GitHub,我将尝试修复它。如果您对测试工具的工作原理感兴趣,可以自由地将其分叉并实验。
修改 TestController
状态或访问文档中标记为 '内部' 的任何其他内容,很可能会导致测试不可靠或行为未定义。
您只需要使用导出的宏来构建您的测试。
依赖项
约2-13MB
约120K SLoC