---
title: "Web3中的测试驱动开发 - 博客"
canonical: https://wavect.io/zh/blog/test-driven-development/
language: zh
description: "为什么 TDD 在 Web3 开发中很重要，如何把它用在智能合约和去中心化应用上，以及为什么跳过测试的代价比你想象的高得多。"
image: "https://wavect.io/img/general/bak/open_graph_preview.jpg"
---

[**返回**](/zh/blog/overview/)

[![Christof Jori](/img/team/christof.webp)](/zh/team/christof-jori/)

[Christof Jori](/zh/team/christof-jori/) https://linkedin.com/in/jocr77

5 分钟 阅读 · 2024年6月17日

[**下一篇**](/zh/blog/agile-fixed-pricing/)

# 为什么测试驱动开发值得投入

要点速览

没有无错的软件，雇最好的工程师也只是减少 bug 而不是消除，所以要写测试。TDD 让工程师先写测试再写实现，确保没有未经测试的代码进生产；在智能合约管理大量资产的 Web3 开发里，它更是关键的安全手段。不写测试的代价是技术债：隐藏问题随功能堆积增长，直到一次小改动引发灾难性故障。对测试不在意的开发者，对你的产品也不会在意。

相关服务: [软件质量保证](/zh/services/software-quality-assurance/)

## 为什么要做测试驱动开发

测试驱动开发（ [TDD](/zh/glossary/tdd/) ）是有经验的软件工程师用来确保应用状态符合预期的技术。在更传统的应用以及软件工程的整体演进里，测试已经被公认为每一套成功且专业打造的软件系统的一部分。如今，仍然有大量公司认为写测试拖慢开发、提高成本，总体上是浪费时间。希望这篇文章能照出这种说法错得有多离谱。

### 什么阻碍软件正常工作？

世上没有完美写就的软件，大概也永远不会有。 “bug”这个词最早于 1946 年在哈佛被提出。当时 Grace Hopper 让一个故事流传开来：一只飞蛾在早期机电计算机里搞出了问题。Hopper 当时在哈佛做 Mark II/III 计算机系统，他发现一只飞蛾被卡在继电器里造成了故障。 把飞蛾取出后，Hopper 在笔记里写下：“First actual case of bug being found（首次真正发现 bug 的实例）。”自此“bug”一词被用来表示计算机系统中的意外行为。一个系统有 bug 的概率？100/100 个项目。如果我雇用地球上最好的工程师，系统有 bug 的概率？100/100 个项目。所以雇更好的工程师并不能解决问题。它当然会让 bug 变少，但不会让 bug 消失。这就是为什么要写测试，因为没有无错的软件。

![The cost of testing over time](/img/blog/posts/tdd-grace_hopper_bug_hu_2b5a209830cfad25.webp)

Grace Hopper 的 bug（1946）

## TDD：降低成本，提升质量

在测试驱动开发（TDD）里，工程师在实现逻辑之前先写测试。不展开技术细节，这导致下列结果： 如果做得好，它确保没有未经测试的代码被推到仓库里，因为你已经先写了一份专门的测试。这能解决前面讨论的 bug 问题吗？很遗憾，不能。但它是我们手上最好的技术之一，用来创造久经考验、有韧性的软件。

![Christof Jori](/img/team/christof.webp)

"尽早验证假设，把后面昂贵的错误降到最低。"

那 [Web3](/zh/glossary/web3/) 有什么不同？ 在 Web3 开发中，安全是最高优先级。 [智能合约](/zh/glossary/smart-contract/) 常常管理大量加密货币和其他有价值的数字资产。任何这些合约里的漏洞都会带来重大资金损失。TDD 通过促进持续测试和早期识别潜在问题，扮演了关键的安全角色。 在开发周期早期捕捉到安全缺陷，TDD 有助于防御那些会损害去中心化应用完整性的利用与攻击。测试让工程师调整代码库并立即得到反馈。如果测试写得到位，任何可能导致 bug 的代码改动都会被测试抓到并上报。 重要的是，上面这些用普通测试也能做到。所谓普通测试，就是想到“现在写一个测试”才写。许多工程师走这条路：“我现在写代码，等有时间再补测试。”从某种程度上说，这没问题。比一行测试都不写好得多！但它永远达不到 TDD 的韧性级别，因为它根本错过了重点。 我乐意重复一遍：“没有未经测试的代码会进生产”。这才是纯粹 TDD 所确保的。

