Potenzia il tuo flusso di lavoro di sviluppo con Gemini Code Assist

1. Introduzione

e5b98fd4e417c877.png

In questo codelab, scoprirai come Gemini Code Assist può supportarti in tutte le fasi chiave del ciclo di vita dello sviluppo del software (SDLC), come progettazione, build, test e deployment. Progetteremo e svilupperemo un'intera applicazione e ne eseguiremo il deployment su Google Cloud.

Creeremo un'API e un'applicazione per la ricerca tra le sessioni di un evento tecnico. Ogni sessione avrà titolo, riepilogo, durata, categorie e uno o più relatori.

Attività previste

  • Progetta, crea, testa ed esegui il deployment di un'applicazione web in base a una specifica OpenAPI da zero

Cosa imparerai a fare

  • Come utilizzare Gemini Code Assist per generare una specifica OpenAPI
  • Come utilizzare le funzionalità di generazione del codice di Gemini Code Assist per sviluppare un'applicazione Python Flask per la specifica OpenAPI
  • Come utilizzare Gemini Code Assist per generare un front-end web per l'applicazione Python Flask
  • Come utilizzare Gemini Code Assist per ricevere assistenza su come eseguire il deployment dell'applicazione in Google Cloud Run
  • Usa le funzionalità di Gemini Code Assist come la spiegazione del codice e la generazione degli scenari di test durante la creazione e il test dell'applicazione

Che cosa ti serve

  • Browser web Chrome
  • Un account Gmail.
  • Un progetto Cloud con fatturazione abilitata
  • Gemini Code Assist abilitato per il tuo progetto Cloud

Questo lab è rivolto a sviluppatori di tutti i livelli, inclusi i principianti. Anche se l'applicazione di esempio è in linguaggio Python, non è necessario avere familiarità con la programmazione Python per capire cosa sta succedendo. Il nostro obiettivo sarà familiarizzare con le funzionalità di Gemini Code Assist.

2. Configura Gemini Code Assist

Questa sezione illustra tutto ciò che devi fare per iniziare a utilizzare questo lab.

Abilita Gemini Code Assist nell'IDE di Cloud Shell

Per il resto del codelab, utilizzeremo l'IDE di Cloud Shell, un ambiente di sviluppo completamente gestito basato su Code OSS. Dobbiamo abilitare e configurare Code Assist nell'IDE di Cloud Shell, seguendo i passaggi riportati di seguito:

  1. Visita il sito ide.cloud.google.com. La visualizzazione dell'IDE potrebbe richiedere un po' di tempo, quindi sii paziente e accetta le scelte predefinite per la configurazione. Se vedi delle istruzioni sulla configurazione dell'IDE, completale con le impostazioni predefinite.
  2. Fai clic sul pulsante Cloud Code - Accedi nella barra di stato in basso come mostrato. Autorizza il plug-in come da istruzioni. Se nella barra di stato vedi il messaggio "Cloud Code - no project" (Cloud Code - nessun progetto), selezionalo e scegli il progetto Google Cloud specifico dall'elenco dei progetti con cui prevedi di lavorare.

6f5ce865fc7a3ef5.png

  1. Fai clic sul pulsante Code Assist nell'angolo in basso a destra, come mostrato, e seleziona un'ultima volta il progetto Google Cloud corretto. Se ti viene chiesto di abilitare l'API Cloud AI Companion, fallo e vai avanti.
  2. Dopo aver selezionato il progetto Google Cloud, assicurati di poterlo vedere nel messaggio di stato di Cloud Code nella barra di stato e di avere attivato Code Assist sulla destra, nella barra di stato, come mostrato di seguito:

709e6c8248ac7d88.png

Gemini Code Assist è pronto per l'uso.

3. Configura Firestore

Cloud Firestore è un database di documenti serverless completamente gestito che utilizzeremo come backend per i dati delle nostre applicazioni. I dati in Cloud Firestore sono strutturati in raccolte di documenti.

Dobbiamo creare una raccolta denominata sessions nel nostro database Firestore predefinito. Questa raccolta conterrà dati di esempio (documenti) che utilizzeremo nella nostra applicazione.

Apri il terminale dall'interno dell'IDE di Cloud Shell tramite il menu principale, come mostrato di seguito:

f1535e14c9beeec6.png

