1. 简介
此 Codelab 介绍了测试驱动开发 ( TDD) 的原则,即在实现代码之前先编写测试。我们将使用 Ruby 构建一个简单的计算器应用来展示这种方法。
您还将了解如何将 Gemini 用作编码助理。Gemini 将通过生成测试用例、建议代码实现,甚至提供代码说明来帮助加快 TDD 周期。
最后,您将了解如何将计算器应用部署到 Google 的全代管式无服务器平台 Cloud Functions,从而使您的应用可供访问。
2. 前提条件
- 启用了结算功能的 Google Cloud 项目
- 网络浏览器
创建项目
- 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 确保您的云项目已启用结算功能。了解如何检查项目是否已启用结算功能。
启用 Gemini API
- 前往 Gemini Marketplace 启用该 API。您还可以使用 gcloud 启用 API:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID
- 访问 Gemini 页面,然后点击“开始聊天”。
- 重要提示:请按照此 Codelab 中的第 1 步和第 2 步操作,分别开始使用 Gemini 并在 Cloud Shell IDE 中启用 Gemini。
启用 Cloud Functions API
- 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
- 前往 Cloud Functions API 页面以启用该 API。您还可以使用 gcloud 启用 API:
gcloud services enable cloudfunctions.googleapis.com --project PROJECT_ID
激活 Cloud Shell
- 您将使用 Cloud Shell,这是一个在 Google Cloud 控制台中运行的命令行环境,它预加载了已安装的必需语言。在 Cloud 控制台中,点击右上角的激活 Cloud Shell:

- 在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID。在 Cloud Shell 中运行以下命令,以确认您已通过身份验证:
gcloud auth list
- 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目:
gcloud config list project
- 如果项目未设置,请使用以下命令进行设置:
gcloud config set project <YOUR_PROJECT_ID>
如需了解 gcloud 命令和用法,请参阅文档。
打开编辑器
- 在此 Codelab 中,我们将使用内置的 Cloud 编辑器。在 Cloud Shell 窗口中,点击右上角的“打开编辑器”按钮。系统随即会打开 VSCode 编辑器。

添加 Ruby 扩展程序
- 在左侧侧边菜单中,点击扩展程序图标
,在搜索栏中输入 vscode ruby,然后安装 VSCode Ruby 扩展程序。

3. Gemini 热身
LLM 具有不确定性。因此,在您尝试提出这些问题时,您收到的回答可能与 Codelab 中附加的屏幕截图中的回答有所不同。
我们先问问 Gemini 什么是 TDD。如需在当前 Cloud Shell 编辑器中开始与 Gemini 对话,请按以下步骤操作:
- 在页面左侧,找到 Gemini 图标
,这会在左侧打开聊天窗口。 - 您可以在显示
Enter a prompt here的文本框中开始输入内容

提示:
What is Test Driven Development?
回答:
Test-driven development (TDD) is a software development methodology that requires developers to write automated tests before writing any production code. This helps ensure the code is correct and meets the requirement. ....
简要介绍了 TDD 及其优势。
现在,我们来问问 Gemini Ruby 是什么:
提示:
What is Ruby?
回答:
Ruby is a general-purpose, interpreted, object-oriented programming language. It is designed to be easy to read and write. Ruby is dynamically typed, meaning that the type of a variable is not declared and can change during execution. ....
它介绍了 Ruby 是什么,以及使用 Ruby 作为语言的优势。
4. 项目设置
现在,我们先来创建一个简单的 Sinatra 应用。
- 我们来创建一个空文件夹。您可以随意为其命名。在此 Codelab 中,我们将其称为
gemini-tdd。在左侧云端编辑器中的“探索器”标签页下,在/home/<YOUR-USERNAME>/下创建文件夹

- 我们来打开刚刚创建的文件夹。在最左侧的菜单中,点击图标
,然后依次点击“文件”->“打开文件夹”。 - 我们在此根文件夹中创建一个新的 Ruby 文件,作为应用的起点,您可以随意命名该文件。在此 Codelab 中,我们将此值称为
app.rb。
- 我们还在根文件夹中添加了
Gemfile。最好也向 Gemini 询问一下Gemfile。 - 我们还将创建一个
app_test.rb文件来编写测试用例。
5. Gemini 驱动的实现
现在,我们先向 Gemini 提供一些有关我们尝试执行的操作的背景信息,然后让它生成相应的测试用例。在 Gemini 对话提示中复制以下提示。
提示:
Answer as a software engineer with Ruby expertise. We want to build a Ruby calculator application with a test driven development approach. Let's start by writing some tests for the calculator app using minitest gem.
回答:
Here is a simple test for a calculator app that adds two numbers:
require "minitest/autorun"
describe "Calculator" do
it "should add two numbers" do
calculator = Calculator.new
assert_equal 5, calculator.add(2, 3)
end
end
This test uses the assert_equal method to verify that the result of the add method is correct. .....
它会为您提供计算器应用的示例测试用例,即用于添加两个数字的测试用例。它还为测试导入了所需的依赖项 minitest/autorun。我们将内容复制到 app_test.rb。现在,我们来尝试运行此测试;由于我们尚未编写任何代码,因此测试肯定会失败。
我们来问问 Gemini 如何运行此测试。
提示:
How do we run the tests written in app_test.rb using ruby command?
回答:
To run the tests written in app_test.rb using the ruby command, you can use the following steps: 1.Make sure that you are in the same directory as the app_test.rb file. 2.Open a terminal window. 3.Type the following command:
ruby app_test.rb
This will run all of the tests in the app_test.rb file and report the results.
接下来,我们运行测试。在“资源管理器”标签页中右键点击 app_test.rb,然后点击“在集成终端中打开”

