Codelab: Gemini per accelerare lo sviluppo basato sui test

1. Introduzione

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

Scoprirai anche come utilizzare Gemini come assistente alla programmazione. Gemini ti aiuterà ad accelerare il ciclo TDD generando casi di test, suggerendo implementazioni di codice e fornendo persino spiegazioni del codice.

Infine, vedrai come eseguire il deployment dell'app calcolatrice su Cloud Functions, la piattaforma serverless completamente gestita di Google, rendendo accessibile la tua app.

2. Prerequisiti

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

Creazione di un progetto

Abilitare 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 che viene precaricato con le lingue richieste installate. Nella console Cloud, fai clic su Attiva Cloud Shell nell'angolo in alto a destra:

6757b2fb50ddcc2d.png

  • Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è impostato sul tuo ID progetto. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list
  • Esegui questo comando in Cloud Shell per verificare che il comando gcloud conosca il tuo progetto:
gcloud config list project
  • Se il progetto non è impostato, utilizza il seguente comando 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, utilizzeremo l'editor Cloud integrato. Nella finestra di Cloud Shell, fai clic sul pulsante Apri editor nell'angolo in alto a destra. Verrà aperto un editor VSCode.

e5a5e95d543db556.png

Aggiungere l'estensione Ruby

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

a6fd4e37b3d847d2.png

3. Riscaldamento di Gemini

I LLM non sono deterministici. Pertanto, mentre provi questi prompt, la risposta che ricevi potrebbe essere diversa da quelle degli screenshot allegati al codelab.

Innanzitutto, chiediamo a Gemini che 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, che aprirà la finestra di chat sul lato sinistro.
  • Puoi iniziare a digitare nella casella di testo con la dicitura 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.
....

Fornisce una breve introduzione al TDD e ai suoi vantaggi.

Ora chiediamo a Gemini che 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 del suo utilizzo come linguaggio.

4. Configurazione del progetto

Ora iniziamo creando una semplice app Sinatra.

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

d1d920b074cd7c79.png

  • Apriamo la cartella appena creata. Nel menu all'estrema sinistra, fai clic sull'icona 1d080370a3ccad53.png, poi su File -> Apri cartella.
  • Creiamo un nuovo file Ruby in questa cartella principale che fungerà da punto di partenza per l'app. Puoi assegnargli il nome che preferisci. In questo codelab lo chiameremo app.rb. 7beab8d21c59eee7.png
  • Aggiungiamo anche un Gemfile nella cartella principale. Ti consigliamo di chiedere a Gemini anche informazioni su Gemfile.
  • Creeremo anche un file app_test.rb per scrivere i nostri scenari di test.

5. Implementazione basata su Gemini

Ora iniziamo fornendo a Gemini un contesto su ciò che stiamo cercando di fare e chiedendogli di generare casi di test per lo stesso. Copia il seguente prompt nel prompt della chat di 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, ad esempio per l'addizione di due numeri. Ha anche importato la dipendenza richiesta minitest/autorun per i test. Copiamo i contenuti in app_test.rb. Proviamo a eseguire questo test ora. Poiché non abbiamo scritto alcun codice, sicuramente non andrà a buon fine.

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.

Quindi, eseguiamo il test. Fai clic con il tasto destro del mouse su app_test.rb nella scheda Explorer e fai clic su "Open in Integrated Terminal" (Apri nel terminale integrato).

66b4bb9598c1feca.png

Assicurati di trovarti 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

Si verifica il seguente errore:

NameError: uninitialized constant Calculator

Chiediamo a Gemini come risolvere il problema direttamente dall'editor. Fai clic sull'icona della chat nel riquadro di navigazione dell'editor Cloud Shell e poni la seguente domanda:

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 dice che non abbiamo un corso chiamato Calculator e che dobbiamo crearne uno. Ci ha anche fornito il codice per creare la classe Calculator. Utilizziamo questo codice. Apri app.rb dalla scheda Esplora e copia il codice fornito da Gemini. Mentre modifichi i contenuti in app.rb, potresti ricevere alcuni suggerimenti da Gemini come completamento automatico; devi premere tab se vuoi accettarli o Esc in caso contrario.

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

ruby app_test.rb

Tuttavia, continuerai a visualizzare 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 dato una risposta, che potrebbe essere uguale o diversa da quella sopra. Quindi, diciamo esplicitamente a Gemini che abbiamo definito la classe Calculator 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 app.rb in cui è definita la classe Calculator. A volte potrebbero essere necessarie 2-3 iterazioni di prompt per ottenere la risposta giusta, ma man mano che acquisisci familiarità con lo strumento, i risultati miglioreranno. Tieni presente che potresti anche visualizzare require "./app" nella risposta di Gemini. Aggiungiamo questo all'app.rb in app_test.rb ed eseguiamo di nuovo lo stesso test.

Assicurati che a questo punto 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 riportato di seguito dal terminale Cloud Shell all'interno della cartella del progetto:

ruby app_test.rb

Se tutto va bene, il test dovrebbe essere superato. Abbiamo quindi sviluppato un'app Ruby molto semplice utilizzando l'approccio TDD e abbiamo chiesto aiuto a Gemini. Le risposte ai prompt non saranno sempre le stesse, per via della natura dei modelli LLM. Potresti ottenere più operazioni della calcolatrice da Gemini, ma in generale 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 in 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

Viene visualizzato 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 visualizzare Gemfile.lock.

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

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

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

In sostanza, nella nostra app manca la gemma functions_framework. Aggiungiamo questa riga nel nostro Gemfile:

gem "functions_framework"

Ora esegui bundle install nel terminale. Potresti visualizzare o meno un errore che indica "Nessuna risorsa globale esplicita in Gemfile" . Se si verifica questo problema, assicurati che la prima riga del Gemfile sia la seguente:

source "https://rubygems.org"

Quindi, esegui di nuovo bundle install dal terminale. Ora esegui di nuovo il comando di deployment:

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

Ora visualizzerai 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 abbiamo già il codice dell'app Calcolatrice. In app.rb, nella prima riga, inizia a digitare FunctionsFramework e poi digita ".". Vedrai alcuni suggerimenti in testo grigio :

9e17476a4a586433.png

Premi Tab per accettare il suggerimento. Una volta accettata, vedrai altri suggerimenti come mostrato di seguito:

f3c35d1539789acc.png

Premi Tab per accettare altri suggerimenti. Pertanto, il file app.rb dovrebbe essere simile al 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 utilizzare il suggerimento di codice di Gemini nell'editor. Ora prova a eseguire di nuovo il deployment dell'app.

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

Se tutto va bene, il deployment dovrebbe essere completato e dovresti essere in grado di vedere l'URL in cui è ospitata la tua app. Bene, modifichiamo un po' il file app.rb per restituire il risultato dell'addizione. 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 visualizzare la risposta come : "Result: 5". Una calcolatrice può fare molte operazioni. Puoi estendere questa app per eseguire anche queste operazioni e ricevere l'aiuto di Gemini.

10. Conclusione

Oggi abbiamo visto come sviluppare un'app Ruby utilizzando l'approccio TDD con l'aiuto di Gemini. Come avrai notato, Gemini potrebbe darti risultati diversi, ma può sicuramente aiutarti ad accelerare il processo di sviluppo in una lingua che non conosci molto bene e mostrarti comunque funzioni o snippet per velocizzare la curva di apprendimento.

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

Buona programmazione con Gemini.