Codelab: Gemini para acelerar el desarrollo basado en pruebas

1. Introducción

En este codelab, se presentan los principios del desarrollo basado en pruebas ( TDD), en el que escribes pruebas antes de implementar el código. Compilaremos una app de calculadora simple con Ruby para mostrar este enfoque.

También aprenderás a usar Gemini como tu asistente de programación. Gemini ayudará a acelerar el ciclo de TDD, ya que generará casos de prueba, sugerirá implementaciones de código y hasta proporcionará explicaciones del código.

Por último, verás cómo implementar la app de calculadora en Cloud Functions, la plataforma sin servidores completamente administrada de Google, para que tu app sea accesible.

2. Requisitos previos

  • Un proyecto de Google Cloud con la facturación habilitada
  • Un navegador web

Crea tu proyecto

Habilita la API de Gemini

  • Navega a Gemini Marketplace para habilitar la API. También puedes usar gcloud para habilitar la API:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID

Habilitar la API de Cloud Functions

gcloud services enable cloudfunctions.googleapis.com --project PROJECT_ID

Activar Cloud Shell

  • Usarás Cloud Shell, un entorno de línea de comandos que se ejecuta en la consola de Google Cloud y que viene precargado con los lenguajes necesarios instalados. En la consola de Cloud, haz clic en Activar Cloud Shell en la esquina superior derecha:

6757b2fb50ddcc2d.png

  • Una vez que te conectes a Cloud Shell, deberías ver que ya te autenticaste y que el proyecto se configuró con tu ID del proyecto. En Cloud Shell, ejecuta el siguiente comando para confirmar que te autenticaste:
gcloud auth list
  • En Cloud Shell, ejecuta el siguiente comando para confirmar que el comando gcloud conoce tu proyecto:
gcloud config list project
  • Si tu proyecto no está configurado, usa el siguiente comando para hacerlo:
gcloud config set project <YOUR_PROJECT_ID>

Consulta la documentación para ver los comandos y el uso de gcloud.

Abrir editor

  • En este codelab, usaremos el editor de Cloud integrado. En la ventana de Cloud Shell, haz clic en el botón Abrir editor que se encuentra en la esquina superior derecha. Se abrirá un editor de VSCode.

e5a5e95d543db556.png

Agrega la extensión de Ruby

  • En el menú del lado izquierdo, haz clic en el ícono de extensiones 999939b067e1d0dc.png, escribe vscode ruby en la barra de búsqueda y, luego, instala la extensión de VSCode Ruby.

a6fd4e37b3d847d2.png

3. Calentamiento de Gemini

Los LLMs no son determinísticos. Así que, mientras pruebas estas instrucciones, la respuesta que recibas podría ser diferente a las que se muestran en las capturas de pantalla adjuntas en el codelab.

Primero, preguntémosle a Gemini qué es un TDD. Para comenzar a conversar con Gemini en el mismo editor de Cloud Shell en el que estamos, sigue estos pasos:

  • En el lado izquierdo de la página, busca el ícono de Gemini 25fdcae4447d063c.png. Se abrirá la ventana de chat en el lado izquierdo.
  • Puedes comenzar a escribir en el cuadro de texto que dice Enter a prompt here.

5e09b0fb6a1b44dd.png

Instrucción:

What is Test Driven Development?

Respuesta:

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.
....

Te brinda una breve introducción al TDD y sus beneficios.

Ahora preguntémosle a Gemini qué es Ruby:

Instrucción:

What is Ruby?

Respuesta:

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.
....

Explica qué es Ruby y cuáles son los beneficios de usarlo como lenguaje.

4. Configuración del proyecto

Ahora, comencemos por crear una app de Sinatra simple.

  • Creemos una carpeta vacía. Puedes asignarle el nombre que desees. Para este codelab, lo llamaremos gemini-tdd. En el editor de Cloud del lado izquierdo, en la pestaña Explorer, crea una carpeta en /home/<YOUR-USERNAME>/.