确保您位于与文件 app_test.rb 相同的文件夹中,否则请使用 cd 命令进入该文件夹。在终端中,运行 Gemini 返回的命令:
ruby app_test.rb
您会遇到以下错误:
NameError: uninitialized constant Calculator
我们来问问 Gemini 如何直接在编辑器中修复此问题。点击 Cloud Shell 编辑器的导航窗格中的聊天图标,然后输入以下提示:
提示:
NameError: uninitialized constant Calculator. Give me Calculator class code.
回答:
The error you are getting is because you have not defined the Calculator class. You need to define the Calculator class before you can use it in your tests. Here is the code for the Calculator class:
Class Calculator
def add(a, b)
a + b
end
end
Once you have defined the Calculator class, you can run the tests again and they will pass. .....
Gemini 告诉我们,我们没有名为 Calculator 的类,需要创建一个。它还提供了用于创建 Calculator 类的代码。我们继续使用此代码。从“资源管理器”标签页中打开 app.rb,然后复制 Gemini 在其中提供的代码。在修改 app.rb 中的内容时,您可能会收到 Gemini 以自动补全形式提供的一些建议;如果您想接受建议,需要按 tab,否则按 Esc。
现在,我们再次运行测试。在集成式终端中输入以下命令:
ruby app_test.rb
但您仍会遇到相同的错误“NameError: uninitialized constant Calculator”。我们来问问 Gemini 如何解决此问题。
6. 使用 Gemini 进行迭代式 TDD
提示:
I am still getting this error: "NameError: uninitialized constant Calculator".
回答:
The error you are getting is because you have not defined the Calculator class. You need to define the Calculator class before you can use it in your tests. Here is the code for the Calculator class:
class Calculator
def add(a, b)
a + b
end
def subtract(a, b)
a - b
end
def multiply(a, b)
a * b
end
def divide(a, b)
a / b
end
end
....
它给出了一些回答,可能与上述回答相同,也可能不同。因此,我们明确告知 Gemini,我们在 app.rb 中定义了 Calculator 类。
提示:
Calculator class is defined in app.rb already.
回答:
I see that the Calculator class is defined in the app.rb file. However, you are getting the NameError error because you are trying to use the Calculator class in the app_test.rb file without requiring the app.rb file. To fix this, you need to add the following line to the top of the app_test.rb file:
require_relative "app"
我们收到了 Gemini 的回答,其中包含用于导入定义了 Calculator 类的 app.rb 的代码。有时,您可能需要迭代 2-3 次提示才能获得正确的回答,但随着您逐渐掌握技巧,效果会越来越好。请注意,在 Gemini 的回答中,您可能还会看到 require "./app"。我们将其添加到 app_test.rb 中的 app.rb,然后再次运行相同的测试。
请确保此时您的 app_test.rb 如下所示:
require "minitest/autorun"
require "./app"
describe "Calculator" do
it "should add two numbers" do
calculator = Calculator.new
assert_equal 5, calculator.add(2, 3)
end
end
在项目文件夹中,从 Cloud Shell 终端运行以下命令:
ruby app_test.rb
如果一切顺利,测试应该会通过。因此,我们使用 TDD 方法开发了一个非常简单的 Ruby 应用,并借助了 Gemini 的帮助。提示回答不会每次都相同,这是 LLM 模型的本质。您可能会从 Gemini 获得更多计算器操作,但总体而言,我们刚刚介绍的流程应该可以正常运行。
7. 将应用部署到 Cloud Functions
现在,我们问问 Gemini 将此函数部署到 Cloud Functions:
提示:
Let's deploy this app to Cloud Functions
回答:
To deploy your app to Cloud Functions, you can use the following steps: 1.Create a new Cloud Functions project. 2.Create a new Cloud Function. 3.Set the trigger for the Cloud Function to be an HTTP request. 4.Set the entry point for the Cloud Function to be the app method in the app.rb file. 5.Deploy the Cloud Function. Once you have deployed the Cloud Function, you can test it by sending an HTTP request to the function's URL. ....
Gemini 介绍了如何使用 Cloud Functions 界面手动部署该函数。但我不想这样做。我们让 Gemini 提供 gcloud 命令,我可以从集成式终端直接运行该命令。
提示:
How do I deploy this app to Cloud Functions gen2 using the gcloud command?
回答:
...
Here are the specific commands you can use to deploy your app to Cloud Functions using the gcloud command:
gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app
This command will create a new Cloud Function called calculator that is triggered by an HTTP request and uses the app method in the app.rb file as the entry point.
Once the Cloud Function is deployed, you can test it by sending an HTTP request to the function's URL. For example, you can use the following command to send a request to the function:
curl -X POST -H "Content-Type: application/json" -d '{"a": 2, "b": 3}' https://REGION-PROJECT_ID.cloudfunctions.net/calculator
我们来在终端中执行 Gemini 提供的 gcloud 命令。
gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app
您会遇到以下错误:
“ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: Could not find Gemfile.lock file in your app. Please make sure your bundle is up to date before deploying.; Error ID: 7916f05c”
我们来借助 Gemini 修复此错误。
提示:
ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: Could not find Gemfile.lock file in your app. Please make sure your bundle is up to date before deploying.; Error ID: 7916f05c
回答:
It looks like you're trying to deploy a function to Cloud Functions, but you don't have a Gemfile.lock file in your app. To fix this, run the following command in your app directory:
bundle install
This will create a Gemfile.lock file that lists all of the gems that your app uses. ...
让我们在终端中运行 bundle install,这将创建 Gemfile.lock。运行命令后,检查资源管理器标签页,您应该能够看到 Gemfile.lock。
我们再尝试部署到 Cloud Functions。在终端中执行相同的部署命令:
gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app
您会遇到以下另一个错误:
“ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: unable to execute functions-framework-ruby; please ensure a recent version of the functions_framework gem is in your Gemfile; Error ID: 89ae7dda”
8. Ruby 版 Functions 框架
我们来问问 Gemini 关于此错误的信息:
提示:
ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: unable to execute functions-framework-ruby; please ensure a recent version of the functions_framework gem is in your Gemfile; Error ID: 89ae7dda
回答:
It looks like you're trying to deploy a function to Cloud Functions, but the build is failing because the functions_framework gem is not in your Gemfile. To fix this, add the following line to your Gemfile: gem "functions_framework" Then, run the following command to install the gem: bundle install Once the gem is installed, you can try deploying your function again. ....
因此,我们的应用中缺少 functions_framework gem。我们继续在 Gemfile 中添加以下代码行:
gem "functions_framework"
现在,在终端中运行 bundle install。您可能会遇到或可能不会遇到“No explicit global resource in Gemfile”错误。如果您遇到此问题,请确保您的 Gemfile 的第一行为以下内容:
source "https://rubygems.org"
然后,再次从终端运行 bundle install。现在,我们再次运行部署命令:
gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app --project PROJECT_ID
您现在会遇到以下错误:
“ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: failed to verify function target "app" in source "app.rb": Undefined function: "app"; Error ID: e12ab0f9”
为了解决这个问题,我们来试试 Gemini 的 Generate Code 功能。我们来打开“资源管理器”标签页中的 app.rb,其中已包含计算器应用代码。在 app.rb 的第一行中,先输入 FunctionsFramework,然后输入“.”。您会看到一些灰色文字的建议:

