Entwicklungs-Workflow mit Gemini Code Assist optimieren

1. Einleitung

e5b98fd4e417c877.png

In diesem Codelab erfahren Sie, wie Gemini Code Assist Sie in den wichtigsten Phasen des Softwareentwicklungszyklus (Software Development Life Cycle, SDLC) wie Design, Entwicklung, Test und Bereitstellung unterstützen kann. Wir entwerfen und entwickeln eine komplette Anwendung und stellen sie in Google Cloud bereit.

Im Rahmen einer technischen Veranstaltung entwickeln wir eine API und eine Anwendung für die sitzungsübergreifende Suche. Jede Sitzung hat einen Titel, eine Zusammenfassung, die Dauer, Kategorien und mindestens einen Sprecher.

Aufgabe

  • Webanwendung basierend auf einer OpenAPI-Spezifikation von Grund auf neu entwerfen, erstellen, testen und bereitstellen

Lerninhalte

  • Mit Gemini Code Assist eine OpenAPI-Spezifikation generieren
  • Mit den Codegenerierungsfunktionen von Gemini Code Assist eine Python Flask-Anwendung für die OpenAPI-Spezifikation entwickeln
  • Gemini Code Assist verwenden, um ein Web-Front-End für die Python Flask-Anwendung zu generieren
  • Gemini Code Assist verwenden, um Unterstützung beim Bereitstellen der Anwendung in Google Cloud Run zu erhalten
  • Beim Entwickeln und Testen der Anwendung Gemini Code Assist-Funktionen wie Codeerklärung und Testfallgenerierung verwenden

Voraussetzungen

  • Chrome-Webbrowser
  • Ein Gmail-Konto
  • Ein Cloud-Projekt mit aktivierter Abrechnung
  • Gemini Code Assist ist für Ihr Cloud-Projekt aktiviert

Dieses Lab richtet sich an Entwickler aller Stufen, auch Anfänger. Die Beispielanwendung ist zwar in Python geschrieben, aber Sie müssen nicht mit der Python-Programmierung vertraut sein, um die Situation zu verstehen. Wir konzentrieren uns darauf, uns mit den Funktionen von Gemini Code Assist vertraut zu machen.

2. Gemini Code Assist einrichten

In diesem Abschnitt werden alle Schritte behandelt, die für den Einstieg in dieses Lab erforderlich sind.

Gemini Code Assist in der Cloud Shell-IDE aktivieren

Für den Rest des Codelabs verwenden wir die Cloud Shell-IDE, eine vollständig verwaltete Code OSS-basierte Entwicklungsumgebung. Wir müssen Code Assist in der Cloud Shell-IDE aktivieren und konfigurieren. Gehen Sie dazu so vor:

  1. Rufen Sie ide.cloud.google.com auf. Es kann eine Weile dauern, bis die IDE erscheint. Bitte haben Sie ein wenig Geduld und akzeptieren Sie die Standardeinstellungen für die Einrichtung. Falls Sie Anleitungen zum Einrichten der IDE sehen, nehmen Sie diese mit den Standardeinstellungen vor.
  2. Klicken Sie wie dargestellt in der unteren Statusleiste auf die Schaltfläche Cloud Code – Sign in (Cloud Code – Anmelden). Autorisieren Sie das Plug-in wie angegeben. Wenn in der Statusleiste Cloud Code - no project angezeigt wird, wählen Sie diese Option aus und wählen Sie dann das gewünschte Google Cloud-Projekt aus der Liste der Projekte aus, mit denen Sie arbeiten möchten.

6f5ce865fc7a3ef5.png

  1. Klicken Sie rechts unten auf die Schaltfläche Code Assist (Codeassistent) und wählen Sie ein letztes Mal das richtige Google Cloud-Projekt aus. Wenn Sie aufgefordert werden, die Cloud AI Companion API zu aktivieren, tun Sie dies, bevor Sie fortfahren.
  2. Nachdem Sie Ihr Google Cloud-Projekt ausgewählt haben, prüfen Sie, ob dies in der Cloud Code-Statusmeldung in der Statusleiste zu sehen ist und ob Code Assist auf der rechten Seite aktiviert ist (siehe unten):

709e6c8248ac7d88.png

Gemini Code Assist kann jetzt verwendet werden.

3. Firestore einrichten