Dobbiamo creare una raccolta denominata sessions. Verrà visualizzato un elenco di documenti di sessione di esempio. Ogni documento avrà i seguenti attributi:

  1. title: stringa
  2. categories: array di stringhe
  3. speakers: array di stringhe
  4. duration: stringa
  5. summary: stringa

Completa questa raccolta con dati di esempio copiando un file che li contiene in un bucket del tuo progetto, da cui potrai poi importare la raccolta tramite il comando gcloud firestore import.

Inizializzazione del database Firestore

Visita la pagina di Firestore nella console Cloud.

Se non hai mai inizializzato un database Firestore nel progetto, crea il database default. Durante la creazione del database, segui questi valori:

  • Modalità Firestore: Native
  • Località: scegli Region come tipo di località e seleziona la regione appropriata per la tua applicazione. Prendi nota di questa località perché ti servirà nel passaggio successivo per la località del bucket.
  • Crea il database.

504cabdb99a222a5.png

Ora creeremo la raccolta sessions seguendo i passaggi indicati di seguito:

  1. Crea un bucket nel tuo progetto con il comando gsutil riportato di seguito. Sostituisci la variabile <PROJECT_ID> nel comando seguente con il tuo ID progetto Google Cloud. Sostituisci <BUCKET_LOCATION> con il nome di una regione corrispondente all'area geografica del tuo database Firestore predefinito (come indicato nel passaggio precedente), che potrebbe essere US-WEST1, EUROPE-WEST1, ASIA-EAST1 :
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
  1. Ora che il bucket è stato creato, dobbiamo copiare l'esportazione del database che abbiamo preparato in questo bucket, prima di poterlo importare nel database Firebase. Utilizza il comando riportato di seguito:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256  gs://<PROJECT_ID>-my-bucket

Ora che abbiamo i dati da importare, possiamo andare al passaggio finale che prevede l'importazione dei dati nel database Firebase (default) che abbiamo creato.

  1. Utilizza il comando gcloud riportato di seguito:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256

L'importazione richiederà alcuni secondi e, una volta pronta, potrai convalidare il database Firestore e la raccolta visitando la pagina https://console.cloud.google.com/firestore/databases, selezionare il database default e la raccolta sessions come mostrato di seguito:

d3e294d46ba29cd5.png

La creazione della raccolta Firestore che utilizzeremo nella nostra applicazione è terminata.

4. Crea il modello di applicazione

Creeremo un'applicazione di esempio (un'applicazione Python Flask) che utilizzeremo nel resto del codelab. Questa applicazione eseguirà una ricerca tra le sessioni offerte nel corso di una conferenza tecnica.

Segui questi passaggi:

  1. Fai clic sul nome del progetto Google Cloud nella barra di stato in basso.

f151759c156c124e.png

  1. Viene visualizzato un elenco di opzioni. Fai clic su New Application (Nuova applicazione) dall'elenco seguente.

91ea9836f38b7f74.png

  1. Seleziona Applicazione Cloud Run (questo sarà il runtime della nostra app).
  2. Seleziona il modello di applicazione Python (Flask): Cloud Run.
  3. Assegna un nome all'applicazione e salvala nella posizione che preferisci.
  4. Una notifica conferma la creazione dell'applicazione; si apre una nuova finestra con l'applicazione caricata, come mostrato di seguito. Viene aperto un file README.md. Per ora puoi chiudere la visualizzazione.

aaa3725b17ce27cf.png

5. Interazione con Gemini Code Assist

In questo lab utilizzeremo la chat di Gemini Code Assist disponibile all'interno dell'IDE di Cloud Shell come parte dell'estensione Cloud Code in VS Code. Per visualizzarla, fai clic sul pulsante Code Assist nella barra di navigazione a sinistra. Cerca l'icona di Assistente codice a489f98a34898727.pngnella barra degli strumenti di navigazione a sinistra e fai clic sopra.

Verrà visualizzato il riquadro della chat di Code Assist all'interno dell'IDE di Cloud Shell e potrai chattare con Code Assist.

14ad103efaa0ddaa.png

Nota l'icona del cestino in alto: in questo modo puoi reimpostare il contesto della cronologia chat di Code Assist. Inoltre, tieni presente che questa interazione via chat è contestuale ai file su cui stai lavorando nell'IDE.

