1. Wprowadzenie

W tym samouczku dowiesz się, jak Gemini Code Assist może Ci pomóc na kluczowych etapach cyklu życia oprogramowania (SDLC), takich jak projektowanie, tworzenie i testowanie oraz wdrażanie. Zaprojektujemy i opracujemy całą aplikację, a następnie wdrożymy ją w Google Cloud.
Stworzymy interfejs API i aplikację do wyszukiwania sesji w ramach wydarzenia technicznego. Każda sesja będzie miała tytuł, podsumowanie, czas trwania, kategorie i co najmniej jednego prelegenta.
Co musisz zrobić
- Projektowanie, tworzenie, testowanie i wdrażanie aplikacji internetowej od podstaw na podstawie specyfikacji OpenAPI
Czego się nauczysz
- Jak używać Gemini Code Assist do generowania specyfikacji OpenAPI
- Jak używać funkcji generowania kodu Gemini Code Assist do tworzenia aplikacji Python Flask na potrzeby specyfikacji OpenAPI
- Jak używać Gemini Code Assist do generowania interfejsu internetowego aplikacji Python Flask
- Jak korzystać z Gemini Code Assist, aby uzyskać pomoc dotyczącą wdrażania aplikacji w Google Cloud Run
- Korzystaj z funkcji Gemini Code Assist, takich jak wyjaśnianie kodu i generowanie przypadków testowych, podczas tworzenia i testowania aplikacji.
Czego potrzebujesz
- przeglądarki Chrome,
- konto Gmail,
- Projekt w chmurze z włączonymi płatnościami
- Usługa Gemini Code Assist jest włączona w Twoim projekcie w Cloud
Ten moduł jest przeznaczony dla deweloperów na wszystkich poziomach zaawansowania, w tym dla początkujących. Chociaż przykładowa aplikacja jest napisana w języku Python, nie musisz znać tego języka, aby zrozumieć, co się dzieje. Skupimy się na zapoznaniu się z możliwościami Gemini Code Assist.
2. Konfigurowanie Gemini Code Assist
W tej sekcji znajdziesz wszystko, co musisz zrobić, aby rozpocząć ten moduł.
Włączanie Gemini Code Assist w środowisku IDE Cloud Shell
W pozostałej części tego samouczka będziemy używać Cloud Shell IDE, w pełni zarządzanego środowiska programistycznego opartego na Code OSS. Musimy włączyć i skonfigurować Code Assist w środowisku IDE Cloud Shell. Poniżej znajdziesz instrukcje:
- Otwórz ide.cloud.google.com. Wyświetlenie środowiska IDE może zająć trochę czasu, więc poczekaj i zaakceptuj domyślne ustawienia. Jeśli zobaczysz instrukcje dotyczące konfigurowania środowiska IDE, wykonaj je z ustawieniami domyślnymi.
- Na pasku stanu u dołu kliknij przycisk Cloud Code – zaloguj się, jak pokazano na ilustracji. Autoryzuj wtyczkę zgodnie z instrukcjami. Jeśli na pasku stanu widzisz „Cloud Code – brak projektu”, wybierz tę opcję, a następnie wybierz z listy projekt Google Cloud, z którym chcesz pracować.

- Kliknij przycisk Pomocnik w pisaniu kodu w prawym dolnym rogu, jak pokazano na ilustracji, i jeszcze raz wybierz właściwy projekt w chmurze Google. Jeśli pojawi się prośba o włączenie interfejsu Cloud AI Companion API, zrób to i przejdź dalej.
- Po wybraniu projektu Google Cloud sprawdź, czy jest on widoczny w komunikacie o stanie Cloud Code na pasku stanu oraz czy po prawej stronie na pasku stanu masz włączoną funkcję Code Assist, jak pokazano poniżej:

Usługa Gemini Code Assist jest gotowa do użycia.
3. Konfigurowanie Firestore
Cloud Firestore to w pełni zarządzana bezserwerowa baza danych dokumentów, której będziemy używać jako backendu do danych aplikacji. Dane w Cloud Firestore są uporządkowane w kolekcjach dokumentów.
Musimy utworzyć kolekcję o nazwie sessions w domyślnej bazie danych Firestore. Będzie ona zawierać przykładowe dane (dokumenty), których będziemy używać w naszej aplikacji.
Otwórz terminal w środowisku IDE Cloud Shell za pomocą menu głównego, jak pokazano poniżej:

Musimy utworzyć kolekcję o nazwie sessions. Będzie ona zawierać listę przykładowych dokumentów sesji. Każdy dokument będzie miał te atrybuty:
- title: ciąg znaków
- categories: tablica ciągów znaków
- speakers: tablica ciągów znaków
- duration: ciąg znaków
- summary: ciąg znaków
Wypełnijmy tę kolekcję przykładowymi danymi, kopiując plik zawierający przykładowe dane do zasobnika w Twoim projekcie, z którego możesz następnie zaimportować kolekcję za pomocą polecenia gcloud firestore import.
Inicjowanie bazy danych Firestore
Otwórz stronę Firestore w konsoli Cloud.
Jeśli w projekcie nie masz jeszcze zainicjowanej bazy danych Firestore, utwórz bazę danych default. Podczas tworzenia bazy danych użyj tych wartości:
- Tryb Firestore:
Native - Lokalizacja: wybierz typ lokalizacji
Regioni region odpowiedni dla Twojej aplikacji. Zanotuj tę lokalizację, ponieważ będzie Ci potrzebna w następnym kroku jako lokalizacja kosza. - Utwórz bazę danych.

Teraz utworzymy kolekcję sessions, wykonując te czynności:
- Utwórz zasobnik w projekcie za pomocą podanego poniżej polecenia
gsutil. W poniższym poleceniu zastąp zmienną<PROJECT_ID>identyfikatorem projektu Google Cloud. Zastąp<BUCKET_LOCATION>nazwą regionu odpowiadającą obszarowi geograficznemu domyślnej bazy danych Firestore (jak podano w poprzednim kroku). Może to być US-WEST1, EUROPE-WEST1 lub ASIA-EAST1 :
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
- Po utworzeniu zasobnika musimy skopiować do niego przygotowany eksport bazy danych, zanim będziemy mogli go zaimportować do bazy danych Firebase. Użyj polecenia podanego poniżej:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256 gs://<PROJECT_ID>-my-bucket
Teraz, gdy mamy dane do zaimportowania, możemy przejść do ostatniego kroku, czyli zaimportowania danych do utworzonej przez nas bazy danych Firebase (default).
- Użyj podanego niżej polecenia gcloud:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256
Importowanie potrwa kilka sekund. Po zakończeniu możesz sprawdzić bazę danych Firestore i kolekcję, otwierając stronę https://console.cloud.google.com/firestore/databases, wybierając bazę danych default i kolekcję sessions, jak pokazano poniżej:

W ten sposób utworzysz kolekcję Firestore, której będziemy używać w naszej aplikacji.
4. Tworzenie szablonu aplikacji
Utworzymy przykładową aplikację (aplikację Flask w języku Python), której będziemy używać w dalszej części tych ćwiczeń. Ta aplikacja będzie wyszukiwać sesje oferowane na konferencji technicznej.
Wykonaj te czynności:
- Na pasku stanu poniżej kliknij nazwę projektu Google Cloud.

- Pojawi się lista opcji. Na liście poniżej kliknij Nowa aplikacja.

- Wybierz Cloud Run application (będzie to środowisko wykonawcze naszej aplikacji).
- Wybierz szablon aplikacji Python (Flask): Cloud Run.
- Nadaj aplikacji nazwę i zapisz ją w wybranej lokalizacji.
- Pojawi się powiadomienie potwierdzające utworzenie aplikacji, a w nowym oknie otworzy się aplikacja, jak pokazano poniżej. Otworzy się plik
README.md. Możesz na razie zamknąć ten widok.