![The cost of testing over time](/img/blog/posts/tdd-cost-of-testing.svg)

完全不写测试最终会反噬你

## 沉默的杀手：技术债

我还欠你一个解释：为什么不写测试会让工程和维护成本爆炸。关键词是技术债。软件总会有 bug。它存在越久、越大，产生的 bug 就越多。这不是我用来强调本节而编出来的，是众所周知的事实。 因此，如果没有任何对策来发现和消除这些 bug，它们会一直留下来并影响后续加进代码库的代码，反复影响。 我们给软件加的功能越多，问题就越大。终于有一天，这座塔倒了，你站在一份已经无法控制的代码库前。 导致项目整体或部分被推倒重建。 设想一个小镇决定快速搭一座桥连接河两岸。工程师们在赶工中跳过了一些安全检查，用了更次的材料。一开始桥运行良好，大家对速度赞不绝口。时间过去，越来越多车开始走这座桥。小裂缝出现了，但被忽略了，因为桥还立着。每辆新车都增加压力，让裂缝变大。一天，一辆超重卡车开过桥，桥塌了，造成巨大停摆。 这正是 [定制软件开发](/zh/services/software-development/) 中的技术债。早期的捷径和未经测试的代码制造隐藏问题。随着新功能不断加入，这些问题增长，直到系统变脆。最终一个看似微小的改动就能引发灾难性故障，就像超载卡车之于那座桥。如果没有测试来尽早捕捉并修复问题，软件就变得不可持续，成本飙升，最终崩塌。 建议 1： 招聘开发者时，用简单问题测试他们在测试方面的熟练度： → 你写测试的经验如何？ → 你在本项目里偏好哪种测试，为什么？ → 我们真的需要写测试吗？ 建议 2：如果他们对测试不在意，他们对你的产品也不会在意。 听起来很狠，但这是真的。 没有测试，你的项目终将死去，这一点毫无疑问。

## 最终思考

忽视软件测试不仅有遇到无法运行的软件的风险，还会侵蚀产品整体质量与可靠性。合适的测试不仅是为了发现 bug 与问题，更是为了确保软件满足用户预期并在各类环境下顺畅运行。 如果你想让你的产品成功，请依靠那些依靠测试的工程师。

QA 与生产就绪

## 继续浏览此集群

[从核心文章开始**AI 生成代码的 QA**](/zh/blog/qa-for-ai-generated-code/)

- [智能体测试与测试自动化：2026 试点指南](/zh/blog/agentic-testing-vs-test-automation-2026/)
- [外部 QA 基准：软件产品前 30 天通常会发现什么](/zh/blog/external-qa-benchmark-first-30-days/)
- [软件上线后维护要花多少钱：DACH SaaS 基准](/zh/blog/software-maintenance-cost-benchmark-dach-saas/)
- [敏捷去工程化](/zh/blog/agile-de-engineering/)
- [Lovable、Bolt 和 Replit 应用尽职调查](/zh/blog/lovable-bolt-replit-app-due-diligence/)

只收重要内容

## 关注与你相关的内容

每当我们发布新文章，你会收到一封简短邮件。你可以关注整个博客，也可以只选感兴趣的主题。

[**返回**](/zh/blog/overview/)

[![Christof Jori](/img/team/christof.webp)](/zh/team/christof-jori/)

[Christof Jori](/zh/team/christof-jori/) https://linkedin.com/in/jocr77

