Codelab: Gemini per accelerare lo sviluppo basato sui test

1. Introduzione

Questo codelab introduce i principi dello sviluppo guidato dal test ( TDD ), in cui scrivi test prima di implementare il codice. Creeremo una semplice app di calcolatrice utilizzando Ruby per dimostrare questo approccio.

Imparerai anche a utilizzare Gemini, come assistente di programmazione. Gemini contribuirà ad accelerare il ciclo TDD generando scenari di test, suggerendo implementazioni del codice e persino fornendo spiegazioni sul codice.

Infine, scoprirai come eseguire il deployment dell'app Calcolatrice in Cloud Functions, la piattaforma serverless completamente gestita di Google, che rende accessibile la tua app.

2. Prerequisiti

  • Un progetto Google Cloud con fatturazione abilitata
  • Un browser web

Creazione di un progetto

Abilita l'API Gemini

  • Vai a Gemini Marketplace per abilitare l'API. Puoi anche utilizzare gcloud per abilitare l'API:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID

Abilita l'API Cloud Functions

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

Attiva Cloud Shell

  • Utilizzerai Cloud Shell, un ambiente a riga di comando in esecuzione nella console Google Cloud in cui sono precaricati i linguaggi richiesti installati. Dalla console Cloud, fai clic su Attiva Cloud Shell nell'angolo in alto a destra:

6757b2fb50ddcc2d.png

  • Una volta stabilita la connessione a Cloud Shell, dovresti vedere che hai già eseguito l'autenticazione e che il progetto è impostato sul tuo ID progetto. Esegui questo comando in Cloud Shell per confermare l'autenticazione:
gcloud auth list
  • Esegui questo comando in Cloud Shell per confermare che il comando gcloud è a conoscenza del tuo progetto:
gcloud config list project
  • Se il progetto non è configurato, utilizza il comando seguente per impostarlo:
gcloud config set project <YOUR_PROJECT_ID>

Consulta la documentazione per i comandi e l'utilizzo di gcloud.

Apri editor

  • Per questo codelab, useremo l'editor Cloud integrato. Nella finestra di Cloud Shell, fai clic sul pulsante Apri editor nell'angolo in alto a destra. Si aprirà un editor VSCode.

e5a5e95d543db556.png

Aggiungi estensione Ruby

  • Nel menu laterale a sinistra, fai clic sull'icona delle estensioni 999939b067e1d0dc.png, scrivi vscode ruby nella barra di ricerca e installa l'estensione Ruby VSCode.

a6fd4e37b3d847d2.png

3. Riscaldamento Gemini

Gli LLM non sono deterministici. Pertanto, mentre provi questi prompt, la risposta che ricevi potrebbe essere diversa da quella negli screenshot allegati nel codelab.

Chiediamo prima a Gemini cos'è un TDD. Per iniziare a conversare con Gemini nello stesso editor di Cloud Shell in cui ci troviamo, segui questi passaggi:

  • Sul lato sinistro della pagina, individua l'icona di Gemini 25fdcae4447d063c.png. Si aprirà la finestra della chat sul lato sinistro.
  • Puoi iniziare a digitare nella casella di testo Enter a prompt here

5e09b0fb6a1b44dd.png

Prompt:

What is Test Driven Development?

Risposta:

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

Questa presentazione offre una breve introduzione della tecnologia TDD e dei suoi vantaggi.

Ora chiediamo a Gemini cos'è Ruby:

Prompt:

What is Ruby?

Risposta:

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

Spiega cos'è Ruby e quali sono i vantaggi dell'utilizzo di Ruby come linguaggio.

4. Configurazione del progetto

Iniziamo creando una semplice app Sinatra.

  • Creiamo una cartella vuota. Puoi assegnargli il nome che preferisci. Lo chiameremo gemini-tdd per questo codelab. Nell'editor cloud a sinistra nella scheda Explorer, crea una cartella sotto /home/<YOUR-USERNAME>/