Cloud Firestore ist eine vollständig verwaltete serverlose Dokumentendatenbank, die als Back-End für unsere Anwendungsdaten verwendet wird. Daten in Cloud Firestore sind in Sammlungen von Dokumenten strukturiert.

Wir müssen eine Sammlung mit dem Namen sessions in unserer Firestore-Standarddatenbank erstellen. Diese Sammlung enthält Beispieldaten (Dokumente), die wir dann in unserer Anwendung verwenden werden.

Öffnen Sie das Terminal in der Cloud Shell-IDE über das Hauptmenü, wie unten gezeigt:

f1535e14c9beeec6.png

Wir müssen eine Sammlung mit dem Namen sessions erstellen. Sie enthält eine Liste mit beispielhaften Sitzungsdokumenten. Jedes Dokument hat die folgenden Attribute:

  1. title: String
  2. categories: String-Array
  3. speakers: Stringarray
  4. duration: String
  5. summary: String

Wir füllen diese Sammlung mit Beispieldaten, indem wir eine Datei mit den Beispieldaten in einen Bucket in Ihrem eigenen Projekt kopieren. Von dort aus können Sie die Sammlung dann mit dem Befehl gcloud firestore import importieren.

Initialisierung der Firestore-Datenbank

Rufen Sie in der Cloud Console die Firestore-Seite auf.

Wenn Sie im Projekt noch keine Firestore-Datenbank initialisiert haben, erstellen Sie die Datenbank default. Verwenden Sie beim Erstellen der Datenbank die folgenden Werte:

  • Firestore-Modus: Native
  • Standort: Wählen Sie als Standorttyp Region und dann die Region aus, die für Ihre Anwendung geeignet ist. Notieren Sie sich diesen Standort, da Sie ihn im nächsten Schritt für den Bucket-Standort benötigen.
  • Erstellen Sie die Datenbank.

504cabdb99a222a5.png

So erstellen Sie jetzt die Sammlung sessions:

  1. Erstellen Sie mit dem unten angegebenen Befehl gsutil einen Bucket in Ihrem Projekt. Ersetzen Sie die Variable <PROJECT_ID> im Befehl unten durch Ihre Google Cloud-Projekt-ID. Ersetzen Sie <BUCKET_LOCATION> durch einen Regionsnamen, der dem geografischen Bereich Ihrer Firestore-Standarddatenbank entspricht (wie im vorherigen Schritt erwähnt). Dieser kann US-WEST1, EUROPE-WEST1, ASIA-EAST1 lauten :
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
  1. Nachdem der Bucket erstellt wurde, müssen Sie den vorbereiteten Datenbankexport in diesen Bucket kopieren, bevor Sie ihn in die Firebase-Datenbank importieren können. Verwenden Sie dazu den folgenden Befehl:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256  gs://<PROJECT_ID>-my-bucket

Da wir nun die zu importierenden Daten haben, können wir mit dem letzten Schritt fortfahren: Importieren der Daten in die von uns erstellte Firebase-Datenbank (default).

  1. Verwenden Sie den unten angegebenen gcloud-Befehl:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256

Der Import dauert einige Sekunden. Sobald er bereit ist, können Sie Ihre Firestore-Datenbank und die Sammlung validieren. Rufen Sie dazu https://console.cloud.google.com/firestore/databases auf und wählen Sie die default-Datenbank und die sessions-Sammlung aus (siehe unten):

d3e294d46ba29cd5.png

Damit ist die Erstellung der Firestore-Sammlung abgeschlossen, die wir in unserer Anwendung verwenden werden.

4. Anwendungsvorlage erstellen

Wir erstellen eine Beispielanwendung (eine Python Flask-Anwendung), die wir im restlichen Codelab verwenden. Diese Anwendung durchsucht alle Sitzungen, die auf technischen Konferenzen angeboten werden.

Gehen Sie so vor:

  1. Klicken Sie in der Statusleiste unten auf den Google Cloud-Projektnamen.

f151759c156c124e.png

  1. Eine Liste mit Optionen wird angezeigt. Klicken Sie in der Liste unten auf New Application (Neue Anwendung).

