Rust中的TDD:通过测试驱动开发实现可靠代码

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么Rust中的TDD既不枯燥又有利可图?

\n\n

您是否曾经写过“看似正确”的代码,却在最意想不到的地方遇到bug?很熟悉吧。测试驱动开发(TDD)是一种将常规流程彻底颠覆的方法。与其先写代码再猜测它是否工作,不如先编写一个应该失败的测试,然后编写刚好能让测试通过的代码。

\n\n

Rust是一种在编译器层面就能保护您免受一整类错误(告别段错误和数据竞争!)的语言。但即使编译器也不能保证您的逻辑正确。Rust中的TDD为这种安全性又增加了一层:您不仅仅是编写代码,而是在测试中直接记录预期行为。这非常酷。

\n\n

在本文中,我们将通过实际示例剖析Rust中的TDD。您将看到如何在实现之前编写测试,如何使用cargo test运行它们,以及如何在不担心破坏任何东西的情况下重构代码。开始吧!

\n\n

什么是TDD,为什么Rust是它的理想选择?

\n\n

TDD代表测试驱动开发。这个循环简单而优雅:

\n\n
    \n
  1. 红色 — 编写描述新功能的测试。运行——测试失败(很合理,代码还不存在)。
  2. \n
  3. 绿色 — 编写最少的代码使测试通过。不考虑美观,只考虑通过测试。
  4. \n
  5. 重构 — 改进代码而不改变其行为。测试保持绿色。
  6. \n
\n\n

Rust非常适合TDD,原因如下:

\n
    \n
  • 内置测试系统 — cargo test开箱即用,无需安装第三方框架。
  • \n
  • 强类型 — 编译器捕获类型错误,测试捕获逻辑错误。两者结合无懈可击。
  • \n
  • 所有权和借用 — 测试有助于确保您正确处理内存,不创建不必要的副本。
  • \n
  • 社区和文档 — Rust社区积极推广测试,示例丰富。
  • \n
\n\n

为TDD配置项目

\n\n

创建一个新项目:

\n
cargo new tdd_rust_example\ncd tdd_rust_example
\n\n

默认情况下,cargo new会创建一个包含简单程序的src/main.rs文件。我们将编写一个库,因此将其重命名为src/lib.rs(或者直接删除main.rs并创建lib.rs)。Cargo.toml中无需更改任何内容——测试已经包含在内。

\n\n

顺便说一句,如果您只编写库(没有可执行文件),请使用cargo new --lib。

\n\n

第一个测试:红色

\n\n

假设我们要编写一个将两个数相加的函数。按照TDD,我们先编写测试。打开src/lib.rs并添加:

\n\n
#[cfg(test)]\nmod tests {\n    #[test]\n    fn test_add() {\n        let result = add(2, 3);\n        assert_eq!(result, 5);\n    }\n}
\n\n

运行:

\n
cargo test
\n\n

您将看到编译错误——函数add未定义。这很正常。我们处于红色区域。

\n\n

绿色:最小实现

\n\n

现在编写刚好能让测试通过的代码。在测试模块上方添加add函数:

\n\n
fn add(a: i32, b: i32) -> i32 {\n    a + b\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    \n    #[test]\n    fn test_add() {\n        let result = add(2, 3);\n        assert_eq!(result, 5);\n    }\n}
\n\n

注意use super::*;——这将从父模块(我们的代码)导入所有内容到测试模块中。

\n\n

再次运行cargo test。绿色!测试通过了。我们做了最少的工作——返回了和。看起来

博客

书籍推荐