d1d920b074cd7c79.png

  • Apriamo la cartella che abbiamo appena creato. Nel menu all'estrema sinistra, fai clic sull'icona 1d080370a3ccad53.png e poi su File -> Apri cartella.
  • Creiamo un nuovo file Ruby in questa cartella principale che agirà da punto di partenza per l'app, puoi assegnargli il nome che preferisci. Lo chiameremo app.rb in questo codelab. 7beab8d21c59eee7.png
  • Aggiungiamo anche Gemfile nella cartella principale. Sarà utile chiedere a Gemini anche informazioni sull'Gemfile.
  • Verrà creato anche un file app_test.rb per scrivere gli scenari di test.

5. Implementazione basata su Gemini

Ora iniziamo fornendo a Gemini un po' di contesto su ciò che stiamo cercando di fare e chiedendogli di generare scenari di test per lo stesso. Copia il seguente prompt nel prompt della chat con Gemini.

Prompt:

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.

Risposta:

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

Fornisce uno scenario di test di esempio per l'app Calcolatrice, ovvero per l'aggiunta di due numeri. Ha anche importato la dipendenza minitest/autorun richiesta per i test. Copiamo i contenuti in app_test.rb. Proviamo a eseguire questo test ora; poiché non esiste alcun codice scritto, il test non funzionerà di sicuro.

Chiediamo a Gemini come eseguire questo test.

Prompt:

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

Risposta:

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.

Andiamo avanti ed eseguiamo il test. Fai clic con il tasto destro del mouse su app_test.rb nella scheda Explorer e fai clic su "Apri in terminale integrato"

66b4bb9598c1feca.png

Assicurati di essere nella stessa cartella del file app_test.rb. In caso contrario, utilizza il comando cd per accedervi. Nel terminale, esegui il comando restituito da Gemini:

ruby app_test.rb

Riscontrerai il seguente errore:

NameError: uninitialized constant Calculator

Chiediamo a Gemini come risolverlo direttamente dall'editor. Fai clic sull'icona della chat nel riquadro di navigazione dell'editor di Cloud Shell e chiedi:

Prompt:

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

Risposta:

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 ci comunica che non abbiamo una classe chiamata Calculator e che dobbiamo crearne una. Inoltre, ci ha fornito il codice per creare il corso Calculator. Andiamo avanti e usiamo questo codice. Apri app.rb dalla scheda Explorer e copia il codice fornito da Gemini al suo interno. Durante la modifica dei contenuti nell'app.rb, potresti ricevere alcuni suggerimenti da Gemini per il completamento automatico. devi premere tab se vuoi accettarlo o Esc in caso contrario.

Ora esegui di nuovo il test. Digita il seguente comando nel terminale integrato:

ruby app_test.rb

Tuttavia, continuerai a riscontrare lo stesso errore: "NameError: uninitialized constant Calculator". Chiediamo a Gemini come risolverlo.

6. TDD iterativo con Gemini

Prompt:

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

Risposta:

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

Ci ha fornito alcune risposte, potrebbe essere o meno uguale a quanto indicato sopra. Quindi diciamo esplicitamente a Gemini che la classe Calcolatrice è definita in app.rb .

Prompt:

Calculator class is defined in app.rb already.

Risposta:

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"

Abbiamo ricevuto la risposta da Gemini per importare l'app.rb in cui è definita la classe Calcolatrice. A volte potrebbero essere necessarie 2-3 iterazioni di prompt per ottenere la risposta giusta, ma man mano che impari, la risposta migliora. Tieni presente che in risposta a Gemini potresti anche visualizzare l'opzione Richiedi "./app". Lo aggiungiamo ad app.rb in app_test.rb ed eseguiamo di nuovo lo stesso test.

A questo punto, assicurati che il file app_test.rb abbia il seguente aspetto:

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

Esegui il comando seguente dal terminale Cloud Shell all'interno della cartella del progetto:

ruby app_test.rb

Se tutto funziona correttamente, il test dovrebbe essere superato. Abbiamo quindi sviluppato un'app Ruby molto semplice utilizzando l'approccio TDD e abbiamo aiutato Gemini. Le risposte ai prompt non saranno sempre le stesse e questo è per natura dei modelli LLM. Potresti ottenere più operazioni della Calcolatrice da Gemini, ma nel complesso la stessa procedura che abbiamo appena seguito dovrebbe funzionare.