6. Progettazione delle API

Il nostro primo passo sarà usare l'assistenza di Gemini Code Assist durante la fase di progettazione. In questo passaggio, genereremo una specifica OpenAPI per le entità (sessioni tecniche in un evento) in cui eseguire la ricerca.

Fornisci il seguente prompt:

Generate an Open API spec that will allow me to retrieve all sessions, sessions by category, session by id. Each session has the following attributes: id, title, list of speakers, list of categories, summary and duration.

Questo dovrebbe generare una specifica OpenAPI per la ricerca tra sessioni tramite vari parametri di query. Di seguito è riportato un esempio di specifica:

openapi: 3.0.0
info:
 title: Sessions API
 description: This API allows you to retrieve all sessions, sessions by category, and session by id.
 version: 1.0.0
servers:
 - url: https://sessions.example.com
paths:
 /sessions:
   get:
     summary: Get all sessions
     operationId: getSessions
     responses:
       '200':
         description: OK
         content:
           application/json:
             schema:
               type: array
               items:
                 $ref: '#/components/schemas/Session'
 /sessions/{id}:
   get:
     summary: Get session by id
     operationId: getSessionById
     parameters:
       - name: id
         in: path
         required: true
         description: The id of the session
         schema:
           type: string
     responses:
       '200':
         description: OK
         content:
           application/json:
             schema:
               $ref: '#/components/schemas/Session'
 /sessions/categories/{category}:
   get:
     summary: Get sessions by category
     operationId: getSessionsByCategory
     parameters:
       - name: category
         in: path
         required: true
         description: The category of the sessions
         schema:
           type: string
     responses:
       '200':
         description: OK
         content:
           application/json:
             schema:
               type: array
               items:
                 $ref: '#/components/schemas/Session'
components:
 schemas:
   Session:
     type: object
     properties:
       id:
         type: string
         description: The id of the session
       title:
         type: string
         description: The title of the session
       speakers:
         type: array
         items:
           type: string
         description: The list of speakers for the session
       categories:
         type: array
         items:
           type: string
         description: The list of categories for the session
       summary:
         type: string
         description: The summary of the session
       duration:
         type: string
         description: The duration of the session

Puoi notare che la specifica presenta quanto segue:

  • Uno schema definito per il Tipo di sessione.
  • Sono stati definiti diversi percorsi API:
  • /sessions
  • /sessions/{id}
  • /sessions/categories/{category}

Crea un file denominato sessionsapi.yaml nella cartella principale, copia i contenuti dalla finestra della chat di Code Assist utilizzando l'opzione "Inserisci nel file attuale" (il pulsante +) e tieni il file aperto nell'IDE di Cloud Shell.

A questo punto, puoi notare una funzionalità interessante di Gemini Code Assist: la citazione. Queste informazioni vengono mostrate allo sviluppatore quando il codice generato cita direttamente per esteso un'altra sorgente, ad esempio il codice open source esistente. Offre l'origine e la licenza allo sviluppatore per decidere cosa farne.

Supponendo che i contenuti generati vadano bene, possiamo usare questo documento di specifica per generare un'applicazione Python Flask apposita.

7. genera l'applicazione

Ora chiederemo a Code Assist di generare l'applicazione. Fornisci il seguente prompt con il file sessionsapi.yaml aperto.

Generate a Python Application using the Flask framework, based on the sessionsapi.yaml file. This application uses a local in memory list of sessions. Do not use any Flask extensions.

Questo dovrebbe fornirti uno scheletro per l'applicazione Python Flask basata sulle funzionalità e sui percorsi specificati nel file delle specifiche OpenAPI.

Il codice dell'applicazione Python Flask fornito dovrebbe essere simile al seguente:

from flask import Flask, jsonify, request

app = Flask(__name__)

sessions = [
    {
        "id": "1",
        "title": "Session 1",
        "speakers": ["Speaker 1", "Speaker 2"],
        "categories": ["Category 1", "Category 2"],
        "summary": "This is a summary of session 1.",
        "duration": "1 hour",
    },
    {
        "id": "2",
        "title": "Session 2",
        "speakers": ["Speaker 3", "Speaker 4"],
        "categories": ["Category 3", "Category 4"],
        "summary": "This is a summary of session 2.",
        "duration": "1 hour 30 minutes",
    },
]