5 分钟 阅读 · 2024年6月17日

[**下一篇**](/zh/blog/agile-fixed-pricing/)

邮件订阅新文章 ×

×

通过邮件获取新文章

我们发布时给你一封简短邮件。免费，不做跟踪。

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://wavect.io/#organization",
      "@type": [
        "Organization",
        "ProfessionalService",
        "LocalBusiness"
      ],
      "employee": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "founder": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "legalRepresentative": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "name": "Wavect GmbH",
      "subjectOf": {
        "@id": "https://wavect.io/verified-claims.json#dataset",
        "@type": "Dataset",
        "creator": {
          "@id": "https://wavect.io/#organization",
          "@type": [
            "Organization",
            "ProfessionalService",
            "LocalBusiness"
          ]
        },
        "description": "A machine-readable registry of quantitative and qualitative claims published by Wavect, with review dates, localized page appearances and public third-party citations where available.",
        "inLanguage": "en",
        "isAccessibleForFree": true,
        "license": "https://creativecommons.org/licenses/by/4.0/",
        "name": "Wavect verified publication claims",
        "url": "https://wavect.io/verified-claims.json"
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/team/kevin-riedl/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Kevin Riedl",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796365",
        "https://www.linkedin.com/in/wsdt",
        "https://github.com/wsdt"
      ],
      "url": "https://wavect.io/team/kevin-riedl/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/team/christof-jori/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Christof Jori",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796367",
        "https://www.linkedin.com/in/jocr77/",
        "https://github.com/jo-chris"
      ],
      "url": "https://wavect.io/team/christof-jori/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/#website",
      "@type": "WebSite",
      "inLanguage": [
        "en",
        "de",
        "es",
        "zh"
      ],
      "name": "Wavect",
      "potentialAction": {
        "@type": "SearchAction",
        "query-input": "required name=search_term_string",
        "target": {
          "@type": "EntryPoint",
          "urlTemplate": "https://wavect.io/search/?q={search_term_string}"
        }
      },
      "publisher": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/zh/blog/test-driven-development/#webpage",
      "@type": "WebPage",
      "dateModified": "2026-07-07",
      "inLanguage": "zh",
      "isPartOf": {
        "@id": "https://wavect.io/#website",
        "@type": "WebSite"
      },
      "lastReviewed": "2026-07-07",
      "url": "https://wavect.io/zh/blog/test-driven-development/"
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "abstract": "没有无错的软件，雇最好的工程师也只是减少 bug 而不是消除，所以要写测试。TDD 让工程师先写测试再写实现，确保没有未经测试的代码进生产；在智能合约管理大量资产的 Web3 开发里，它更是关键的安全手段。不写测试的代价是技术债：隐藏问题随功能堆积增长，直到一次小改动引发灾难性故障。对测试不在意的开发者，对你的产品也不会在意。",
  "articleBody": " 博客概览/交付与 QA/QA 与生产就绪 为什么测试驱动开发值得投入 要点速览 没有无错的软件，雇最好的工程师也只是减少 bug 而不是消除，所以要写测试。TDD 让工程师先写测试再写实现，确保没有未经测试的代码进生产；在智能合约管理大量资产的 Web3 开发里，它更是关键的安全手段。不写测试的代价是技术债：隐藏问题随功能堆积增长，直到一次小改动引发灾难性故障。对测试不在意的开发者，对你的产品也不会在意。 相关服务: 软件质量保证 为什么要做测试驱动开发 测试驱动开发（TDD）是有经验的软件工程师用来确保应用状态符合预期的技术。在更传统的应用以及软件工程的整体演进里，测试已经被公认为每一套成功且专业打造的软件系统的一部分。如今，仍然有大量公司认为写测试拖慢开发、提高成本，总体上是浪费时间。希望这篇文章能照出这种说法错得有多离谱。 什么阻碍软件正常工作？ 世上没有完美写就的软件，大概也永远不会有。 “bug”这个词最早于 1946 年在哈佛被提出。当时 Grace Hopper 让一个故事流传开来：一只飞蛾在早期机电计算机里搞出了问题。Hopper 当时在哈佛做 Mark II/III 计算机系统，他发现一只飞蛾被卡在继电器里造成了故障。 把飞蛾取出后，Hopper 在笔记里写下：“First actual case of bug being found（首次真正发现 bug 的实例）。”自此“bug”一词被用来表示计算机系统中的意外行为。一个系统有 bug 的概率？100/100 个项目。如果我雇用地球上最好的工程师，系统有 bug 的概率？100/100 个项目。所以雇更好的工程师并不能解决问题。它当然会让 bug 变少，但不会让 bug 消失。这就是为什么要写测试，因为没有无错的软件。 Grace Hopper 的 bug（1946） TDD：降低成本，提升质量 在测试驱动开发（TDD）里，工程师在实现逻辑之前先写测试。不展开技术细节，这导致下列结果： 如果做得好，它确保没有未经测试的代码被推到仓库里，因为你已经先写了一份专门的测试。这能解决前面讨论的 bug 问题吗？很遗憾，不能。但它是我们手上最好的技术之一，用来创造久经考验、有韧性的软件。 \"尽早验证假设，把后面昂贵的错误降到最低。\" 那 Web3 有什么不同？ 在 Web3 开发中，安全是最高优先级。智能合约常常管理大量加密货币和其他有价值的数字资产。任何这些合约里的漏洞都会带来重大资金损失。TDD 通过促进持续测试和早期识别潜在问题，扮演了关键的安全角色。 在开发周期早期捕捉到安全缺陷，TDD 有助于防御那些会损害去中心化应用完整性的利用与攻击。测试让工程师调整代码库并立即得到反馈。如果测试写得到位，任何可能导致 bug 的代码改动都会被测试抓到并上报。 重要的是，上面这些用普通测试也能做到。所谓普通测试，就是想到“现在写一个测试”才写。许多工程师走这条路：“我现在写代码，等有时间再补测试。”从某种程度上说，这没问题。比一行测试都不写好得多！但它永远达不到 TDD 的韧性级别，因为它根本错过了重点。 我乐意重复一遍：“没有未经测试的代码会进生产”。这才是纯粹 TDD 所确保的。 完全不写测试最终会反噬你 沉默的杀手：技术债 我还欠你一个解释：为什么不写测试会让工程和维护成本爆炸。关键词是技术债。软件总会有 bug。它存在越久、越大，产生的 bug 就越多。这不是我用来强调本节而编出来的，是众所周知的事实。 因此，如果没有任何对策来发现和消除这些 bug，它们会一直留下来并影响后续加进代码库的代码，反复影响。 我们给软件加的功能越多，问题就越大。终于有一天，这座塔倒了，你站在一份已经无法控制的代码库前。 导致项目整体或部分被推倒重建。 设想一个小镇决定快速搭一座桥连接河两岸。工程师们在赶工中跳过了一些安全检查，用了更次的材料。一开始桥运行良好，大家对速度赞不绝口。时间过去，越来越多车开始走这座桥。小裂缝出现了，但被忽略了，因为桥还立着。每辆新车都增加压力，让裂缝变大。一天，一辆超重卡车开过桥，桥塌了，造成巨大停摆。 这正是定制软件开发中的技术债。早期的捷径和未经测试的代码制造隐藏问题。随着新功能不断加入，这些问题增长，直到系统变脆。最终一个看似微小的改动就能引发灾难性故障，就像超载卡车之于那座桥。如果没有测试来尽早捕捉并修复问题，软件就变得不可持续，成本飙升，最终崩塌。 建议 1： 招聘开发者时，用简单问题测试他们在测试方面的熟练度： → 你写测试的经验如何？ → 你在本项目里偏好哪种测试，为什么？ → 我们真的需要写测试吗？ 建议 2：如果他们对测试不在意，他们对你的产品也不会在意。 听起来很狠，但这是真的。 没有测试，你的项目终将死去，这一点毫无疑问。 最终思考 忽视软件测试不仅有遇到无法运行的软件的风险，还会侵蚀产品整体质量与可靠性。合适的测试不仅是为了发现 bug 与问题，更是为了确保软件满足用户预期并在各类环境下顺畅运行。 如果你想让你的产品成功，请依靠那些依靠测试的工程师。 QA 与生产就绪继续浏览此集群从核心文章开始AI 生成代码的 QA智能体测试与测试自动化：2026 试点指南外部 QA 基准：软件产品前 30 天通常会发现什么软件上线后维护要花多少钱：DACH SaaS 基准敏捷去工程化Lovable、Bolt 和 Replit 应用尽职调查 集群中的上一篇Vibe-Coded 软件审计：上线前会出什么问题 可选服务路径： 软件开发 MVP 开发 软件 QA Fractional CTO Fractional Co-Founder 看看生产环境中的应用: 债券分析平台 先做决定: 如何挑选软件开发公司 只收重要内容 关注与你相关的内容 每当我们发布新文章，你会收到一封简短邮件。你可以关注整个博客，也可以只选感兴趣的主题。 Company 电子邮箱 你希望接收哪些内容？ 完整的 Wavect 博客接收六个主题下的每一篇新文章。 仅接收所选主题请在下方选择一个或多个分类。 选择主题 AI 与智能体 产品与 MVP 交付与 QA 领导力与团队 商业与监管 Web3 与隐私 我希望接收所选的 Wavect 博客邮件，并已阅读 隐私信息。我可以随时退订。 发送确认邮件→ 免费、双重确认、不使用跟踪像素。 ",
  "articleSection": "Engineering",
  "author": {
    "@id": "https://wavect.io/team/christof-jori/#person",
    "@type": "Person",
    "name": "Christof Jori",
    "sameAs": [
      "https://www.wikidata.org/wiki/Q139796367",
      "https://www.linkedin.com/in/jocr77/",
      "https://github.com/jo-chris"
    ],
    "url": "https://wavect.io/team/christof-jori/"
  },
  "dateModified": "2026-07-07",
  "datePublished": "2024-06-17",
  "description": "没有无错的软件，雇最好的工程师也只是减少 bug 而不是消除，所以要写测试。TDD 让工程师先写测试再写实现，确保没有未经测试的代码进生产；在智能合约管理大量资产的 Web3 开发里，它更是关键的安全手段。不写测试的代价是技术债：隐藏问题随功能堆积增长，直到一次小改动引发灾难性故障。对测试不在意的开发者，对你的产品也不会在意。",
  "headline": "为什么测试驱动开发值得投入",
  "image": "https://wavect.io/img/blog/headers/header_test-driven-development.svg",
  "inLanguage": "zh",
  "mainEntityOfPage": {
    "@id": "https://wavect.io/zh/blog/test-driven-development/",
    "@type": "WebPage"
  },
  "publisher": {
    "@id": "https://wavect.io/#organization",
    "@type": [
      "Organization",
      "ProfessionalService",
      "LocalBusiness"
    ]
  },
  "url": "https://wavect.io/zh/blog/test-driven-development/",
  "wordCount": 163
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "item": "https://wavect.io/zh/",
      "name": "首页",
      "position": 1
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/zh/blog/overview/",
      "name": "博客概览",
      "position": 2
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/zh/blog/topics/delivery-qa/",
      "name": "交付与 QA",
      "position": 3
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/zh/blog/clusters/qa-production/",
      "name": "QA 与生产就绪",
      "position": 4
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/zh/blog/test-driven-development/",
      "name": "Web3中的测试驱动开发 - 博客 | ",
      "position": 5
    }
  ]
}
```