5. Interakcja z Gemini Code Assist
Na potrzeby tego modułu użyjemy czatu Gemini Code Assist dostępnego w środowisku IDE Cloud Shell w ramach rozszerzenia Cloud Code w VS Code. Możesz go otworzyć, klikając przycisk Asystent kodu na pasku nawigacyjnym po lewej stronie. Na pasku narzędzi nawigacyjnych po lewej stronie znajdź ikonę Code Assist
i kliknij ją.
Spowoduje to wyświetlenie panelu czatu Code Assist w środowisku IDE Cloud Shell, na którym możesz rozmawiać z Code Assist.

U góry zobaczysz ikonę kosza na śmieci – to sposób na zresetowanie kontekstu historii czatu Code Assist. Pamiętaj też, że ta rozmowa na czacie jest powiązana z plikami, nad którymi pracujesz w IDE.
6. Projekt interfejsu API
Pierwszym krokiem będzie skorzystanie z pomocy Gemini Code Assist na etapie projektowania. W tym kroku wygenerujemy specyfikację OpenAPI dla encji (sesji technicznych w ramach wydarzenia), które chcemy przeszukiwać.
Wpisz ten 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.
Powinno to wygenerować specyfikację OpenAPI do wyszukiwania w sesjach za pomocą różnych parametrów zapytania. Przykładowa specyfikacja:
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
W specyfikacji możesz zauważyć:
- Schemat zdefiniowany dla typu sesji.
- Zdefiniowano kilka ścieżek interfejsu API:
/sessions/sessions/{id}/sessions/categories/{category}
Utwórz w głównym folderze plik o nazwie sessionsapi.yaml i skopiuj do niego zawartość z okna czatu Asystenta kodu, korzystając z opcji „Wstaw do bieżącego pliku” (przycisk +). Pozostaw plik otwarty w IDE Cloud Shell.
W tym momencie możesz zwrócić uwagę na ciekawą funkcję Gemini Code Assist: cytowanie. Te informacje są udostępniane deweloperowi, gdy wygenerowany kod zawiera długie cytaty z innego źródła, np. z istniejącego kodu open source. Zawiera źródło i licencję, dzięki czemu deweloper może zdecydować, co z nim zrobić.
Jeśli wygenerowane treści są odpowiednie, możemy użyć tego dokumentu specyfikacji do wygenerowania aplikacji Python Flask.
7. Generowanie aplikacji
Teraz poprosimy Code Assist o wygenerowanie aplikacji. Wpisz ten prompt, gdy plik sessionsapi.yaml jest otwarty.
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.
Powinien on zawierać szkielet aplikacji Python Flask, który jest oparty na funkcjach i ścieżkach określonych w pliku specyfikacji OpenAPI.
Podany kod aplikacji w Pythonie Flask powinien być podobny do tego:
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()
Plik app.py został wygenerowany w poprzednim kroku. Wystarczy zastąpić jego zawartość kodem wygenerowanym przez Code Assist i zapisać plik.
Chcemy zmienić wiersz app.run(), aby używać portu 8080, adresu hosta 0.0.0.0, a także uruchamiać go w trybie debugowania podczas lokalnego wykonywania.Oto jak to zrobić. Najpierw zaznaczmy wiersz:
app.run()
Następnie w interfejsie czatu Code Assist wpisz prompt: Explain this.
Powinno się w nim znaleźć szczegółowe wyjaśnienie dotyczące danego wiersza. Przykład znajdziesz poniżej:

Teraz użyj tego prompta:
update the code to run the application on port 8080, host address 0.0.0.0, and in debug mode
Wygenerowany sugerowany kod powinien wyglądać tak:
app.run(host='0.0.0.0', port=8080, debug=True)
Pamiętaj, aby zaktualizować plik app.py za pomocą tego fragmentu kodu.
Lokalne uruchamianie aplikacji
Uruchommy teraz aplikację lokalnie, aby sprawdzić, czy spełnia ona wymagania, które określiliśmy na początku.
Pierwszym krokiem będzie utworzenie wirtualnego środowiska Pythona z zależnościami pakietu Pythona w pliku requirements.txt, które zostaną zainstalowane w środowisku wirtualnym. Aby to zrobić, otwórz paletę poleceń (Ctrl+Shift+P) w IDE Cloud Shell i wpisz Utwórz środowisko Pythona. Wykonaj kilka kolejnych kroków, aby wybrać środowisko wirtualne (venv), interpreter Pythona 3.x i plik requirements.txt.
Po utworzeniu środowiska otwórz nowe okno terminala (Ctrl+Shift+`) i wpisz to polecenie:
python app.py
Przykładowe wykonanie jest pokazane poniżej:
(.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
Możesz teraz wyświetlić podgląd interfejsu API pod tymi adresami URL. Zakładamy, że serwer programistyczny działa na porcie 8080. Jeśli nie, zmień go na odpowiedni numer portu.
https://<host-name>:8080/sessionshttps://<host-name>:8080/sessions/{id}https://<host-name>:8080/sessions/categories/{category}
Aby mieć pewność, że za pomocą tych adresów URL możesz pobrać dane JSON zawarte w pliku app.py, wykonaj te czynności:
Otwórz nowe okno terminala i wypróbuj dowolne z tych poleceń:
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. Refaktoryzacja kodu
Zamiast umieszczać w app.py zakodowane na stałe przykładowe dane JSON, prawdopodobnie chcielibyśmy je oddzielić lub wyodrębnić do innego modułu, aby zachować wyraźny podział między kodem a danymi. Zróbmy to!
Pozostaw otwarty plik app.py i wpisz ten prompt:
Can I improve this code and separate out the sessions data from this app.py file?
Powinny pojawić się sugestie, jak to zrobić. Przykładowa sugestia, którą otrzymaliśmy (Ty też powinieneś otrzymać podobną), jest pokazana poniżej:

Zgodnie z sugestią Asystenta kodu podzielmy dane na pliki sessions.py.
Utwórz nowy plik o nazwie sessions.py.
, której zawartość jest listą JSON, zgodnie z wygenerowanymi przez nas danymi:
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",
},
]
Plik app.py został znacznie uproszczony i wygląda teraz tak:
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)
Sprawdź, czy nadal możesz uruchamiać aplikację lokalnie i korzystać z interfejsu API po wprowadzeniu tych zmian. Serwer programistyczny Pythona prawdopodobnie nadal działa, więc wystarczy, że przypomnisz sobie polecenia curl z poprzedniego kroku.
9. Integracja z kolekcją Firestore
Następnym krokiem jest odejście od lokalnej listy JSON w pamięci, którą mamy dla naszych sesji, i połączenie aplikacji z kolekcją sessions w bazie danych Firestore, którą utworzyliśmy na początku tego laboratorium.
Pozostaw otwarty plik sessions.py i wpisz ten 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.
Otrzymaliśmy następującą sugestię, aby odczytać wszystkie sesje z kolekcji 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)
Wprowadź kod w sessions.py.
Jeśli lokalnie działa serwer programistyczny Flask, aplikacja mogła zostać zamknięta z powodu braku modułu Pythona.
Możesz na przykład zapytać Code Assist, który moduł Pythona należy dodać do pliku requirements.txt:
Which Python package needs to be installed to make the firestore code work?
Otrzymasz nazwę modułu Pythona (np. google-cloud-firestore). Dodaj ją do pliku requirements.txt.
Musisz ponownie utworzyć środowisko Pythona z nowo dodanym modułem (google-cloud-firestore). Aby to zrobić, wpisz w istniejącym oknie terminala to polecenie:
pip install -r requirements.txt
Uruchom ponownie aplikację (zrestartuj ją, klikając python app.py) i otwórz adres URL /sessions. Powinny się teraz wyświetlić przykładowe dokumenty, które dodaliśmy do kolekcji sessions.

Możesz wysyłać zapytania dotyczące innych identyfikatorów URI, aby pobrać konkretne sesje lub wszystkie sesje w danej kategorii, zgodnie z opisem w poprzednich krokach.
10. Wyjaśnienie kodu
Teraz jest dobry moment, aby użyć funkcji "Explain this" Gemini Code Assist i lepiej zrozumieć kod. Możesz otworzyć dowolny plik lub wybrać konkretne fragmenty kodu i zadać pytanie Code Assist, używając tego promptu: Explain this.
Aby poćwiczyć, otwórz plik sessions.py i zaznacz kod dotyczący Firestore, a następnie uzyskaj jego wyjaśnienie. Wypróbuj tę funkcję także w przypadku innych plików w projekcie, nie tylko kodu w języku Python.
11. Generowanie aplikacji internetowej
Po wygenerowaniu interfejsu API i zintegrowaniu go z aktywną kolekcją Firestore wygenerujmy frontend aplikacji oparty na internecie. Nasza platforma internetowa będzie obecnie miała minimalną funkcjonalność, tzn. będzie umożliwiać wyszukiwanie sesji należących do określonej kategorii. Pamiętaj, że mamy ścieżkę interfejsu API, czyli /sessions/categories/{category}, więc nasza aplikacja internetowa powinna ją wywołać i pobrać wyniki.
Zaczynajmy. Wpisz w Code Assist ten 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.
Spowoduje to wygenerowanie kodu HTML aplikacji internetowej z osadzonymi w nim kodami JavaScript i CSS. Poprosi Cię też o dodanie nowej trasy do pliku app.py, aby każdy użytkownik odwiedzający poziom główny lub podstawowy adres URL mógł zobaczyć stronę główną. Jeśli nie ma w nim tych informacji, zapytaj o nie lub użyj poniższego fragmentu:
@app.route('/')
def index():
return render_template('index.html')
Możesz zapisać ten plik jako index.html, ale możesz mieć pytanie, gdzie go zapisać (tzn. w którym folderze). Możemy zadać Asystentowi kodu dodatkowe pytanie.
Given that I am using the flask framework, where should I put the index.html file?
Powinny one zawierać jasne informacje o tym, że używa on platformy render_template, a w związku z tym plik index.html musi znajdować się w folderze templates. Ten folder będzie dostępny, ponieważ na początku tego ćwiczenia wygenerowaliśmy aplikację na podstawie szablonu Flask. W rezultacie istnieje już plik index.html, więc wystarczy zastąpić jego zawartość nową, wygenerowaną tutaj. Code Assist wspomina też o zaimportowaniu render_template w pliku app.py.
Zapisz kod aplikacji internetowej w pliku index.html i pamiętaj, aby umieścić go w folderze templates.
Lokalne uruchamianie aplikacji
Uruchommy teraz aplikację lokalnie, aby sprawdzić, czy spełnia ona wymagania, które określiliśmy na początku.
Sprawdź, czy lokalny serwer Flask nadal działa i nie wyświetla żadnych błędów. Jeśli wystąpią błędy, rozwiąż je i uruchom serwer.
Po uruchomieniu aplikacji otwórz jej adres URL. Powinien wyświetlić się plik index.html, jak pokazano poniżej:

Podaj jedną z kategorii z danych jako dane wejściowe (np. AI) i kliknij przycisk Search. Powinny się wyświetlić sesje otagowane kategorią AI.

Opcjonalnym ćwiczeniem jest wyświetlenie dodatkowych metadanych, takich jak czas trwania, kategorie, prelegenci i podsumowanie każdej sesji.
12. Generowanie przypadków testowych
Wygenerowaliśmy interfejs API sesji i możemy teraz użyć Gemini Code Assist, aby wygenerować przypadki testów jednostkowych dla różnych ścieżek interfejsu API.
Pozostaw otwarty plik app.py i wpisz ten prompt:
Generate unit test cases for app routes. Use unittest module.
Otrzymaliśmy następującą odpowiedź:
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()
Utwórz plik o nazwie tests.py z powyższym kodem.
Uwaga na temat generowania przypadków testowych
Może się zdarzyć, że zobaczysz inną listę kodów niż powyższa, co może powodować problemy z uruchamianiem przypadków testowych. Na przykład w niektórych naszych testach pominięto te kluczowe fragmenty kodu:
from app import app
Powyższy kod jest wymagany do zaimportowania istniejącej aplikacji Flask, w której będziemy wywoływać przypadki testowe.
if __name__ == '__main__':
`unittest.main()`
Powyższy kod jest potrzebny do uruchomienia przypadków testowych.
Zalecamy sprawdzenie każdego przypadku testowego, assertEqual i innych warunków w wygenerowanym kodzie, aby upewnić się, że będzie on działać. Ponieważ dane są zewnętrzne w kolekcji Firestore, może nie mieć do nich dostępu i w rezultacie używać danych testowych, co może powodować niepowodzenie testów. Dostosuj odpowiednio przypadki testowe lub zakomentuj niektóre z nich, jeśli nie są Ci od razu potrzebne.
Na potrzeby demonstracji uruchomiliśmy przypadki testowe za pomocą tego polecenia (pamiętaj, aby uruchomić lokalny serwer deweloperski, ponieważ wywołania będą kierowane do lokalnych punktów końcowych interfejsu API):
python tests.py
Otrzymaliśmy to podsumowanie:
Ran 4 tests in 0.274s
FAILED (failures=2)
To prawda, ponieważ w 3 teście identyfikator sesji był nieprawidłowy, a nie ma kategorii o nazwie category1.
.
Dostosuj odpowiednio elementy testowania i przeprowadź test.
13. Test Driven Development
Przyjrzyjmy się teraz dodawaniu nowej metody wyszukiwania w naszym interfejsie API sesji zgodnie z metodologią programowania opartego na testach (TDD), która polega na pisaniu najpierw przypadków testowych, powodowaniu ich niepowodzenia z powodu braku implementacji i używaniu Gemini Code Assist do generowania brakującej implementacji, aby test zakończył się powodzeniem.
Otwórz plik tests.py (zakładając, że plik tests.py zawiera wszystkie testy, które przechodzą). Zadaj Asystentowi kodu ten prompt:
Generate a new test case to search for sessions by speaker
Dzięki temu uzyskaliśmy implementację testu, którą wstawiliśmy do pliku 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]])
Jeśli uruchomisz testy, powinien pojawić się ten błąd:
$ 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)
Dzieje się tak, ponieważ przypadek testowy wywołał ścieżkę (/sessions/speakers/), która nie jest zaimplementowana w app.py.
Poprośmy Code Assist o podanie implementacji. Otwórz plik app.py i wpisz w Code Assist ten prompt:
Add a new route to search for sessions by a specific speaker
Asystent kodu zaproponował nam tę implementację, którą dodaliśmy do pliku 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)
Ponownie sprawdziliśmy plik tests.py i zmodyfikowaliśmy nasz przypadek testowy w ten sposób, aby szybko sprawdzić:
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)
Test został przeprowadzony prawidłowo. Pozostawiamy Ci sprawdzenie wygenerowanych elementów testowania, zmodyfikowanie ich w zależności od danych, które możesz mieć w Firestore, oraz zastosowanie odpowiednich metod assert* w elementach testowania jednostki Pythona.
14. Wdrażanie w Google Cloud Run
Teraz, gdy mamy pewność, że jakość naszego programowania jest odpowiednia, ostatnim krokiem będzie wdrożenie tej aplikacji w Google Cloud Run. Ale na wszelki wypadek zapytajmy Code Assist, czy o czymś nie zapomnieliśmy. Otwórz app.py i wpisz ten prompt :
Is there something here I should change before I deploy to production?
Dobrze, że o to pytasz, bo zapomnieliśmy wyłączyć flagę debugowania :

Zgodnie z instrukcjami wyłącz debugowanie i zapytaj Gemini Code Assist o pomoc w wykonaniu polecenia gcloud, które umożliwia wdrożenie aplikacji w Cloud Run bezpośrednio ze źródła (bez konieczności wcześniejszego tworzenia kontenera).
Wpisz ten prompt:
I would like to deploy the application to Cloud Run directly from source. What is the gcloud command to do that?
Wypróbuj kilka odmian powyższego prompta. Inny przykład, który wypróbowaliśmy:
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?
Powinno pojawić się to polecenie gcloud:
gcloud run deploy sessions --source .
Możesz też otrzymać:
gcloud run deploy <service-name> --source . \
—-platform managed \
—-allow-unauthenticated
Uruchom powyższe polecenie w folderze głównym aplikacji. Gdy pojawi się prośba o podanie region, wybierz us-central1, a gdy pojawi się prośba o zezwolenie na unauthenticated invocations, wybierz Y. Może też pojawić się prośba o włączenie interfejsów API Google Cloud, takich jak Artifact Registry, Cloud Build i Cloud Run, oraz o przyznanie uprawnień do tworzenia repozytorium Artifact Registry. W takim przypadku przyznaj te uprawnienia.
Proces wdrażania potrwa około 2 minut, więc zachowaj cierpliwość.
Po pomyślnym wdrożeniu zobaczysz adres URL usługi Cloud Run. Otwórz ten publiczny adres URL. Powinna się wyświetlić ta sama aplikacja internetowa, która została wdrożona i działa prawidłowo.

Gratulacje, świetna robota!
15. (Opcjonalnie) Korzystanie z Cloud Logging
Możemy wprowadzić w aplikacji rejestrowanie, tak aby logi aplikacji były scentralizowane w jednej z usług Google Cloud (Cloud Logging). Możemy też użyć funkcji Obserwacja w Gemini, aby zrozumieć wpisy w logach.
Aby to zrobić, musimy najpierw użyć istniejącej biblioteki Python Cloud Logging z Google Cloud i wykorzystać ją do rejestrowania komunikatów informacyjnych, ostrzegawczych lub o błędach (w zależności od dziennika lub poziomu ważności).
Spróbujmy najpierw zadać to pytanie usłudze Code Assist. Wypróbuj ten prompt:
How do I use the google-cloud-logging package in Python?
Powinna się wyświetlić odpowiedź z informacjami na ten temat, jak poniżej:

Dodajmy instrukcje logowania do funkcji, która wyszukuje sesje według kategorii.
Najpierw dodaj pakiet Pythona google-cloud-logging do pliku requirements.txt.
Poniżej znajdziesz fragment kodu, który pokazuje, jak zintegrowaliśmy kod, aby wdrożyć rejestrowanie:
...
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
Ponownie wdróż usługę w Cloud Run, używając tego samego polecenia co w poprzedniej sekcji. Po wdrożeniu wykonaj kilka wywołań punktu końcowego /sessions/categories/<category>.
Otwórz stronę Cloud Console → Logs Explorer.

…i powinno być możliwe filtrowanie tych instrukcji logowania, jak pokazano poniżej:

Możesz kliknąć dowolny wpis logu, rozwinąć go, a następnie kliknąć Explain this log entry, aby Gemini wyjaśnił wpis. Pamiętaj, że jeśli nie masz włączonej usługi Gemini w Google Cloud, pojawi się prośba o włączenie interfejsu Cloud AI Companion API. Wykonaj te czynności zgodnie z instrukcjami.
Przykładowa odpowiedź jest podana poniżej:

16. Gratulacje
Gratulacje! Udało Ci się utworzyć aplikację od podstaw i użyć Gemini Code Assist w wielu aspektach cyklu życia oprogramowania, w tym w projektowaniu, tworzeniu, testowaniu i wdrażaniu.
Co dalej?
Sprawdź te ćwiczenia z programowania:
- Przewodnik po Duet AI dla programistów
- Korzystanie z Duet AI w całym cyklu tworzenia oprogramowania
- Stylowe rozwiązania z Duet AI dla deweloperów