91ea9836f38b7f74.png

  1. Wählen Sie Cloud Run-Anwendung aus. Dies ist die Laufzeit für unsere Anwendung.
  2. Wählen Sie die Anwendungsvorlage Python (Flask): Cloud Run aus.
  3. Benennen Sie die Anwendung und speichern Sie sie am gewünschten Speicherort.
  4. In einer Benachrichtigung wird bestätigt, dass Ihre Anwendung erstellt wurde. Daraufhin wird ein neues Fenster geöffnet, in dem Ihre Anwendung geladen ist (siehe unten). Eine README.md-Datei wird geöffnet. Sie können diese Ansicht vorerst schließen.

aaa3725b17ce27cf.png

5. Mit Gemini Code Assist interagieren

Für dieses Lab verwenden wir den Gemini Code Assist Chat, der in der Cloud Shell IDE als Teil der Cloud Code-Erweiterung in VS Code verfügbar ist. Sie können ihn aufrufen, indem Sie in der linken Navigationsleiste auf die Schaltfläche Code Assist klicken. Suchen Sie in der linken Navigationsleiste nach dem Code Assist-Symbol a489f98a34898727.png und klicken Sie darauf.

Dadurch wird das Chatfenster von Code Assist in der Cloud Shell IDE geöffnet und Sie können mit Code Assist chatten.

14ad103efaa0ddaa.png

Beachten Sie das Papierkorbsymbol oben. Damit können Sie den Kontext für den Code Assist-Chatverlauf zurücksetzen. Beachten Sie auch, dass diese Chat-Interaktion kontextabhängig von den Dateien ist, an denen Sie in der IDE arbeiten.

6. API-Design

Der erste Schritt besteht darin, Gemini Code Assist während der Designphase zu unterstützen. In diesem Schritt generieren wir eine OpenAPI-Spezifikation für die Entitäten (technische Sitzungen in einem Ereignis), die durchsucht werden sollen.

Geben Sie den folgenden Prompt ein:

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.

Dadurch sollte eine OpenAPI-Spezifikation für die sitzungsübergreifende Suche mithilfe verschiedener Abfrageparameter generiert werden. Im Folgenden finden Sie ein Spezifikationsbeispiel:

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

Sie sehen, dass die Spezifikation Folgendes enthält:

  • Ein Schema, das für den Sitzungstyp definiert wurde.
  • Mehrere API-Pfade definiert:
  • /sessions
  • /sessions/{id}
  • /sessions/categories/{category}

Erstellen Sie im obersten Ordner eine Datei mit dem Namen sessionsapi.yaml und kopieren Sie den Inhalt mit der Option „In aktuelle Datei einfügen“ (+) aus dem Chatfenster von Code Assist. Lassen Sie die Datei in der Cloud Shell-IDE geöffnet.

An dieser Stelle können Sie eine interessante Funktion von Gemini Code Assist bemerken: Zitation. Diese Informationen werden dem Entwickler angezeigt, wenn der generierte Code direkt aus einer anderen Quelle, z. B. vorhandenem Open-Source-Code, in ausführlicher Zitate führt. Es stellt die Quelle und die Lizenz für den Entwickler bereit, damit er entscheiden kann, wie er damit umgehen soll.

Wenn wir mit dem generierten Inhalt einverstanden sind, können wir dieses Spezifikationsdokument jetzt verwenden, um eine Python Flask-Anwendung dafür zu generieren.

7. Anwendung generieren

Wir fordern nun Code Assist auf, die Anwendung zu generieren. Geben Sie den folgenden Prompt ein, während die Datei sessionsapi.yaml geöffnet ist.

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.

Dadurch erhalten Sie ein Grundgerüst für die Python Flask-Anwendung, das auf den Funktionen und Pfaden basiert, die in der OpenAPI-Spezifikationsdatei angegeben wurden.

Der bereitgestellte Python Flask-Anwendungscode sollte in etwa so aussehen:

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()

Im vorherigen Schritt wurde eine app.py-Datei generiert. Ersetzen Sie einfach den Inhalt durch den von Code Assist generierten Code und speichern Sie die Datei.

Wir möchten die app.run()-Zeile so ändern, dass Port 8080 und die Hostadresse 0.0.0.0 verwendet und auch während der lokalen Ausführung im Debug-Modus ausgeführt werden. Zunächst wählen wir die folgende Zeile aus:

app.run()

Geben Sie dann im Chat mit Code Assist den folgenden Prompt ein: Explain this.

Daraufhin sollte eine detaillierte Erklärung der jeweiligen Zeile angezeigt werden, wie unten ein Beispiel gezeigt:

