• 使用babyapi的简单示例创建初始main.go

  • 使用 CLI 生成测试样板

  • 通过用预期的 JSON 填充占位符来实现每个测试

  • 运行测试并查看它们是否通过!

  • 由于 PUT 是幂等的,因此需要包含所有字段。为了避免这种情况,我们希望添加对使用 PATCH 请求切换 Completed 的支持。我们首先添加一个简单的测试来了解我们期望此功能的外观

  • 此测试失败,因为babyapi默认不支持PATCH。我们可以通过为 TODO 结构实现 Patch 来修复它。由于我们通过两个测试定义了我们的功能,因此我们最简单的实现不仅仅是设置 Completed = true 并且我们必须使用请求中的值

  • 现在我们可以更改 TODO 的已完成状态,但我们仍然无法使用 PATCH 来修改其他字段,如这组新测试所示

  • 更新补丁以设置剩余字段

  • 我们的测试仍然失败,因为我们总是使用请求字段更新 TODO,即使它们是空的。通过更新实现来检查空值来修复此问题

  • 新的 UpdateWithPatch 测试通过,但我们之前的测试失败。由于我们将 Completed 更改为 *bool,因此使用空值创建的 TODO 将显示为 null

  • 为 TODO 实现渲染,这样我们就可以将 nil 视为 false

  • 通过测试驱动开发来实现 PATCH 功能,从而产生了一组强大的测试和良好实现的功能。由于我们首先在测试中定义 PATCH 请求的预期输入和输出,因此很容易看到由于不检查请求中的空值而导致的问题。此外,当将 Completed 类型更改为 *bool 时,我们预先存在的测试能够防止重大更改。

    结论

    测试驱动开发是创建经过充分测试的正确代码的有效方法。通过从测试开始,我们可以确保每段代码都被设计为可测试的,而不是让测试成为事后的想法。

    如果您对采用 TDD 犹豫不决,这里有一些可以开始的想法:

    即使 TDD 不太适合您编写代码的方式,它仍然是您随身携带的强大工具。我鼓励您至少花一些时间尝试一下,看看它如何影响您的开发过程。

    ","image":"http://www.luping.net/uploads/20240730/172232678666a89f02dc4a5.jpg","datePublished":"2024-07-30T16:06:26+08:00","dateModified":"2024-07-30T16:06:26+08:00","author":{"@type":"Person","name":"luping.net","url":"https://www.luping.net/articlelist/0_1.html"}}
    」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
    首頁 > 程式設計 > Go 中的測試驅動 API 開發

    Go 中的測試驅動 API 開發

    發佈於2024-07-30
    瀏覽:778

    Test-driven API Development in Go

    介绍

    测试驱动开发是确保代码经过良好测试和可重构的有效方法。基本思想是通过编写测试开始开发。这些测试清楚地记录了期望并为成功实施创建了标准。如果做得正确,您可以在编写任何代码之前清楚地定义函数的预期输入/输出。这有一些直接的好处:

    • 您仔细考虑与代码交互的界面并将其设计为可测试的
    • 当您开始编写代码时,您的流程不会因手动测试或单步执行执行逻辑来预测结果而中断。相反,您只需运行测试
    • 通过测试成为一个令人满意的目标。将流程分解为一系列明确且可实现的里程碑使工作变得更加愉快
    • 避免实施后的懒惰和过度自信,这可能会阻止您测试代码

    现在您已确信这些好处,您可以按照以下步骤开始测试驱动开发 (TDD):

    1. 编写或修改测试
    2. 检查测试是否失败
    3. 编写最少数量的代码以使测试通过

    这些步骤是循环执行的,因此您总是添加更多测试来挑战当前的实现。

    最后一步,指定编写最少量的代码,如果严格遵循,事情可能会变得乏味。在确定何时适合偏离该规则之前,了解该规则存在的原因非常重要。

    简单的例子

    您的任务是实现函数 Add(x, y int) int。在跳转到实现并返回 x y 之前,编写最简单的测试:1 1 == 2。那么,通过测试的最简单实现是什么?只是返回 2。现在你的测试通过了!

    此时,您意识到需要更多测试,因此您加快了步伐并添加了更多测试:

    • 1 2 == 3
    • 100 5 == 105

    现在您的测试失败了,因此您需要修复实现。这次你不能只返回 3 或返回 105,所以你需要找到一个适用于所有测试的解决方案。这导致了实现: return x y.

    虽然在这个简单的示例中这感觉过于乏味,但严格遵守此方法会导致您编写多个测试而不是仅仅信任您的实现。当然,您最初返回 x y 的想法是可行的,但重点是重新训练自己依赖测试而不是您自己对代码的理解。在现实世界中,您并不是唯一一个处理这段代码的人,并且不可避免地会忘记实现细节。这个过程迫使你编写更多的测试并思考更多的方法来打破简单的实现。

    最终,您将获得经验并学会找到适合您遇到的不同场景的平衡点。您将恢复全速实现功能,并发现错误更少并编写更多可维护的代码。

    HTTP API 的逐步 TDD

    让我们进入一个使用 TDD 实现 HTTP REST API 的更复杂的示例。本分步指南使用我的 Go 框架babyapi,但这些概念可以应用于任何地方。

    babyapi 使用泛型围绕 Go 结构创建完整的 CRUD API,从而使创建完整的 REST API 和客户端 CLI 变得非常容易。除此之外,babytest 包还提供了一些用于创建端到端 API 表测试的工具。在 API 级别使用 TDD 可以一次性全面测试新 API 或功能的 HTTP 和存储层。

    免责声明:由于babyapi 处理大部分实现并且还用于生成测试样板,因此从技术上讲我们并不是从TDD 开始。然而,我们将看到在我们的 API 中添加对 PATCH 请求的支持有多么有益。

    1. 创建一个新的Go项目

    2. 使用babyapi的简单示例创建初始main.go

    3. 使用 CLI 生成测试样板

    4. 通过用预期的 JSON 填充占位符来实现每个测试

    5. 运行测试并查看它们是否通过!

    6. 由于 PUT 是幂等的,因此需要包含所有字段。为了避免这种情况,我们希望添加对使用 PATCH 请求切换 Completed 的支持。我们首先添加一个简单的测试来了解我们期望此功能的外观

    7. 此测试失败,因为babyapi默认不支持PATCH。我们可以通过为 TODO 结构实现 Patch 来修复它。由于我们通过两个测试定义了我们的功能,因此我们最简单的实现不仅仅是设置 Completed = true 并且我们必须使用请求中的值

    8. 现在我们可以更改 TODO 的已完成状态,但我们仍然无法使用 PATCH 来修改其他字段,如这组新测试所示

    9. 更新补丁以设置剩余字段

    10. 我们的测试仍然失败,因为我们总是使用请求字段更新 TODO,即使它们是空的。通过更新实现来检查空值来修复此问题

    11. 新的 UpdateWithPatch 测试通过,但我们之前的测试失败。由于我们将 Completed 更改为 *bool,因此使用空值创建的 TODO 将显示为 null

    12. 为 TODO 实现渲染,这样我们就可以将 nil 视为 false

    通过测试驱动开发来实现 PATCH 功能,从而产生了一组强大的测试和良好实现的功能。由于我们首先在测试中定义 PATCH 请求的预期输入和输出,因此很容易看到由于不检查请求中的空值而导致的问题。此外,当将 Completed 类型更改为 *bool 时,我们预先存在的测试能够防止重大更改。

    结论

    测试驱动开发是创建经过充分测试的正确代码的有效方法。通过从测试开始,我们可以确保每段代码都被设计为可测试的,而不是让测试成为事后的想法。

    如果您对采用 TDD 犹豫不决,这里有一些可以开始的想法:

    • 在函数的输入/输出清晰且实现不太复杂的简单场景中尝试。您可以为可能遇到的各种输入/输出编写一个强大的表测试。清晰地了解不同的场景可以简化实施
    • 如果您正在修复新的错误,那么您已经在测试中发现了差距。首先编写一个可以首先识别此错误的测试。然后,在不破坏任何现有测试的情况下使该测试通过。
    • 与babyapi示例类似,您可以使用TDD进行高级API测试。一旦您定义了预期的请求/响应,您就可以恢复通常的开发流程,以实现更注重细节的部分

    即使 TDD 不太适合您编写代码的方式,它仍然是您随身携带的强大工具。我鼓励您至少花一些时间尝试一下,看看它如何影响您的开发过程。

    版本聲明 本文轉載於:https://dev.to/calvinmclean/test-driven-api-development-in-go-1fb8?1如有侵犯,請聯絡[email protected]刪除
    最新教學 更多>
    • 如何從Maven存儲庫中下載源罐子和Javadocs?
      如何從Maven存儲庫中下載源罐子和Javadocs?
      [2 ]步驟1:下載源代碼執行以下命令,以下載所有項目依賴項的源代碼: mvn dependenty:sources 步驟2 : Download JavadocsTo download Javadocs, use the following command:mvn dependency:resol...
      程式設計 發佈於2025-02-06
    • 在映射到MySQL枚舉列時,如何確保冬眠保留值?
      在映射到MySQL枚舉列時,如何確保冬眠保留值?
      在hibernate中保存枚舉值:故障排除錯誤的列type ,他們各自的映射至關重要。在Java中使用枚舉類型時,至關重要的是,建立冬眠的方式如何映射到基礎數據庫。 在您的情況下,您已將MySQL列定義為枚舉,並在Java中創建了相應的枚舉代碼。但是,您遇到以下錯誤:“ MyApp中的錯誤列類型...
      程式設計 發佈於2025-02-06
    • 如何將HTML字符串轉換為DOM元素以將其附加到DOM樹上?
      如何將HTML字符串轉換為DOM元素以將其附加到DOM樹上?
      將html字符串轉換為dom elements 可以使用Domparser類,如下所示: var xmlString =“< div> [&& && && &&&華[&華[&&華使用標準DOM方法。
      程式設計 發佈於2025-02-06
    • 哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
      哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
      在Python 射線tracing方法Matplotlib's path.contains_points FunctionMatplotlib's path.contains_points function employs a路徑對象表示多邊形。它檢查給定點是否位於定義路徑內。 T...
      程式設計 發佈於2025-02-06
    • 如何在Java列表中有效計算元素的發生?
      如何在Java列表中有效計算元素的發生?
      計數列表中的元素出現在列表 中,在java編程中,列舉列表中列舉元素出現的任務來自列表。為此,收集框架提供了全面的工具套件。 在這種情況下,Batocurrences變量將保持值3,代表動物列表中的“ BAT”出現的數量。 &&& [此方法是簡單的,可以得出準確的結果,使其成為計算列表中元素出現的...
      程式設計 發佈於2025-02-06
    • 為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
      為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
      [2明確擔心Microsoft Visual C(MSVC)在正確實現兩相模板實例化方面努力努力。該機制的哪些具體方面無法按預期運行? 背景:說明:的初始Syntax檢查在範圍中受到限制。它未能檢查是否存在聲明名稱的存在,導致名稱缺乏正確的聲明時會導致編譯問題。 為了說明這一點,請考慮以下示例:一個...
      程式設計 發佈於2025-02-06
    • 'exec()
      'exec()
      Exec對本地變量的影響: exec function,python staple,用於動態代碼執行的python staple,提出一個有趣的Query:它可以在函數中更新局部變量嗎? python 3 Dialemma 在Python 3中,以下代碼shippet無法更新本地變量,因為人...
      程式設計 發佈於2025-02-06
    • 如何使用PHP從XML文件中有效地檢索屬性值?
      如何使用PHP從XML文件中有效地檢索屬性值?
      從php 您的目標可能是檢索“ varnum”屬性值,其中提取數據的傳統方法可能會使您感到困惑。 - > attributes()為$ attributeName => $ attributeValue){ echo $ attributeName,'=“',$ a...
      程式設計 發佈於2025-02-06
    • 如何使用不同數量列的聯合數據庫表?
      如何使用不同數量列的聯合數據庫表?
      合併列數不同的表 當嘗試合併列數不同的數據庫表時,可能會遇到挑戰。一種直接的方法是在列數較少的表中,為缺失的列追加空值。 例如,考慮兩個表,表 A 和表 B,其中表 A 的列數多於表 B。為了合併這些表,同時處理表 B 中缺失的列,請按照以下步驟操作: 確定表 B 中缺失的列,並將它們添加到表的...
      程式設計 發佈於2025-02-06
    • 如何使用Python的記錄模塊實現自定義處理?
      如何使用Python的記錄模塊實現自定義處理?
      使用Python的Loggging Module 確保正確處理和登錄對於疑慮和維護的穩定性至關重要Python應用程序。儘管手動捕獲和記錄異常是一種可行的方法,但它可能乏味且容易出錯。 解決此問題,Python允許您覆蓋默認的異常處理機制,並將其重定向為登錄模塊。這提供了一種方便而係統的方法來捕獲...
      程式設計 發佈於2025-02-06
    • 如何從Google API中檢索最新的jQuery庫?
      如何從Google API中檢索最新的jQuery庫?
      從Google APIS 問題中提供的jQuery URL是版本1.2.6。對於檢索最新版本,以前有一種使用特定版本號的替代方法,它是使用以下語法: https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js(google hosted...
      程式設計 發佈於2025-02-06
    • 為什麼使用Firefox後退按鈕時JavaScript執行停止?
      為什麼使用Firefox後退按鈕時JavaScript執行停止?
      導航歷史記錄問題:JavaScript使用Firefox Back Back 此行為是由瀏覽器緩存JavaScript資源引起的。 To resolve this issue and ensure scripts execute on subsequent page visits, Firefox...
      程式設計 發佈於2025-02-06
    • 如何檢索SQL中每個用戶的最新登錄日期?
      如何檢索SQL中每個用戶的最新登錄日期?
      SQL查詢每個用戶的最後登錄記錄日期 問題: 假設數據庫表包含用戶登錄信息,我們如何檢索每個用戶的最後登錄日期?考慮到可能存在重複的登錄日期。 解決方案: 解決此問題有兩種常見方法: 方法一:使用INNER JOIN的子查詢 此方法利用子查詢來識別每個用戶的最後登錄日期,然後用於過濾主表: se...
      程式設計 發佈於2025-02-06
    • 如何有效處理Java中的時區轉換?
      如何有效處理Java中的時區轉換?
      跨時區的時區轉換 java.util.date類缺乏明確的時區分配。它的Tostring方法誤導了JVM的默認時區,導致混亂。為了避免這些陷阱,現代Java利用Java.Time軟件包進行更健壯的時間處理。 在Java.Time中轉換時區,指定一個時區並調用ZonedDateTime.now方...
      程式設計 發佈於2025-02-06
    • 為什麼我的燒瓶應用程序會拋出“ templatenotfound”錯誤,即使我的模板文件存在?
      為什麼我的燒瓶應用程序會拋出“ templatenotfound”錯誤,即使我的模板文件存在?
      故障排除flask的templatenotfound錯誤 在嘗試在flask中渲染模板,例如'home.html' ,您可能會遇到''''',您可能會遇到''' jinja2.exceptions.templateno...
      程式設計 發佈於2025-02-06

    免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

    Copyright© 2022 湘ICP备2022001581号-3