7. Esegui il deployment dell'app in Cloud Functions

Ora chiediamo a Gemini di eseguire il deployment della funzione Cloud Functions:

Prompt:

Let's deploy this app to Cloud Functions

Risposta:

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 spiega come eseguirne il deployment manualmente utilizzando la UI di Cloud Functions. Ma non voglio farlo. Chiediamo a Gemini di darci il comando gcloud che posso eseguire direttamente dal terminale integrato.

Prompt:

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

Risposta:

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

Eseguiamo il comando gcloud fornito da Gemini nel terminale.

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

Riscontrerai il seguente errore:

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

Chiediamo aiuto a Gemini per correggere l'errore.

Prompt:

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

Risposta:

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

Eseguiamo bundle install nel terminale che creerà Gemfile.lock . Dopo aver eseguito il comando, controlla la scheda Explorer. Dovresti essere in grado di vedere l'Gemfile.lock.

Proviamo a eseguire di nuovo il deployment in Cloud Functions. Esegui lo stesso comando di deployment nel terminale:

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

Riscontrerai un altro errore:

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

Chiediamo a Gemini informazioni sull'errore:

Prompt:

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

Risposta:

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

Quindi, essenzialmente, nella nostra app manca la gemma Functions_framework. Aggiungiamo questa riga al nostro file Gemfile:

gem "functions_framework"

Ora esegui bundle install nel terminale. Potresti riscontrare o meno il messaggio di errore "Nessuna risorsa globale esplicita nel file Gem" di Google. In questo caso, assicurati di avere quanto segue come prima riga del file Gem:

source "https://rubygems.org"

Poi esegui di nuovo bundle install dal terminale. Ora eseguiamo di nuovo il comando deploy:

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

Ora riscontrerai il seguente errore:

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

Per risolvere il problema, proviamo la funzionalità Generate Code di Gemini. Apriamo app.rb dalla scheda Explorer, dove è già disponibile il codice dell'app Calcolatrice. In app.rb, nella prima riga, inizia a digitare FunctionsFramework , quindi digita ".". Vedrai alcuni suggerimenti in grigio :

9e17476a4a586433.png

Premi Tab per accettare il suggerimento. Una volta accettato, verranno visualizzati altri suggerimenti come quelli mostrati di seguito:

f3c35d1539789acc.png

Premi Tab per accettare ulteriori suggerimenti. Pertanto, il file app.rb dovrebbe avere l'aspetto seguente:

( Rinomina il nome della funzione da add ad 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

Abbiamo appena creato il punto di ingresso per l'app Cloud Functions e abbiamo anche imparato a usare il suggerimento di codice di Gemini nell'editor. Ora proviamo a eseguire nuovamente il deployment dell'app.

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

Se tutto funziona correttamente, l'implementazione dovrebbe andare a buon fine e dovresti essere in grado di vedere l'URL in cui è ospitata la tua app. Ora modifichiamo un po' il file app.rb per restituire il risultato dell'aggiunta. Il file app.rb finale dovrebbe avere il seguente aspetto:

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. Test end-to-end

Apri l'URL e trasmetti i parametri di query a e b come mostrato di seguito:

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

Dovresti riuscire a vedere la risposta come : "Result: 5". Il calcolatore esegue numerose operazioni. Puoi estendere questa app per eseguire anche queste e farti aiutare da Gemini.

10. Conclusione

Oggi abbiamo visto come sviluppare un'app Ruby usando l'approccio TDD con l'aiuto di Gemini. Come hai notato, Gemini potrebbe darti risultati diversi, ma può sicuramente aiutarti ad accelerare il processo di sviluppo in una lingua che potresti non conoscere meglio e continuare a mostrarti funzioni o snippet per accelerare la curva di apprendimento.

Qualsiasi sviluppatore ( indipendentemente dall'esperienza) può ricevere aiuto da Gemini per il processo di sviluppo. Se non per lo sviluppo, puoi usare Gemini per spiegare il codice esistente, quindi puoi chiedergli di generare test per il codice esistente, almeno per me è il lavoro più noioso 🙂

Buona programmazione con Gemini!