58ec896a32a4fb68.png

Verwenden Sie nun den folgenden Prompt:

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

Der vorgeschlagene Code sollte so aussehen:

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

Denken Sie daran, die Datei app.py mit diesem Snippet zu aktualisieren.

Anwendung lokal ausführen

Lassen Sie uns die Anwendung nun lokal ausführen, um die Anwendungsanforderungen gemäß dem, was wir angefangen haben, zu validieren.

Der erste Schritt besteht darin, eine virtuelle Python-Umgebung mit den Python-Paketabhängigkeiten in requirements.txt zu erstellen und in der virtuellen Umgebung zu installieren. Öffnen Sie dazu in der Cloud Shell-IDE die Befehlspalette (Strg + Umschalttaste + P) und geben Sie Python-Umgebung erstellen ein. Führen Sie die nächsten Schritte aus, um eine virtuelle Umgebung (venv), einen Python 3.x-Interpreter und die Datei requirements.txt auszuwählen.

Nachdem die Umgebung erstellt wurde, starten Sie ein neues Terminalfenster („Strg + Umschalttaste + “) und geben den folgenden Befehl ein:

python app.py

Im Folgenden finden Sie eine Beispielausführung:

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

Sie können jetzt unter den folgenden URLs eine Vorschau der API anzeigen. Es wird davon ausgegangen, dass Ihr Entwicklungsteam über Port 8080 ausgeführt wird. Falls nicht, ändern Sie sie in die entsprechende Portnummer.

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

Führen Sie die folgenden Schritte aus, um sicherzustellen, dass Sie die in der Datei app.py enthaltenen JSON-Daten über diese URLs abrufen können:

Öffnen Sie ein neues Terminalfenster und führen Sie einen der folgenden Befehle aus:

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

Anstatt die hartcodierten JSON-Beispieldaten in app.py zu enthalten, möchten wir diese wahrscheinlich in ein anderes Modul aufteilen/extrahieren, damit wir eine saubere Trennung zwischen Code und Daten aufrechterhalten können. Los gehts!

Lassen Sie die Datei app.py geöffnet und geben Sie Folgendes ein:

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

Dies sollte Ihnen einige Vorschläge dazu geben. Hier sehen Sie einen Beispielvorschlag, den wir erhalten haben und der in etwa so aussehen sollte:

9b9c56cb527dac4c.png

Im Folgenden werden wir unsere Daten in eine sessions.py-Datei aufteilen, wie von Code Assist vorgeschlagen.

Erstellen Sie eine neue Datei mit dem Namen sessions.py.

, deren Inhalt die JSON-Liste ist, gemäß den generierten Daten im Folgenden:

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",
   },
]

Die Datei app.py ist jetzt viel vereinfacht und sieht so aus:

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)

Stellen Sie sicher, dass Sie die Anwendung weiterhin lokal ausführen und die API mit diesen refaktorierten Änderungen ausführen können. Da der Python-Entwicklungsserver wahrscheinlich noch ausgeführt wird, müssen Sie nur die curl-Befehle aus dem vorherigen Schritt abrufen.

9. In Firestore-Sammlung einbinden

Der nächste Schritt besteht darin, uns von der lokalen In-Memory-JSON-Liste für unsere Sitzungen zu entfernen und unsere Anwendung mit der Sammlung sessions in der Firestore-Datenbank zu verbinden, die wir zu Beginn dieses Codelabs erstellt haben.

Lassen Sie die Datei sessions.py geöffnet und geben Sie Folgendes ein:

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. 

Wir haben den folgenden Vorschlag erhalten, alle Sitzungen aus der Firestore-Sammlung zu lesen:

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)

Binden Sie den Code nun in sessions.py ein.

Wenn der Flask-Entwicklungsserver lokal ausgeführt wird, wurde Ihre Anwendung möglicherweise geschlossen und beschwert, dass das Python-Modul nicht gefunden wurde.

Sie können Code Assist beispielsweise so fragen, welches Python-Modul der Datei requirements.txt hinzugefügt werden muss:

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

Dadurch erhalten Sie den Namen des Python-Moduls (z.B. google-cloud-firestore). Fügen Sie diesen in die Datei requirements.txt ein.

