1. Introdução

Neste codelab, você vai aprender como o Gemini Code Assist pode ajudar nas principais etapas do ciclo de vida de desenvolvimento de software (SDLC, na sigla em inglês), como design, criação e teste, além de implantação. Vamos projetar e desenvolver um aplicativo inteiro e implantá-lo no Google Cloud.
Vamos criar uma API e um aplicativo para pesquisar em sessões de um evento técnico. Cada sessão terá um título, um resumo, uma duração, categorias e um ou mais palestrantes.
O que você aprenderá
- Projetar, criar, testar e implantar um aplicativo da Web com base em uma especificação OpenAPI do zero
O que você vai aprender
- Como usar o Gemini Code Assist para gerar uma especificação OpenAPI
- Como usar os recursos de geração de código do Gemini Code Assist para desenvolver um aplicativo Python Flask para a especificação OpenAPI
- Como usar o Gemini Code Assist para gerar um front-end da Web para o aplicativo Python Flask
- Como usar o Gemini Code Assist para receber ajuda sobre como implantar o aplicativo no Google Cloud Run
- Use os recursos do Gemini Code Assist, como explicação de código e geração de casos de teste, ao criar e testar o aplicativo
O que é necessário
- Navegador da Web Google Chrome
- Uma conta do Gmail
- Um projeto do Cloud com faturamento ativado
- O Gemini Code Assist está ativado para seu projeto do Cloud
Este laboratório é voltado para desenvolvedores com todos os níveis de conhecimento, inclusive iniciantes. O aplicativo de amostra está na linguagem Python, mas você não precisa conhecer esse tipo de programação para entender o que está acontecendo. Nosso foco será apresentar os recursos do Gemini Code Assist.
2. Configurar o Gemini Code Assist
Nesta seção, você vai encontrar tudo o que precisa fazer para começar o laboratório.
Ativar o Gemini Code Assist no Cloud Shell IDE
Vamos usar o Cloud Shell IDE, um ambiente de desenvolvimento totalmente gerenciado baseado no Code OSS, no restante do codelab. É necessário ativar e configurar o Code Assist no Cloud Shell IDE. Siga as etapas abaixo:
- Acesse ide.cloud.google.com. Pode levar um tempo para o ambiente de desenvolvimento integrado aparecer. Aguarde e aceite as opções padrão de configuração. Se você encontrar instruções sobre como configurar o ambiente de desenvolvimento integrado, siga em frente e conclua essas etapas com as configurações padrão.
- Clique no botão Cloud Code – Fazer login na barra de status inferior, conforme mostrado. Autorize o plug-in conforme instruído. Se a barra de status mostrar Cloud Code – sem projeto, clique na opção e escolha o projeto do Google Cloud com que você quer trabalhar na lista.

- Clique no botão Code Assist no canto inferior direito, conforme mostrado, e selecione o projeto correto do Google Cloud pela última vez. Se for necessário ativar a API IA do Google Cloud Companion, faça isso e continue.
- Depois de selecionar o projeto na nuvem do Google Cloud, confira se a mensagem de status do Cloud Code aparece na barra de status. Analise também se o Code Assist está ativado à direita, na barra de status, conforme mostrado abaixo:

O Gemini Code Assist está pronto para uso.
3. Configurar o Firestore
O Cloud Firestore é um banco de dados de documentos sem servidor totalmente gerenciado que usaremos como back-end para os dados do aplicativo. Os dados no Cloud Firestore são estruturados em coleções de documentos.
Precisamos criar uma coleção chamada sessions no nosso banco de dados padrão do Firestore. Essa coleção vai conter dados de amostra (documentos) que serão usados no aplicativo.
Abra o Terminal no Cloud Shell IDE pelo menu principal, como mostrado abaixo:

Precisamos criar uma coleção chamada sessions. Isso vai conter uma lista de documentos de sessão de exemplo. Cada documento terá os seguintes atributos:
- title: string
- categories: matriz de strings
- speakers: matriz de strings
- duration: string
- summary: string
Vamos preencher essa coleção com dados de amostra copiando um arquivo que contém os dados de amostra para um bucket no seu projeto, de onde você pode importar a coleção usando o comando gcloud firestore import.
Inicialização do banco de dados do Firestore
Acesse a página do Firestore no console do Cloud.
Se você nunca inicializou um banco de dados do Firestore no projeto, crie o banco de dados default. Durante a criação do banco de dados, use os seguintes valores:
- Modo do Firestore:
Native - Local: escolha o tipo de local como
Regione selecione a região adequada para seu aplicativo. Anote esse local, porque você vai precisar dele na próxima etapa para o local do bucket. - Crie o banco de dados.

Agora vamos criar a coleção sessions seguindo as etapas abaixo:
- Crie um bucket no seu projeto com o comando
gsutilabaixo. Substitua a variável<PROJECT_ID>no comando abaixo pelo ID do seu projeto do Google Cloud. Substitua<BUCKET_LOCATION>por um nome de região que corresponda à área geográfica do seu banco de dados padrão do Firestore (conforme observado na etapa anterior). Pode ser US-WEST1, EUROPE-WEST1, ASIA-EAST1 :
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
- Agora que o bucket foi criado, precisamos copiar a exportação do banco de dados que preparamos para ele antes de importar para o banco de dados do Firebase. Use o comando abaixo:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256 gs://<PROJECT_ID>-my-bucket
Agora que temos os dados para importar, podemos passar para a etapa final de importação para o banco de dados do Firebase (default) que criamos.
- Use o comando gcloud abaixo:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256
A importação leva alguns segundos. Depois que ela estiver pronta, você poderá validar seu banco de dados e a coleção do Firestore acessando https://console.cloud.google.com/firestore/databases, selecionando o banco de dados default e a coleção sessions, conforme mostrado abaixo:

Isso conclui a criação da coleção do Firestore que vamos usar no aplicativo.
4. Criar o modelo de aplicativo
Vamos criar um aplicativo de amostra (Python Flask) para usar no restante do codelab. Esse aplicativo vai pesquisar em todas as sessões oferecidas em uma conferência técnica.
Siga estas etapas:
- Clique no nome do projeto do Google Cloud na barra de status abaixo.

- Uma lista de opções vai aparecer. Clique em Novo aplicativo na lista abaixo.

- Selecione Aplicativo do Cloud Run (será o ambiente de execução do nosso app).
- Selecione o modelo de aplicativo Python (Flask): Cloud Run.
- Dê um nome ao aplicativo e salve no local de sua preferência.
- Uma notificação confirma que o aplicativo foi criado. Além disso, uma nova janela é aberta com o aplicativo carregado, conforme mostrado abaixo. Um arquivo
README.mdé aberto. Por enquanto, você pode fechar essa visualização.

5. Interação com o Gemini Code Assist
Para este laboratório, vamos usar o chat do Gemini Code Assist disponível no Cloud Shell IDE como parte da extensão do Cloud Code no VS Code. Para acessar, clique no botão "Assistente de programação" na barra de navegação à esquerda. Procure e clique no ícone
do Code Assist na barra de ferramentas de navegação à esquerda.
Assim você abre o painel de chat do Code Assist no Cloud Shell IDE e pode conversar com ele.