按 Tab 键可接受建议。接受后,您会看到更多建议,如下所示:

按 Tab 键可接受更多建议。因此,您的 app.rb 应如下所示:
(将函数名称从 add 重命名为 app)
require "functions_framework"
FunctionsFramework.http "app" do |request|
a = request.params["a"].to_i
b = request.params["b"].to_i
Calculator.new.add(a, b)
end
class Calculator
def add(a, b)
a + b
end
end
我们刚刚创建了 Cloud Functions 应用的入口点,还学习了如何在编辑器中使用 Gemini 的代码建议。现在,我们再次尝试部署应用。
gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app --project PROJECT_ID
如果一切顺利,部署应该会完成,并且您应该能够看到托管应用的网址。很好,我们来稍微修改一下 app.rb,以返回加法结果。最终的 app.rb 应如下所示:
require "functions_framework"
FunctionsFramework.http "app" do |request|
a = request.params["a"].to_i
b = request.params["b"].to_i
calculator = Calculator.new
add = calculator.add(a, b)
"Result: #{add}"
end
class Calculator
def add(a, b)
a + b
end
end
9. 端到端测试
打开网址并传递查询参数 a 和 b,如下所示:
https://[APP-URL]/?a=2&b=3
您应该能够看到以下响应:"Result: 5"。计算器可以执行很多操作。您可以扩展此应用,使其也能执行这些操作,并在此过程中获得 Gemini 的帮助。
10. 总结
我们了解了如何在 Gemini 的帮助下使用 TDD 方法开发 Ruby 应用。如您所见,Gemini 可能会给出不同的结果,但它肯定有助于加快您不太熟悉的语言的开发流程,并且仍然可以向您展示函数或代码段,从而缩短您的学习曲线。
任何开发者(无论经验如何)都可以在开发过程中获得 Gemini 的帮助。如果不用于开发,您可以使用 Gemini 来解释现有代码,还可以让它为现有代码生成测试,这至少对我来说是最无聊的工作 🙂
祝您使用 Gemini 愉快地编写代码!