Sie müssen die Python-Umgebung mit dem neu hinzugefügten Modul (google-cloud-firestore) neu erstellen. Geben Sie dazu den folgenden Befehl im vorhandenen Terminalfenster ein:

pip install -r requirements.txt

Führen Sie die Anwendung noch einmal aus, starten Sie sie mit python app.py neu und rufen Sie die URL /sessions auf. Sie sollten jetzt die Beispieldokumente erhalten, die wir der Sammlung sessions hinzugefügt haben.

975d05e6518f1a6a.png

Sie können auch andere URIs abfragen, um bestimmte Sitzungen oder alle Sitzungen für eine bestimmte Kategorie abzurufen, wie in den vorherigen Schritten beschrieben.

10. Erläuterung des Codes

Jetzt ist ein guter Zeitpunkt, die "Explain this"-Funktion von Gemini Code Assist zu verwenden, um den Code besser zu verstehen. Sie können in jede beliebige Datei gehen oder bestimmte Code-Snippets auswählen und Code Assist mit dem folgenden Prompt fragen: Explain this.

Rufen Sie als Übung die Datei sessions.py auf und markieren Sie den Firestore-spezifischen Code, um eine Codeerklärung dazu zu erhalten. Versuchen Sie, diese Funktion auch für andere Dateien in Ihrem Projekt und nicht nur für Python-Code zu verwenden.

11. Webanwendung generieren

Nachdem Sie die API generiert und in eine Live-Firestore-Sammlung integriert haben, können wir ein webbasiertes Front-End für die Anwendung generieren. Unser Web-Frontend beschränkt die Funktionalität derzeit auf ein Minimum, d.h. es kann nach Sitzungen suchen, die zu einer bestimmten Kategorie gehören. Denken Sie daran, dass wir einen API-Pfad dafür haben, z. B. /sessions/categories/{category}. Unsere Webanwendung sollte also dieses aufrufen und die Ergebnisse abrufen.

Lassen Sie uns direkt loslegen. Geben Sie Code Assist den folgenden Prompt:

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.

Dadurch wird der HTML-Code der Webanwendung mit eingebettetem JavaScript und CSS generiert. Außerdem werden Sie aufgefordert, der Datei app.py eine neue Route hinzuzufügen, damit jeder Nutzer, der die Stamm- oder Basis-URL aufruft, die Startseite erhält. Wenn diese Informationen nicht erwähnt werden, fragen Sie danach oder verwenden Sie das folgende Snippet:

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

Sie können die Datei als index.html speichern. Sie sind sich aber nicht sicher, wo die Datei gespeichert werden soll (in welchem Ordner?). Wir können Code Assist eine weiterführende Frage stellen.

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

Sie sollte deutlich machen, dass das render_template-Framework verwendet wird und daher die Datei „index.html“ im Ordner templates abgelegt werden muss. Sie finden diesen Ordner verfügbar, da wir zu Beginn dieses Codelabs eine Anwendung generiert haben, die auf der Flask-Vorlage basiert. Aus diesem Grund ist bereits eine index.html-Datei vorhanden. Sie sollten ihren Inhalt einfach durch die neue Datei ersetzen, die hier generiert wurde. Code Assist erwähnt auch, render_template in Ihre app.py-Datei zu importieren.

Speichern Sie den Code für die Webanwendung in der Datei index.html und platzieren Sie sie im Ordner templates.

Anwendung lokal ausführen

Lassen Sie uns die Anwendung nun lokal ausführen, um die Anwendungsanforderungen gemäß dem, was wir angefangen haben, zu validieren.

Vergewissern Sie sich, dass der lokale Flask-Server noch ausgeführt wird und keine Fehler anzeigt. Beheben Sie etwaige Fehler und starten Sie den Server.

Rufen Sie nach der Einrichtung die Startseiten-URL der Anwendung auf. Hier sollte die bereitgestellte index.html-Datei zu sehen sein:

8ca586acc4536879.png

Geben Sie eine der Kategorien aus den Daten als Eingabe an (z.B. AI) und klicken Sie auf die Schaltfläche Search. Daraufhin sollten die mit der Kategorie AI getaggten Sitzungen angezeigt werden.

165faded790a6c.png

Eine optionale Übung besteht darin, für jede Sitzung zusätzliche Metadaten wie Dauer, Kategorien, Sprecher und Zusammenfassungen anzuzeigen.

12. Testlauferstellung