Observe o ícone de lixeira na parte de cima. É assim que você redefine o contexto do histórico de conversas do Code Assist. Essa conversa por chat é contextual aos arquivos em que você está trabalhando no ambiente de desenvolvimento integrado.
6. Design de API
Nossa primeira etapa será usar a assistência do Gemini Code Assist durante a fase de design. Nesta etapa, vamos gerar uma especificação OpenAPI para as entidades (sessões técnicas em um evento) que queremos pesquisar.
Dê o seguinte comando:
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.
Isso vai gerar uma especificação OpenAPI para pesquisar em sessões usando vários parâmetros de consulta. Confira abaixo um exemplo de especificação:
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
Você pode notar que a especificação tem o seguinte:
- Um esquema definido para o tipo de sessão.
- Vários caminhos de API definidos:
/sessions/sessions/{id}/sessions/categories/{category}
Crie um arquivo chamado sessionsapi.yaml na pasta principal e copie o conteúdo da janela de chat do Code Assist usando a opção "Inserir no arquivo atual" (botão +). Mantenha o arquivo aberto no Cloud Shell IDE.
Neste ponto, você pode notar um recurso interessante do Gemini Code Assist: citação. Essas informações são apresentadas ao desenvolvedor quando o código gerado extrai um grande trecho de outra fonte, como um código-fonte aberto. Ela oferece a fonte e a licença para o desenvolvedor decidir o que fazer com ela.
Supondo que o conteúdo gerado esteja bom, agora podemos usar esse documento de especificação para gerar um aplicativo Python Flask.
7. Gerar o aplicativo
Agora vamos pedir ao Code Assist para gerar o aplicativo. Dê o seguinte comando com o arquivo sessionsapi.yaml aberto.
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.
Isso vai fornecer um esqueleto para o aplicativo Python Flask com base na funcionalidade e nos caminhos especificados no arquivo de especificação OpenAPI.
O código do aplicativo Python Flask fornecido deve ser semelhante a este:
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()
Há um arquivo app.py gerado como parte da etapa anterior. Basta substituir o conteúdo pelo código gerado pelo Code Assist e salvar o arquivo.
Queremos mudar a linha app.run() para usar a porta 8080, o endereço do host 0.0.0.0 e também executar no modo de depuração durante a execução local.Veja como fazer isso. Primeiro, vamos destacar/selecionar a linha:
app.run()
Em seguida, na interface do chat do Code Assist, digite o comando: Explain this.
Isso vai mostrar uma explicação detalhada dessa linha específica, como no exemplo abaixo:

Agora, use o seguinte comando:
update the code to run the application on port 8080, host address 0.0.0.0, and in debug mode
O código sugerido gerado deve ser este:
app.run(host='0.0.0.0', port=8080, debug=True)
Não se esqueça de atualizar o arquivo app.py com esse snippet.
Executar o aplicativo localmente
Vamos executar o aplicativo localmente agora para validar os requisitos dele, conforme o que tínhamos começado.
A primeira etapa é criar um ambiente virtual do Python com as dependências de pacote do Python em requirements.txt para serem instaladas no ambiente virtual. Para fazer isso, acesse a Paleta de comandos (Ctrl+Shift+P) no Cloud Shell IDE e digite Criar ambiente Python. Siga as próximas etapas para selecionar um ambiente virtual (venv), um interpretador Python 3.x e o arquivo requirements.txt.
Depois que o ambiente for criado, abra uma nova janela do terminal (Ctrl+Shift+`) e execute o seguinte comando:
python app.py
Confira um exemplo de execução abaixo:
(.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
Agora você pode visualizar a API nos seguintes URLs. Estamos supondo que o servidor de desenvolvimento está sendo executado na porta 8080. Se não for, mude para o número da porta adequado.
https://<host-name>:8080/sessionshttps://<host-name>:8080/sessions/{id}https://<host-name>:8080/sessions/categories/{category}
Siga as etapas abaixo para garantir que você consiga recuperar usando esses URLs os dados JSON contidos no arquivo app.py:
Abra uma nova janela de terminal e tente um dos seguintes comandos:
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. Refatoração de código
Em vez de fazer com que app.py contenha os dados JSON de amostra codificados, provavelmente vamos querer separar/extrair isso em outro módulo para manter uma separação limpa entre o código e os dados. Vamos fazer isso!
Mantenha o arquivo app.py aberto e dê o seguinte comando:
Can I improve this code and separate out the sessions data from this app.py file?
Isso vai dar algumas sugestões de como fazer isso. Confira abaixo um exemplo de sugestão que recebemos e que você também pode receber:

Vamos seguir essa sugestão e separar nossos dados em um arquivo sessions.py, conforme sugerido pelo Code Assist.
Crie um arquivo chamado sessions.py.
, cujo conteúdo é a lista JSON, conforme nossos dados gerados abaixo:
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",
},
]
O arquivo app.py agora está muito mais simples e é mostrado abaixo:
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)
Verifique se ainda é possível executar o aplicativo localmente e testar a API com essas mudanças refatoradas. O servidor de desenvolvimento Python provavelmente ainda está em execução. Portanto, basta lembrar os comandos curl da etapa anterior.
9. Integrar com a coleção do Firestore
A próxima etapa é deixar de usar a lista JSON local na memória que temos para nossas sessões e conectar o aplicativo à coleção sessions no banco de dados do Firestore, que criamos no início deste codelab.
Mantenha o arquivo sessions.py aberto e dê o seguinte comando:
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.
Recebemos a seguinte sugestão para ler todas as sessões da coleção do 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)
Incorpore o código em sessions.py.
Se você tiver o servidor de desenvolvimento do Flask em execução localmente, talvez o aplicativo tenha sido fechado informando que o módulo Python não foi encontrado.
Por exemplo, você pode perguntar ao Code Assist qual módulo do Python precisa ser adicionado ao arquivo requirements.txt, da seguinte maneira:
Which Python package needs to be installed to make the firestore code work?
Isso vai fornecer o nome do módulo Python (por exemplo, google-cloud-firestore). Adicione-o ao arquivo requirements.txt.
Será necessário recriar o ambiente Python com o módulo recém-adicionado (google-cloud-firestore). Para isso, execute o seguinte comando na janela de terminal aberta:
pip install -r requirements.txt
Execute o aplicativo novamente (reinicie com python app.py) e acesse o URL /sessions. Agora você vai receber os documentos de amostra que adicionamos à coleção sessions.

Consulte outros URIs para recuperar sessões específicas ou todas as sessões de uma determinada categoria, conforme descrito nas etapas anteriores.
10. Explicação de código
Agora é um bom momento para usar o recurso "Explain this" do Gemini Code Assist e entender melhor o código. Abra qualquer um dos arquivos ou selecione snippets de código específicos e peça ajuda ao Code Assist com o seguinte comando: Explain this.
Como exercício, acesse o arquivo sessions.py, destaque o código específico do Firestore e receba uma explicação sobre ele. Tente usar esse recurso em outros arquivos do projeto, não apenas em código Python.
11. Gerar o aplicativo da Web
Agora que geramos a API e a integramos a uma coleção ativa do Firestore, vamos gerar um front-end baseado na Web para o aplicativo. No momento, nosso front-end da Web vai manter a funcionalidade no mínimo, ou seja, será possível pesquisar sessões que pertencem a uma categoria específica. Temos um caminho de API para isso, ou seja, /sessions/categories/{category}. Portanto, nosso aplicativo da Web precisa invocar esse caminho e recuperar os resultados.
Vamos começar. Dê o seguinte comando ao 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.
Isso vai gerar o HTML do aplicativo da Web com o JavaScript e o CSS incorporados. Ele também vai pedir para você adicionar uma nova rota ao arquivo app.py para que qualquer usuário que acesse o URL raiz ou de base receba a página inicial. Se não mencionar, pergunte ou use o trecho abaixo:
@app.route('/')
def index():
return render_template('index.html')
Você pode salvar como index.html, mas talvez tenha uma dúvida sobre onde esse arquivo deve ser salvo (ou seja, em qual pasta?). Podemos fazer uma pergunta complementar ao Code Assist.
Given that I am using the flask framework, where should I put the index.html file?
Ele vai fornecer informações claras de que usa o framework render_template e, portanto, o arquivo index.html precisa ser colocado na pasta templates. Essa pasta está disponível porque geramos um aplicativo com base no modelo do Flask no início deste codelab. Como resultado, há um arquivo index.html e você só precisa substituir o conteúdo dele pelo novo que foi gerado aqui. O Code Assist também menciona a importação de render_template no arquivo app.py.
Salve o código do aplicativo da Web no arquivo index.html e coloque esse arquivo na pasta templates.
Executar o aplicativo localmente
Vamos executar o aplicativo localmente agora para validar os requisitos dele, conforme o que tínhamos começado.
Verifique se o servidor Flask local ainda está em execução e não mostra erros. Se houver erros, corrija-os e inicie o servidor.
Depois que ele estiver funcionando, acesse o URL da página inicial do aplicativo. Ele vai mostrar o arquivo index.html veiculado, como mostrado abaixo:

Forneça uma das categorias dos dados como entrada (por exemplo, AI) e clique no botão Search. Isso vai mostrar as sessões marcadas com a categoria AI.

Um exercício opcional é mostrar metadados adicionais, como duração, categorias, palestrantes e resumo de cada sessão.
12. Geração de caso de teste
Geramos a API de sessões e agora é hora de usar o Gemini Code Assist para gerar casos de teste de unidade para os diferentes caminhos da API.
Mantenha o arquivo app.py aberto e dê o seguinte comando:
Generate unit test cases for app routes. Use unittest module.
Recebemos a seguinte resposta:
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()
Crie um arquivo chamado tests.py com o código acima.
Observação sobre a geração de casos de teste
Você pode ver uma lista de códigos diferente da acima, o que pode causar alguns problemas na execução dos casos de teste. Por exemplo, percebemos que, em algumas das nossas execuções, as seguintes partes principais do código foram omitidas:
from app import app
O código acima é necessário para importar o app Flask atual em que vamos invocar os casos de teste.
if __name__ == '__main__':
`unittest.main()`
O código acima é necessário para executar os casos de teste.
Recomendamos analisar cada caso de teste, verificar o assertEqual e outras condições no código gerado para garantir que ele funcione. Como os dados são externos na coleção do Firestore, talvez não haja acesso a eles, e alguns dados fictícios podem ser usados. Como resultado, os testes podem falhar. Modifique seus casos de teste de acordo ou comente alguns deles que você não precisa imediatamente.
Como demonstração, executamos os casos de teste usando o seguinte comando. Não se esqueça de executar o servidor de desenvolvimento local, já que as chamadas serão feitas para os endpoints da API local:
python tests.py
Recebemos o seguinte resultado de resumo:
Ran 4 tests in 0.274s
FAILED (failures=2)
Isso está correto, já que o ID da sessão não estava correto no terceiro teste e não há uma categoria chamada category1.
.
Ajuste os casos de teste de acordo e teste.
13. Desenvolvimento orientado a testes
Agora vamos adicionar um novo método de pesquisa à API Sessions seguindo a metodologia de desenvolvimento orientado a testes (TDD), que consiste em escrever casos de teste primeiro, fazer com que eles falhem devido à falta de implementação e usar o Gemini Code Assist para gerar a implementação ausente para que o teste seja aprovado.
Acesse o arquivo tests.py (supondo que você tenha corrigido o arquivo tests.py para ter todos os testes aprovados). Faça o seguinte comando para o Code Assist:
Generate a new test case to search for sessions by speaker
Isso nos deu a seguinte implementação de caso de teste, que inserimos no arquivo 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 você executar os testes, vai aparecer o seguinte erro:
$ 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)
Isso ocorre porque o caso de teste invocou o seguinte caminho (/sessions/speakers/), e não há implementação dele em app.py.
Vamos pedir ao Code Assist para fornecer uma implementação. Acesse o arquivo app.py e dê o seguinte comando ao Code Assist:
Add a new route to search for sessions by a specific speaker
Recebemos a seguinte implementação sugerida pelo Code Assist, que adicionamos ao arquivo 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)
Revisite o arquivo tests.py e modifique o caso de teste da seguinte maneira para uma verificação rápida:
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)
O teste foi executado sem problemas. Deixamos como exercício para você analisar os casos de teste gerados, ajustar um pouco dependendo dos dados que você pode ter no Firestore e ter os métodos assert* adequados nos casos de teste de unidade do Python.
14. Como implantar no Google Cloud Run
Agora que estamos satisfeitos com a qualidade do nosso desenvolvimento, a etapa final é implantar esse aplicativo no Google Cloud Run. Mas, por precaução, vamos perguntar ao Code Assist se esquecemos de algo. Com o app.py aberto, envie o seguinte comando :
Is there something here I should change before I deploy to production?
Ainda bem que você perguntou, porque esquecemos de desativar a flag de depuração :

Conforme indicado, desative a depuração e peça ajuda ao Gemini Code Assist com o comando gcloud, que pode ser usado para implantar o aplicativo no Cloud Run diretamente da origem, sem precisar criar um contêiner primeiro.
Dê o seguinte comando:
I would like to deploy the application to Cloud Run directly from source. What is the gcloud command to do that?
Teste algumas variações do comando acima. Outra tentativa foi:
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?
O ideal é que você receba o seguinte comando gcloud:
gcloud run deploy sessions --source .
Você também pode receber:
gcloud run deploy <service-name> --source . \
—-platform managed \
—-allow-unauthenticated
Execute o comando acima na pasta raiz do aplicativo. Quando for solicitado o region, selecione us-central1 e, quando for solicitado para permitir o unauthenticated invocations, escolha Y. Talvez seja necessário ativar as APIs do Google Cloud, como Artifact Registry, Cloud Build e Cloud Run, e dar permissão para criar um repositório do Artifact Registry.
O processo de implantação leva cerca de 2 minutos. Aguarde.
Depois da implantação, o URL do serviço do Cloud Run vai aparecer. Acesse esse URL público para ver o mesmo aplicativo da Web implantado e em execução.

Parabéns, você fez um ótimo trabalho!
15. (Opcional) Usar o Cloud Logging
Podemos introduzir o registro em nosso aplicativo para que os registros sejam centralizados em um dos serviços do Google Cloud (Cloud Logging). Em seguida, podemos usar o recurso Gemini de observabilidade para entender as entradas de registro também.
Para isso, primeiro vamos usar uma biblioteca Python do Cloud Logging do Google Cloud e usá-la para registrar mensagens informativas, de aviso ou de erro (dependendo do nível de registro / gravidade).
Vamos tentar perguntar isso primeiro ao Code Assist. Tente o seguinte comando:
How do I use the google-cloud-logging package in Python?
Você vai receber uma resposta com algumas informações sobre ele, como mostrado abaixo:

Vamos adicionar instruções de registro à função que pesquisa sessões por categoria.
Primeiro, adicione o pacote Python google-cloud-logging ao arquivo requirements.txt.
Em seguida, um snippet de código mostra como integramos o código para implementar o registro em log:
...
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
Implante o serviço no Cloud Run novamente usando o mesmo comando da seção anterior e, depois da implantação, execute algumas chamadas para o endpoint /sessions/categories/<category>.
Acesse o Cloud Console → Logs Explorer

...e você poderá filtrar essas instruções de registro em log, conforme mostrado abaixo:

Clique em qualquer uma das instruções de registro, expanda e clique em Explain this log entry, que vai usar o Gemini para explicar a entrada de registro. Se você não tiver ativado o Gemini para Google Cloud, será necessário ativar a API IA do Google Cloud Companion. Faça isso conforme as instruções.
Confira um exemplo de resposta:

16. Parabéns
Parabéns! Você criou um aplicativo do zero e usou o Gemini Code Assist em vários aspectos do SDLC, incluindo design, build, teste e implantação.
Qual é a próxima etapa?
Confira alguns destes codelabs:
- Um tour pela Duet AI para desenvolvedores
- Como usar a Duet AI durante todo o ciclo de vida de desenvolvimento de software
- Como ter estilo com a Duet AI para desenvolvedores