d1d920b074cd7c79.png

  • Abramos la carpeta que acabamos de crear. En el menú de la izquierda, haz clic en el ícono 1d080370a3ccad53.png y, luego, en File -> Open Folder.
  • Creemos un nuevo archivo Ruby en esta carpeta raíz que actuará como punto de partida para la app. Puedes ponerle el nombre que quieras. En este codelab, lo llamaremos app.rb. 7beab8d21c59eee7.png
  • También agreguemos un Gemfile en la carpeta raíz. También será bueno preguntarle a Gemini sobre Gemfile.
  • También crearemos un archivo app_test.rb para escribir nuestros casos de prueba.

5. Implementación impulsada por Gemini

Ahora, comencemos por darle a Gemini algo de contexto sobre lo que intentamos hacer y pidámosle que genere casos de prueba para ello. Copia la siguiente instrucción en el chat de Gemini.

Instrucción:

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.

Respuesta:

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. 
.....

Te proporciona un caso de prueba de ejemplo para la app de Calculadora, es decir, para sumar dos números. También importó la dependencia requerida minitest/autorun para las pruebas. Copiemos el contenido en app_test.rb. Intentemos ejecutar esta prueba ahora. Como no escribimos ningún código, seguramente fallará.

Preguntémosle a Gemini cómo ejecutar esta prueba.

Instrucción:

How do we run the tests written in app_test.rb using ruby command?

Respuesta:

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.

Así que ejecutemos la prueba. Haz clic con el botón derecho en app_test.rb en la pestaña Explorer y, luego, en "Open in Integrated Terminal".

66b4bb9598c1feca.png

Asegúrate de estar en la misma carpeta que el archivo app_test.rb. Si no es así, usa el comando cd para llegar allí. En la terminal, ejecuta el comando que devolvió Gemini:

ruby app_test.rb

Aparecerá el siguiente error:

NameError: uninitialized constant Calculator

Preguntémosle a Gemini cómo solucionarlo directamente desde el editor. Haz clic en el ícono de chat en el panel de navegación del editor de Cloud Shell y haz la siguiente solicitud:

Instrucción:

NameError: uninitialized constant Calculator. Give me Calculator class code.

Respuesta:

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 nos indica que no tenemos una clase llamada Calculator y que debemos crear una. También nos proporcionó el código para crear la clase Calculator. Usemos este código. Abre app.rb desde la pestaña Explorer y copia el código que te proporcionó Gemini. Mientras modificas el contenido en app.rb, es posible que Gemini te dé algunas sugerencias como autocompletar. Debes presionar tab si quieres aceptarlas o Esc si no.

Ahora, volvamos a ejecutar la prueba. Escribe el siguiente comando en tu terminal integrada:

ruby app_test.rb

Sin embargo, seguirás encontrando el mismo error "NameError: uninitialized constant Calculator". Preguntémosle a Gemini cómo solucionarlo.

6. TDD iterativo con Gemini

Instrucción:

I am still getting this error: "NameError: uninitialized constant Calculator".

Respuesta:

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
....

Nos dio alguna respuesta, que puede ser la misma que la anterior o no. Por lo tanto, indiquemos explícitamente a Gemini que tenemos la clase Calculator definida en app.rb .

Instrucción:

Calculator class is defined in app.rb already.

Respuesta:

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"

Obtuvimos la respuesta de Gemini para importar el archivo app.rb en el que tenemos definida la clase Calculator. A veces, es posible que necesites entre 2 y 3 iteraciones de instrucciones para obtener la respuesta correcta, pero, a medida que te acostumbres, mejorarás. Ten en cuenta que es posible que también veas require "./app" en la respuesta de Gemini. Agreguemos esto a app.rb en app_test.rb y volvamos a ejecutar la misma prueba.

Asegúrate de que, en este punto, tu archivo app_test.rb se vea de la siguiente manera:

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

Ejecuta el siguiente comando desde la terminal de Cloud Shell dentro de la carpeta del proyecto:

ruby app_test.rb

Si todo sale bien, la prueba debería aprobarse. Por lo tanto, desarrollamos una app de Ruby muy simple con el enfoque de TDD y recurrimos a la ayuda de Gemini. Las respuestas a las instrucciones no serán las mismas todo el tiempo, y eso es propio de los modelos LLM. Es posible que obtengas más operaciones de la Calculadora de Gemini, pero, en general, debería funcionar el mismo proceso que acabamos de seguir.