Wir haben die Sessions API generiert und nutzen jetzt Gemini Code Assist, um Einheitentestfälle für die verschiedenen API-Pfade zu generieren.

Lassen Sie die Datei app.py geöffnet und geben Sie Folgendes ein:

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

Wir haben folgende Antwort erhalten:

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()

Erstellen Sie eine Datei mit dem Namen tests.py mit dem Code oben.

Hinweis zum Generieren von Testläufen

Möglicherweise wird eine andere Codeauflistung als die obige Codeliste angezeigt, was zu Problemen beim Ausführen der Testläufe führen kann. Beispielsweise haben wir festgestellt, dass in einigen unserer Ausführungen die folgenden wichtigen Code-Elemente übersehen wurden:

from app import app

Der obige Code ist erforderlich, um die vorhandene Flask-Anwendung zu importieren, für die die Testläufe aufgerufen werden.

if __name__ == '__main__':

`unittest.main()`

Der obige Code wird zum Ausführen der Testläufe benötigt.

Wir empfehlen Ihnen, sich alle Testfälle anzusehen und die assertEqual und andere Bedingungen im generierten Code zu prüfen, um sicherzustellen, dass er funktioniert. Da die Daten in der Firestore-Sammlung extern sind, haben sie möglicherweise keinen Zugriff darauf und verwenden möglicherweise Dummy-Daten, wodurch die Tests fehlschlagen können. Passen Sie Ihre Testläufe daher entsprechend an oder kommentieren Sie einige Testläufe aus, die Sie möglicherweise nicht sofort benötigen.

Zur Veranschaulichung haben wir die Testfälle mit dem folgenden Befehl ausgeführt. Führen Sie unbedingt den lokalen Entwicklungsteam aus, da Aufrufe an die lokalen API-Endpunkte erfolgen:

python tests.py

Wir haben das folgende zusammenfassende Ergebnis erhalten:

Ran 4 tests in 0.274s

FAILED (failures=2)

Das ist in der Tat richtig, da die Sitzungs-ID im dritten Test nicht korrekt war und keine Kategorie mit dem Namen category1 vorhanden ist.

.

Passe also die Testläufe entsprechend an und probiere es aus.

13. Testgesteuerte Entwicklung

Als Nächstes sehen wir uns an, wie wir unserer Sessions API eine neue Suchmethode hinzufügen können, die der Test Driven Development (TDD)-Methode folgt. Dabei geht es darum, zuerst Testfälle zu schreiben, die dazu führen sollen, dass sie aufgrund fehlender Implementierungen scheitern, und mithilfe von Gemini Code Assist die fehlende Implementierung generieren, damit der Test bestanden wird.

Rufen Sie die Datei „tests.py“ auf (vorausgesetzt, Sie haben die Datei tests.py so korrigiert, dass alle bestandenen Tests enthalten sind). Bitten Sie Code Assist, die folgende Aufforderung zu erhalten:

Generate a new test case to search for sessions by speaker

So erhielten wir die folgende Testfallimplementierung, die wir ordnungsgemäß in die Datei tests.py eingefügt haben.

  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]])

Wenn Sie die Tests ausführen, sollten Sie den folgenden Fehler sehen:

$ 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)

Das liegt daran, dass der Testfall den Pfad (/sessions/speakers/) aufgerufen hat und dieser nicht in app.py implementiert ist.

Lassen Sie uns Code Assist bitten, uns eine Implementierung zu ermöglichen. Rufen Sie die Datei app.py auf und geben Sie in Code Assist den folgenden Prompt ein:

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

Wir haben die folgende von Code Assist vorgeschlagene Implementierung erhalten, die wir der Datei app.py hinzugefügt haben:

@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)

Sehen Sie sich die Datei tests.py noch einmal an. Wir haben unseren Testfall so geändert, dass Sie ihn schnell prüfen können:

   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)

Der Test lief gut. Wir überlassen es Ihnen als Übung, sich die generierten Testfälle anzusehen, sie je nach den Daten in Firestore ein wenig zu optimieren und die entsprechenden assert*-Methoden in den Python-Einheitentestfällen zu verwenden.

14. In Google Cloud Run bereitstellen

Da wir nun mit der Qualität unserer Entwicklung zufrieden sind, stellen wir diese Anwendung im letzten Schritt in Google Cloud Run bereit. Aber vielleicht sollten wir Code Assist fragen, wenn wir etwas vergessen haben. Wenn app.py geöffnet ist, senden Sie den folgenden Prompt :

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