@app.route('/sessions', methods=['GET'])
def get_sessions():
    return jsonify(sessions)

@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
    session = next((session for session in sessions if session['id'] == id), None)
    if session is None:
        return jsonify({}), 404
    return jsonify(session)

@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
    sessions_by_category = [session for session in sessions if category in session['categories']]
    return jsonify(sessions_by_category)

if __name__ == '__main__':
    app.run()

Esiste già un file app.py generato nell'ambito del passaggio precedente. È sufficiente sostituirne i contenuti con il codice generato da Code Assist e salvare il file.

Vorremmo cambiare la riga app.run() in modo che utilizzi la porta 8080, l'indirizzo host 0.0.0.0 e anche l'esecuzione in modalità di debug durante l'esecuzione locale.Ecco un modo per farlo. Per prima cosa, evidenzia/seleziona la riga:

app.run()

Quindi, nell'interfaccia di Code Assist Chat, digita la richiesta: Explain this.

Dovrebbe essere visualizzata una spiegazione dettagliata di quella particolare riga, il cui esempio è riportato di seguito:

58ec896a32a4fb68.png

A questo punto, utilizza questo prompt:

update the code to run the application on port 8080, host address 0.0.0.0, and in debug mode

Il codice suggerito generato dovrebbe essere il seguente:

app.run(host='0.0.0.0', port=8080, debug=True)

Ricorda di aggiornare il file app.py con questo snippet.

Esegui l'applicazione in locale

Ora eseguiamo l'applicazione localmente per convalidare i requisiti dell'applicazione in base a ciò con cui abbiamo iniziato.

Il primo passaggio prevede la creazione di un ambiente Python virtuale con le dipendenze del pacchetto Python nel file requirements.txt, da installare nell'ambiente virtuale. Per farlo, vai alla tavolozza dei comandi (Ctrl+Maiusc+P) nell'IDE di Cloud Shell e digita in Crea ambiente Python. Segui i passaggi successivi per selezionare un ambiente virtuale (venv), un interprete Python 3.x e il file requirements.txt.

Una volta creato l'ambiente, apri una nuova finestra del terminale (Ctrl+Maiusc+`) e dai il seguente comando:

python app.py

Di seguito è riportato un esempio di esecuzione:

(.venv) romin@cloudshell: $ python app.py 
 * Serving Flask app 'app'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:8080
 * Running on http://10.88.0.3:8080
Press CTRL+C to quit
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 132-247-368

Ora puoi visualizzare in anteprima l'API ai seguenti URL. Supponendo che il tuo server di sviluppo sia in esecuzione sulla porta 8080. In caso contrario, modificalo con il numero di porta appropriato.

  • https://<host-name>:8080/sessions
  • https://<host-name>:8080/sessions/{id}
  • https://<host-name>:8080/sessions/categories/{category}

Segui i passaggi indicati di seguito per assicurarti di poter recuperare utilizzando questi URL, i dati JSON contenuti nel file app.py:

Apri una nuova finestra del terminale e prova uno dei seguenti comandi:

curl -X GET http://127.0.0.1:8080/sessions
curl -X GET http://127.0.0.1:8080/sessions/<ID>
curl -X GET http://127.0.0.1:8080/sessions/categories/<CATEGORY_NAME> 

8. Refactoring del codice

Anziché fare in modo che app.py contenga i dati JSON di esempio hardcoded, probabilmente vorremmo separarli/estrarli in un altro modulo, in modo da mantenere una netta separazione tra il codice e i dati. Procediamo.

Tieni aperto il file app.py e fornisci il seguente prompt:

Can I improve this code and separate out the sessions data from this app.py file?

Dovresti ricevere alcuni suggerimenti su come farlo. Di seguito è riportato un esempio di suggerimento che abbiamo ricevuto e che dovresti ricevere:

9b9c56cb527dac4c.png

Seguiamolo e separiamo i nostri dati in un file sessions.py come suggerito da Code Assist.

Crea un nuovo file denominato sessions.py

, il cui contenuto è l'elenco JSON, in base ai nostri dati generati di seguito:

sessions = [
   {
       "id": "1",
       "title": "Session 1",
       "speakers": ["Speaker 1", "Speaker 2"],
       "categories": ["Category 1", "Category 2"],
       "summary": "This is a summary of session 1.",
       "duration": "1 hour",
   },
   {
       "id": "2",
       "title": "Session 2",
       "speakers": ["Speaker 3", "Speaker 4"],
       "categories": ["Category 3", "Category 4"],
       "summary": "This is a summary of session 2.",
       "duration": "1 hour 30 minutes",
   },
]

Il file app.py ora è molto semplificato ed è mostrato di seguito:

from flask import Flask, jsonify, request
from sessions import sessions

app = Flask(__name__)

@app.route('/sessions', methods=['GET'])
def get_sessions():
   return jsonify(sessions.sessions)

@app.route('/sessions/<id>', methods=['GET'])
def get_session_by_id(id):
   session = next((session for session in sessions.sessions if session['id'] == id), None)
   if session is None:
       return jsonify({}), 404
   return jsonify(session)

@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
   sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
   return jsonify(sessions_by_category)

if __name__ == '__main__':
   app.run(host='0.0.0.0', port=8080, debug=True)

Assicurati di poter ancora eseguire l'applicazione in locale ed esercitarti con l'API con queste modifiche sottoposte a refactoring. È probabile che il server di sviluppo Python sia ancora in esecuzione, quindi devi solo richiamare i comandi curl del passaggio precedente.

9. Esegui l'integrazione con la raccolta Firestore

Il passaggio successivo consiste nell'abbandonare l'elenco JSON in memoria locale che abbiamo per le nostre sessioni e connettere la nostra applicazione alla raccolta sessions nel database Firestore, che abbiamo creato all'inizio di questo codelab.

Tieni aperto il file sessions.py e fornisci il seguente prompt:

Can you further refactor the sessions.py code to read from a Firestore database that has a collection named sessions. The collection has the same attributes as the session object that we have defined. Use the Python module google-cloud-firestore. 

Abbiamo ricevuto il seguente suggerimento per leggere tutte le sessioni dalla raccolta Firestore:

import google.cloud.firestore

# Create a Firestore client
db = google.cloud.firestore.Client()

# Get the sessions collection
sessions_collection = db.collection("sessions")

# Create a list of sessions
sessions = []

# Iterate over the documents and add them to the list
for doc in sessions_collection.stream():
   session = doc.to_dict()
   session["id"] = doc.id
   sessions.append(session)

Procedi e incorpora il codice in sessions.py.

Se il server di sviluppo Flask è in esecuzione in locale, l'applicazione potrebbe essere stata chiusa lamentando che il modulo Python non è stato trovato.

Ad esempio, puoi chiedere a Code Assist informazioni su quale modulo Python deve essere aggiunto al file requirements.txt, come segue:

Which Python package needs to be installed to make the firestore code work?

In questo modo ti verrà fornito il nome del modulo Python (ad es. google-cloud-firestore). Aggiungilo al file requirements.txt.

Dovrai ricreare l'ambiente Python con il modulo appena aggiunto (google-cloud-firestore). Per farlo, fornisci il seguente comando nella finestra Terminale esistente:

pip install -r requirements.txt

Esegui di nuovo l'applicazione (riavviala con python app.py) e visita l'URL di /sessions. Ora dovresti visualizzare i documenti di esempio che abbiamo aggiunto alla raccolta sessions.

975d05e6518f1a6a.png

Non esitare a eseguire query su altri URI per recuperare sessioni specifiche o tutte le sessioni per una determinata categoria, come descritto nei passaggi precedenti.

10. Spiegazione del codice

Questo è un buon momento per utilizzare la funzionalità "Explain this" di Gemini Code Assist per comprendere meglio il codice. Puoi accedere a uno qualsiasi dei file o selezionare snippet di codice specifici e chiedere a Code Assist come segue: Explain this.

Come esercizio, visita il file sessions.py, evidenzia il codice specifico di Firestore e ottieni una spiegazione del codice in merito. Prova a utilizzare questa funzionalità anche su altri file del tuo progetto, non solo nel codice Python.

11. Genera l'applicazione web

Ora che abbiamo generato l'API e l'abbiamo integrata con una raccolta Firestore attiva, generiamo un front-end basato sul web per l'applicazione. Il nostro front-end web al momento manterrà al minimo la sua funzionalità, vale a dire sarà in grado di cercare sessioni che appartengono a una categoria specifica. Tieni presente che abbiamo un percorso API per questo, ad esempio /sessions/categories/{category}, quindi la nostra applicazione web dovrebbe richiamarlo e recuperare i risultati.