7. Implementa la app en Cloud Functions

Ahora, pidámosle a Gemini que implemente esto en Cloud Functions:

Instrucción:

Let's deploy this app to Cloud Functions

Respuesta:

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 explica cómo implementarla de forma manual con la IU de Cloud Functions. Pero no quiero hacerlo. Pidámosle a Gemini que nos proporcione el comando gcloud que puedo ejecutar directamente desde la terminal integrada.

Instrucción:

How do I deploy this app to Cloud Functions gen2 using the gcloud command?

Respuesta:

...
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

Ejecutemos el comando de gcloud que proporcionó Gemini en la terminal.

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app

Aparecerá el siguiente error:

"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"

Recurramos a Gemini para corregir el error.

Instrucción:

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

Respuesta:

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.
...

Ejecutemos bundle install en la terminal, lo que creará Gemfile.lock . Después de ejecutar el comando, revisa la pestaña del explorador. Deberías poder ver el Gemfile.lock.

Intentemos implementar en Cloud Functions nuevamente. Ejecuta el mismo comando de implementación en la terminal:

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app

Aparecerá otro error:

"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. Functions Framework para Ruby

Preguntémosle a Gemini sobre el error:

Instrucción:

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

Respuesta:

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.
....

Básicamente, falta la gema functions_framework en nuestra app. Agreguemos esta línea en nuestro Gemfile:

gem "functions_framework"

Ahora ejecuta bundle install en la terminal. Es posible que aparezca o no un error que diga "No explicit global resource in Gemfile" . Si te encuentras con este problema, asegúrate de que la primera línea de tu Gemfile sea la siguiente:

source "https://rubygems.org"

Luego, vuelve a ejecutar bundle install desde la terminal. Ahora, volvamos a ejecutar el comando de implementación:

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app --project PROJECT_ID

Ahora, aparecerá el siguiente error:

"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"

Para resolver este problema, probemos la función Generate Code de Gemini. Abramos app.rb desde la pestaña Explorer, donde ya tenemos el código de la app de calculadora. En app.rb, en la primera línea, comienza a escribir FunctionsFramework y, luego, escribe ".". Verás algunas sugerencias en texto gris :

9e17476a4a586433.png

Presiona Tab para aceptar la sugerencia. Una vez que se acepte, verás más sugerencias como las que se muestran a continuación:

f3c35d1539789acc.png

Presiona Tab para aceptar más sugerencias. Por lo tanto, tu app.rb debería verse así:

( Cambia el nombre de la función de add a 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

Acabamos de crear el punto de entrada para la app de Cloud Functions y también aprendimos a usar la sugerencia de código de Gemini en el editor. Ahora, intentemos implementar la app nuevamente.

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app --project PROJECT_ID

Si todo sale bien, la implementación debería completarse y deberías poder ver la URL en la que se aloja tu app. Bien, modifiquemos un poco el archivo app.rb para que muestre el resultado de la suma. Tu archivo app.rb final debería verse de la siguiente manera:

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. Pruebas de extremo a extremo

Abre la URL y pasa los parámetros de búsqueda a y b como se muestra a continuación:

https://[APP-URL]/?a=2&b=3

Deberías poder ver la respuesta como "Result: 5". Una calculadora realiza muchas operaciones. Puedes extender esta app para que también realice esas tareas y pedirle ayuda a Gemini para hacerlo.

10. Conclusión

Hoy vimos cómo desarrollar una app de Ruby con el enfoque de TDD con la ayuda de Gemini. Como notaste, Gemini puede brindarte diferentes resultados, pero sin duda puede ayudarte a acelerar el proceso de desarrollo en un idioma con el que quizás no estés tan familiarizado y mostrarte funciones o fragmentos para acelerar tu curva de aprendizaje.

Cualquier desarrollador ( independientemente de su experiencia) puede obtener ayuda de Gemini para su proceso de desarrollo. Si no es para desarrollar, puedes usar Gemini para explicar el código existente y pedirle que genere pruebas para el código existente, que es el trabajo más aburrido para mí, al menos 🙂.

¡Feliz programación con Gemini!