Gut, dass Sie sich gewünscht haben, da wir vergessen haben, die Debugging-Markierung auf off zu setzen :

2f87ed3a811fb218.png

Deaktivieren Sie wie angegeben das Debugging und bitten Sie Gemini Code Assist um Hilfe mit dem Befehl gcloud, mit dem die Anwendung direkt aus der Quelle in Cloud Run bereitgestellt werden kann (ohne zuerst einen Container erstellen zu müssen).

Geben Sie den folgenden Prompt ein:

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

Probieren Sie einige Varianten des obigen Prompts aus. Wir haben auch Folgendes versucht:

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?

Im Idealfall sollten Sie den folgenden gcloud-Befehl erhalten:

gcloud run deploy sessions --source .

Weitere Vorteile:

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

Führen Sie den obigen Befehl vom Stammverzeichnis der Anwendung aus aus. Wenn Sie nach region gefragt werden, wählen Sie us-central1 aus. Wenn Sie gefragt werden, ob Sie unauthenticated invocations zulassen möchten, wählen Sie Y aus. Möglicherweise werden Sie auch aufgefordert, Google Cloud APIs wie Artifact Registry, Cloud Build und Cloud Run zu aktivieren und die Berechtigung zum Erstellen eines Artifact Registry-Repositorys zu erteilen.

Die Bereitstellung dauert etwa zwei Minuten. Bitte haben Sie etwas Geduld.

Nach der erfolgreichen Bereitstellung wird die URL des Cloud Run-Dienstes angezeigt. Rufen Sie diese öffentliche URL auf. Sie sollten nun dieselbe Webanwendung bereitstellen und ausführen.

c5322d0fd3e0f616.png

Glückwunsch, gut gemacht!

15. (Optional) Cloud Logging verwenden

Wir können Logging in unserer Anwendung so einführen, dass die Anwendungslogs in einem der Google Cloud-Dienste (Cloud Logging) zentralisiert werden. Anschließend können wir die Funktion „Observability Gemini“ verwenden, um auch Logeinträge zu verstehen.

Dazu müssen wir zuerst eine vorhandene Cloud Logging-Bibliothek von Google Cloud in Python verwenden und diese für das Logging von Informationen, Warnungen oder Fehlermeldungen verwenden (abhängig vom Log-/Schweregrad).

Versuchen wir es zuerst mit Code Assist. Versuchen Sie es mit dem folgenden Prompt:

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

Sie sollten eine Antwort mit einigen Informationen dazu erhalten:

2472e1ccaf8a217d.png

Fügen wir der Funktion, die Sitzungen nach Kategorie sucht, Logging-Anweisungen hinzu.

Fügen Sie der Datei requirements.txt zuerst das Python-Paket google-cloud-logging hinzu.

Als Nächstes sehen Sie ein Code-Snippet, das zeigt, wie wir den Code zur Implementierung der Protokollierung integriert haben:

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

Stellen Sie den Dienst noch einmal in Cloud Run bereit. Verwenden Sie dazu denselben Befehl wie im vorherigen Abschnitt und führen Sie nach der Bereitstellung einige Aufrufe an den /sessions/categories/<category>-Endpunkt aus.

Rufen Sie die Cloud Console → Logs Explorer auf.

59e297577570695.png

...und Sie sollten in der Lage sein, diese Logging-Anweisungen wie unten dargestellt zu filtern:

914f1fb6cac30a89.png

Sie können auf die einzelnen Logberichte klicken, sie maximieren und dann auf Explain this log entry klicken. Der Logeintrag wird mithilfe von Gemini erklärt. Wenn Sie Gemini für Google Cloud nicht aktiviert haben, werden Sie aufgefordert, die Cloud AI Companion API zu aktivieren. Folgen Sie der Anleitung.

Hier eine Beispielantwort:

7fc9783910fa92cc.png

16. Glückwunsch

Herzlichen Glückwunsch! Sie haben eine Anwendung von Grund auf neu erstellt und Gemini Code Assist für mehrere Aspekte des SDLC verwendet, darunter Design, Build, Test und Bereitstellung.

Was liegt als Nächstes an?

Sehen Sie sich einige dieser Codelabs an...

Referenzdokumente