Approfondiamo l'argomento. Invia il seguente prompt a Code Assist:

Generate a web application that allows me to search for sessions by category and uses the Flask application that we created. Please use basic HTML, CSS and JS. Embed all the Javascript and CSS code into a single HTML file only.

Verrà generato il codice HTML dell'applicazione web con JavaScript e CSS incorporati. Verrà inoltre richiesto di aggiungere un nuovo percorso al file app.py, in modo che a qualsiasi utente che visita l'URL principale o di base venga mostrata la home page. Se non menziona tali informazioni, chiedi informazioni o utilizza lo snippet fornito di seguito:

@app.route('/')
def index():
   return render_template('index.html')

Puoi salvarlo come index.html, ma potresti avere una domanda su dove salvare il file (ad esempio, quale cartella?). Possiamo fare una domanda aggiuntiva a Code Assist.

Given that I am using the flask framework, where should I put the index.html file?

Dovrebbe indicare chiaramente che utilizza il framework render_template, pertanto il file index.html dovrà essere inserito nella cartella templates. Troverai questa cartella disponibile perché all'inizio di questo codelab abbiamo generato un'applicazione basata su un modello Flask. Di conseguenza, esiste già un file index.html e dovresti semplicemente sostituirne i contenuti con quello nuovo che è stato generato qui. Code Assist menziona anche di importare render_template nel file app.py.

Salva il codice dell'applicazione web nel file index.html e ricorda di inserirlo nella cartella templates.

Esegui l'applicazione in locale

Ora eseguiamo l'applicazione localmente per convalidare i requisiti dell'applicazione in base a ciò con cui abbiamo iniziato.

Assicurati che il server Flask locale sia ancora in esecuzione e che non mostri errori. In caso di errori, risolvili e avvia il server.

Una volta avviata la configurazione, visita l'URL della home page dell'applicazione. Dovrebbe essere visualizzato il file index.html pubblicato come mostrato di seguito:

8ca586acc4536879.png

Fornisci una delle categorie dei dati come input (ad es. AI) e fai clic sul pulsante Search. Dovrebbero essere visualizzate le sessioni codificate con la categoria AI.

165faded790a6c.png

Un esercizio facoltativo consiste nel mostrare metadati aggiuntivi come durata, categorie, relatori e riepilogo per ciascuna sessione.

12. Generazione dello scenario di test

Abbiamo generato l'API Sessioni ed è il momento di usare Gemini Code Assist ora per generare scenari di test delle unità per i diversi percorsi delle API.

Tieni aperto il file app.py e fornisci il seguente prompt:

Generate unit test cases for app routes. Use unittest module.

Abbiamo ricevuto la seguente risposta:

import unittest
from app import app

class FlaskAppTestCase(unittest.TestCase):

    def test_index(self):
        tester = app.test_client()
        response = tester.get('/')
        self.assertEqual(response.status_code, 200)

    def test_get_sessions(self):
        tester = app.test_client()
        response = tester.get('/sessions')
        self.assertEqual(response.status_code, 200)

    def test_get_session_by_id(self):
        tester = app.test_client()
        response = tester.get('/sessions/1')
        self.assertEqual(response.status_code, 200)

    def test_get_sessions_by_category(self):
        tester = app.test_client()
        response = tester.get('/sessions/categories/category1')
        self.assertEqual(response.status_code, 200)

if __name__ == '__main__':
    unittest.main()

Crea un file denominato tests.py con il codice riportato sopra.

Nota sulla generazione degli scenari di test

Potresti vedere un elenco di codice diverso da quello precedente e questo potrebbe causare alcuni problemi nell'esecuzione degli scenari di test. Ad esempio, abbiamo notato che in alcune delle nostre esecuzioni sono stati persi i seguenti elementi chiave di codice:

from app import app

Il codice riportato sopra è necessario per importare l'app Flask esistente in base alla quale richiameremo gli scenari di test.

if __name__ == '__main__':

`unittest.main()`

Il codice riportato sopra è necessario per eseguire gli scenari di test.

