---
title: Neovim 项目实践：修复一个边界错误
url: https://doc.liz6.com/tools/nvim/05-project-workflow
locale: zh
area: tools
tags:
- Neovim
- 开发工具
date: 2026-09-15
modified: 2026-09-15
description: 用一个 Rust 运费函数贯穿项目打开、测试失败、代码修改、格式检查、Git 审阅与调试。
---

# Neovim 项目实践：修复一个边界错误

本篇使用一个没有外部依赖的 Rust 小项目，完成“看见失败 → 定位 → 修改 → 验证 → 审阅”的过程。只需理解条件判断；重点是编辑器如何连接项目工具，不要求熟悉完整 Rust 语言。

准备好 Cargo、Git 和 Neovim。LSP 有助于阅读与导航，但基本编辑和测试可以独立完成。

## 建立独立练习项目

在放置练习的目录执行，确保 `editor-lab` 尚不存在：

```bash
cargo new --lib --vcs git editor-lab
cd editor-lab
nvim src/lib.rs
```

如果使用前文的学习配置，将最后一条改为 `NVIM_APPNAME=nvim-lab nvim src/lib.rs`。本文后面的命令都从 `editor-lab` 根目录执行。

需求是：订单金额达到 50 时免运费，否则收取 5。用下面的完整代码替换 `src/lib.rs`；其中故意保留一个边界错误：

```rust
pub fn shipping_fee(total: u32) -> u32 {
    if total > 50 {
        0
    } else {
        5
    }
}

#[cfg(test)]
mod tests {
    use super::shipping_fee;

    #[test]
    fn below_threshold() {
        assert_eq!(shipping_fee(49), 5);
    }

    #[test]
    fn at_threshold() {
        assert_eq!(shipping_fee(50), 0);
    }

    #[test]
    fn above_threshold() {
        assert_eq!(shipping_fee(51), 0);
    }
}
```

用 `:write` 保存。金额用整数表达，避免把浮点或货币精度问题混入这次编辑练习。

## 先理解失败输出

在另一个终端面板运行：

```bash
cargo test
```

应有两个测试通过，`at_threshold` 失败：实际返回 5，预期为 0。代码可以编译，类型也没有问题，因此 LSP 不一定报告错误。

测试输出给出失败测试名和断言位置。先检查需求与期望值，再从测试跳到 `shipping_fee` 的定义；没有 LSP 时也可以用 `/shipping_fee` 搜索。观察条件 `total > 50`：它把 50 排除在免运费范围之外。

为便于稍后审阅，先将这个已知失败的练习状态作为本地基线提交。仅在本练习仓库中执行：

```bash
git add Cargo.toml Cargo.lock src/lib.rs .gitignore
git diff --cached
```

确认暂存内容后再提交：

```bash
git commit -m 'Add shipping fee boundary exercise'
```

此处提交用于保存故障样本，不涉及远程推送。若 Git 尚未设置作者身份，按个人环境配置身份后继续；不要为完成练习临时冒用其他人的信息。

## 做最小修改

将条件改为：

```rust
if total >= 50 {
```

这是替换原条件的一行，不是完整程序。保存后先只运行边界测试：

```bash
cargo test at_threshold
```

通过后运行完整测试与格式检查：

```bash
cargo test
cargo fmt --check
```

预期三个测试都通过，格式检查无差异。若格式检查失败，先确认项目规则，再用 `cargo fmt` 应用格式化并审阅修改。

## 从编辑器连接测试

可以使用 Zellij 的另一个面板，也可以在 Neovim 中通过 `:terminal` 打开终端。终端模式下要先回到普通模式才能执行窗口命令，默认按键是 `Ctrl+\` 后接 `Ctrl+n`；发行版可能提供其他映射。

无论从哪里启动测试，都要确认工作目录和保存状态。测试读取磁盘文件，未保存的 buffer 不会自动成为 Cargo 的输入。

习惯稳定后，可以在项目 `justfile` 中固定 `test` 和 `check` 任务，让终端与编辑器使用相同命令，见 [CLI 工具箱](../cli-toolbox.md)。

## 审阅差异再结束任务

```bash
git diff -- src/lib.rs
git diff --check
git status --short
```

预期业务修改只将 `>` 改为 `>=`。如果出现整个文件重新排版、换行符变化或其他文件改动，应先解释原因，再选择是否保留。测试通过不能代替差异审阅。

完成检查后，可将修复单独暂存并提交。练习的价值是保留“失败基线”和“最小修复”之间清楚的关系。

## 需要调试时观察什么

这个错误通过测试已容易定位。更复杂的逻辑可以在 `shipping_fee` 条件处下断点，选择 `at_threshold` 的测试目标，观察 `total = 50` 和实际分支。

在 LazyVim 中启用 DAP 核心和 Rust 对应调试依赖后，使用 Rust extra 的 debuggables 入口选择测试目标。若没有可运行目标，先确认 `cargo test` 已能构建，再检查 adapter、构建产物和调试符号，不能把编译失败当作断点问题。

最终应能说明：为什么原程序没有类型错误却不符合需求，为什么三个边界测试有不同作用，以及哪一行改动使需求与实现一致。