Il nostro consiglio è di esaminare ciascuno degli scenari di test, controllare assertEqual e altre condizioni nel codice generato per assicurarti che funzioni. Poiché i dati sono esterni nella raccolta Firestore, potrebbero non avere accesso e potrebbero utilizzare alcuni dati fittizi, a seguito dei quali i test potrebbero non riuscire. Modifica gli scenari di test di conseguenza o commenta alcuni di quelli di cui potresti non aver bisogno immediatamente.

Come dimostrazione, abbiamo eseguito gli scenari di test utilizzando il seguente comando (assicurati di eseguire il server di sviluppo locale poiché le chiamate verranno effettuate agli endpoint API locali):

python tests.py

Abbiamo ottenuto il seguente risultato di riepilogo:

Ran 4 tests in 0.274s

FAILED (failures=2)

è corretto poiché l'ID sessione non era corretto nel terzo test e non esiste alcuna categoria denominata category1

.

Quindi modifica gli scenari di test di conseguenza e testali.

13. Sviluppo basato sui test

Ora vediamo come aggiungere un nuovo metodo di ricerca nell'API delle sessioni seguendo la metodologia dello sviluppo guidato dal test (TDD), che consiste nel scrivere per primi gli scenari di test, farli non riuscire a causa della mancanza di implementazione e utilizzare Gemini Code Assist per generare l'implementazione mancante in modo che il test superi il test.

Vai al file test.py (supponendo che tu abbia corretto il file tests.py in modo da avere tutti i test superati). Chiedi a Code Assist il seguente prompt:

Generate a new test case to search for sessions by speaker

In questo modo abbiamo ottenuto la seguente implementazione dello scenario di test, che abbiamo debitamente inserito nel file tests.py.

  def test_get_sessions_by_speaker(self):
        tester = app.test_client()
        response = tester.get('/sessions/speakers/speaker1')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.json, [sessions.sessions[0], sessions.sessions[1]])

Se esegui i test, dovresti visualizzare il seguente errore:

$ python tests.py 
.F.
======================================================================
FAIL: test_get_sessions_by_speaker (__main__.FlaskAppTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/romin/hello-world-5/tests.py", line 21, in test_get_sessions_by_speaker
    self.assertEqual(response.status_code, 200)
AssertionError: 404 != 200

----------------------------------------------------------------------
Ran 3 tests in 0.010s

FAILED (failures=1)

Il motivo è che lo scenario di test ha richiamato il seguente percorso (/sessions/speakers/) e non è presente alcuna implementazione di questo percorso in app.py.

Chiediamo a Code Assist di fornirci un'implementazione. Vai al file app.py e fornisci il seguente prompt a Code Assist:

Add a new route to search for sessions by a specific speaker

Abbiamo ricevuto la seguente implementazione suggerita da Code Assist, che è stata aggiunta al file app.py:

@app.route('/sessions/speakers/<speaker>', methods=['GET'])
def get_sessions_by_speaker(speaker):
    sessions_by_speaker = [session for session in sessions.sessions if speaker in session['speakers']]
    return jsonify(sessions_by_speaker)

Per un rapido controllo, abbiamo esaminato nuovamente il file tests.py e abbiamo modificato il nostro scenario di test come segue:

   def test_get_sessions_by_speaker(self):
       tester = app.test_client()
       response = tester.get('/sessions/speakers/Romin Irani')
       self.assertEqual(response.status_code, 200)
       self.assertEqual(len(response.json), 1)

Il test è andato a buon fine. Lasciamolo come esercizio per esaminare gli scenari di test generati, modificarli un po' a seconda dei dati che potresti avere in Firestore e avere i metodi assert* appropriati negli scenari di test dell'unità Python.

14. Deployment in Google Cloud Run

Ora che siamo consapevoli della qualità del nostro sviluppo, il nostro passaggio finale sarà eseguire il deployment di questa applicazione in Google Cloud Run. Ma forse, per delle buone misure, dovremmo chiedere a Code Assist se abbiamo dimenticato qualcosa. Con app.py aperto, invia il seguente prompt :

Is there something here I should change before I deploy to production?

Per fortuna ci hai chiesto perché abbiamo dimenticato di impostare il flag di debug su off :

2f87ed3a811fb218.png

Come indicato, disattiva il debug e chiedi a Gemini Code Assist di aiutarti con il comando gcloud, che può essere utilizzato per eseguire il deployment dell'applicazione in Cloud Run direttamente dal codice sorgente (senza dover prima creare un container).

Fornisci il seguente prompt:

I would like to deploy the application to Cloud Run directly from source. What is the gcloud command to do that?

Prova alcune varianti della richiesta precedente. Un altro esempio che abbiamo provato è stato:

I would like to deploy this application to Cloud Run. I don't want to build a container image locally but deploy directly from source to Cloud Run. What is the gcloud command for that?

Possibilmente, dovresti visualizzare il seguente comando gcloud:

gcloud run deploy sessions --source .

Potresti anche ricevere:

gcloud run deploy <service-name> --source . \
—-platform managed \
—-allow-unauthenticated

Esegui il comando riportato sopra dalla cartella principale dell'applicazione. Quando ti viene chiesto region, seleziona us-central1 e quando ti viene chiesto di consentire unauthenticated invocations, scegli Y. Ti potrebbe essere chiesto di abilitare le API Google Cloud come Artifact Registry, Cloud Build e Cloud Run e di disporre dell'autorizzazione per creare un repository Artifact Registry. Procedi e concedi l'autorizzazione.

Il completamento del processo di deployment richiederà circa 2 minuti, quindi ti chiediamo di avere pazienza.

Una volta eseguito il deployment, visualizzerai l'URL del servizio Cloud Run. Visita l'URL pubblico. Dovresti vedere la stessa applicazione web di cui è stato eseguito il deployment e che è in esecuzione.

c5322d0fd3e0f616.png

Congratulazioni, ben fatto!

15. (Facoltativo) Usa Cloud Logging

Possiamo introdurre il logging nella nostra applicazione in modo che i log dell'applicazione siano centralizzati in uno dei servizi Google Cloud (Cloud Logging). Possiamo quindi utilizzare la funzionalità Observability Gemini per comprendere anche le voci di log.

Per farlo, dovremo prima utilizzare una libreria Python Cloud Logging esistente di Google Cloud e utilizzarla per il logging di messaggi informativi, di avviso o di errore (a seconda del livello di log o di gravità).

Proviamo a chiedere prima a Code Assist. Prova il seguente prompt:

How do I use the google-cloud-logging package in Python?

Dovresti ricevere una risposta che fornisce alcune informazioni in merito, come indicato di seguito:

2472e1ccaf8a217d.png

Aggiungiamo istruzioni di logging alla funzione che cerca le sessioni per categoria.

Per prima cosa, aggiungi il pacchetto Python google-cloud-logging al file requirements.txt.

Di seguito è riportato uno snippet di codice che mostra come abbiamo integrato il codice per implementare il logging:

...
from google.cloud import logging
...
app = Flask(__name__)

# Create a logger
logger = logging.Client().logger('my-log')

@app.route('/sessions/categories/<category>', methods=['GET'])
def get_sessions_by_category(category):
   logger.log_text(f"Fetching sessions with category {category}")
   sessions_by_category = [session for session in sessions.sessions if category in session['categories']]
   logger.log_text(f'Found {len(sessions_by_category)} sessions with category {category}')
   return jsonify(sessions_by_category)

# # Other App Routes

Esegui nuovamente il deployment del servizio su Cloud Run utilizzando lo stesso comando della sezione precedente e, una volta eseguito il deployment, esegui alcune chiamate all'endpoint /sessions/categories/<category>.

Vai al Cloud Console → Logs Explorer

59e297577570695.png

...e dovresti essere in grado di filtrare queste istruzioni di logging come mostrato di seguito:

914f1fb6cac30a89.png

Puoi fare clic su una qualsiasi delle istruzioni di log, espanderla e quindi fare clic su Explain this log entry. Verrà utilizzato Gemini per spiegare la voce di log. Tieni presente che se non hai abilitato Gemini per Google Cloud, ti verrà chiesto di abilitare l'API Cloud AI Companion. Procedi seguendo le istruzioni.

Di seguito è riportato un esempio di risposta:

7fc9783910fa92cc.png

16. Complimenti

Complimenti, hai creato un'applicazione da zero e utilizzato Gemini Code Assist in diversi aspetti dello SDLC, tra cui progettazione, build, test e deployment.

Passaggi successivi

Dai un'occhiata ad alcuni di questi codelab...

Documenti di riferimento