Ускорьте свой рабочий процесс разработки с помощью Gemini Code Assist.

1. Введение

e5b98fd4e417c877.png

В этой лаборатории кода вы увидите, как Gemini Code Assist может помочь вам на ключевых этапах жизненного цикла разработки программного обеспечения (SDLC), таких как проектирование, сборка, тестирование и развертывание. Мы спроектируем и разработаем целое приложение и развернем его в Google Cloud.

Мы будем создавать API и приложение для поиска между сеансами технического мероприятия. Каждая сессия будет иметь название, краткое содержание, продолжительность, категории и одного или нескольких докладчиков.

Что ты будешь делать

  • Проектирование, сборка, тестирование и развертывание веб-приложения на основе спецификации OpenAPI с нуля.

Что вы узнаете

  • Как использовать Gemini Code Assist для создания спецификации OpenAPI
  • Как использовать функции генерации кода Gemini Code Assist для разработки приложения Python Flask для спецификации OpenAPI.
  • Как использовать Gemini Code Assist для создания веб-интерфейса для приложения Python Flask
  • Как использовать Gemini Code Assist для получения помощи по развертыванию приложения в Google Cloud Run
  • Используйте функции Gemini Code Assist, такие как объяснение кода, создание тестовых примеров, при создании и тестировании приложения.

Что вам понадобится

  • Веб-браузер Chrome
  • Учетная запись Gmail
  • Облачный проект с включенной оплатой
  • Gemini Code Assist включен для вашего облачного проекта

Эта лабораторная работа ориентирована на разработчиков всех уровней, включая новичков. Хотя пример приложения написан на языке Python, вам не обязательно быть знакомым с программированием на Python, чтобы понять, что происходит. Наше внимание будет сосредоточено на ознакомлении с возможностями Gemini Code Assist.

2. Настройка помощника по коду Gemini

В этом разделе описано все, что вам нужно сделать, чтобы начать работу с этой лабораторной работой.

Включите Gemini Code Assist в Cloud Shell IDE

Для остальной части лаборатории кода мы будем использовать Cloud Shell IDE, полностью управляемую среду разработки на основе Code OSS . Нам нужно включить и настроить Code Assist в Cloud Shell IDE, шаги приведены ниже:

  1. Посетите ide.cloud.google.com . Для появления среды IDE может потребоваться некоторое время, поэтому наберитесь терпения и примите любые параметры настройки по умолчанию. Если вы видите какие-либо инструкции по настройке IDE, пожалуйста, выполните их с настройками по умолчанию.
  2. Нажмите кнопку Cloud Code — Войти в нижней строке состояния, как показано на рисунке. Авторизуйте плагин согласно инструкциям. Если в строке состояния вы видите «Cloud Code — нет проекта» , выберите его, а затем выберите конкретный проект Google Cloud из списка проектов, с которыми вы планируете работать.

6f5ce865fc7a3ef5.png

  1. Нажмите кнопку Code Assist в правом нижнем углу, как показано, и в последний раз выберите правильный проект Google Cloud. Если вас попросят включить Cloud AI Companion API , сделайте это и продолжайте.
  2. Выбрав проект Google Cloud, убедитесь, что вы видите это в сообщении о состоянии Cloud Code в строке состояния и что у вас также включен Code Assist справа в строке состояния, как показано ниже:

709e6c8248ac7d88.png

Gemini Code Assist готов к использованию!

3. Настройте Firestore

Cloud Firestore — это полностью управляемая бессерверная база данных документов, которую мы будем использовать в качестве серверной части для данных нашего приложения. Данные в Cloud Firestore структурированы в коллекции документов .

Нам нужно создать коллекцию с именем « sessions в нашей базе данных Firestore по умолчанию. Эта коллекция будет содержать образцы данных (документов), которые мы затем будем использовать в нашем приложении.

Откройте терминал из Cloud Shell IDE через главное меню, как показано ниже:

f1535e14c9beeec6.png

Нам нужно создать коллекцию с именем sessions . Здесь будет храниться список образцов документов сеанса. Каждый документ будет иметь следующие атрибуты:

  1. заголовок : строка
  2. категории : массив строк
  3. динамики : массив строк
  4. продолжительность : строка
  5. резюме : строка

Давайте заполним эту коллекцию образцами данных, скопировав файл, содержащий образцы данных, в корзину вашего собственного проекта, откуда вы затем сможете импортировать коллекцию с помощью команды gcloud firestore import .

Инициализация базы данных Firestore

Посетите страницу Firestore в облачной консоли.

Если вы еще не инициализировали базу данных Firestore в проекте, создайте базу данных default . При создании базы данных используйте следующие значения:

  • Режим Firestore: Native
  • Местоположение: выберите тип местоположения « Region и выберите регион, подходящий для вашего приложения. Запишите это местоположение, так как оно понадобится вам на следующем шаге для определения местоположения корзины.
  • Создайте базу данных.

504cabdb99a222a5.png

Теперь мы создадим коллекцию sessions , выполнив следующие шаги:

  1. Создайте корзину в своем проекте с помощью команды gsutil , приведенной ниже. Замените переменную <PROJECT_ID> в приведенной ниже команде идентификатором своего проекта Google Cloud. Замените <BUCKET_LOCATION> именем региона, соответствующим географической зоне вашей базы данных Firestore по умолчанию (как указано на предыдущем шаге), это может быть US-WEST1, EUROPE-WEST1, ASIA-EAST1:
gsutil mb -l <BUCKET-LOCATION> gs://<PROJECT_ID>-my-bucket
  1. Теперь, когда корзина создана, нам нужно скопировать подготовленный нами экспорт базы данных в эту корзину, прежде чем мы сможем импортировать ее в базу данных Firebase. Используйте команду, указанную ниже:
gsutil cp -r gs://sessions-master-database-bucket/2024-03-26T09:28:15_95256  gs://<PROJECT_ID>-my-bucket

Теперь, когда у нас есть данные для импорта, мы можем перейти к последнему этапу импорта данных в созданную нами базу данных Firebase ( default ).

  1. Используйте команду gcloud, приведенную ниже:
gcloud firestore import gs://<PROJECT_ID>-my-bucket/2024-03-26T09:28:15_95256

Импорт займет несколько секунд, и как только он будет готов, вы сможете проверить свою базу данных Firestore и коллекцию, посетив https://console.cloud.google.com/firestore/databases , выберите базу данных default и коллекцию sessions , как показано ниже. :

d3e294d46ba29cd5.png

На этом создание коллекции Firestore, которую мы будем использовать в нашем приложении, завершено.

4. Создайте шаблон приложения.

Мы создадим пример приложения (приложение Python Flask), которое будем использовать в остальной части лаборатории кода. Это приложение будет выполнять поиск по сессиям, предлагаемым на технической конференции.

Следуй этим шагам:

  1. Нажмите на название проекта Google Cloud в строке состояния ниже.

f151759c156c124e.png

  1. Появится список опций. Нажмите «Новое приложение» из списка ниже.

91ea9836f38b7f74.png

  1. Выберите приложение Cloud Run (это будет среда выполнения нашего приложения).
  2. Выберите шаблон приложения Python (Flask): Cloud Run .
  3. Дайте приложению имя и сохраните его в нужном вам месте.
  4. Уведомление подтверждает, что ваше приложение было создано, и открывается новое окно с загруженным приложением, как показано ниже. Откроется файл README.md . Вы можете закрыть это представление на данный момент.

ааа3725b17ce27cf.png

5. Взаимодействие с Gemini Code Assist

Для целей этой лабораторной работы мы будем использовать чат Gemini Code Assist Chat, доступный в Cloud Shell IDE как часть расширения Cloud Code в VS Code. Вы можете вызвать его, нажав кнопку Code Assist на левой панели навигации. Найдите значок «Помощник по коду». а489f98a34898727.png на левой панели инструментов навигации и щелкните по нему.

Откроется панель чата Code Assist в Cloud Shell IDE, и вы сможете общаться с Code Assist.

14ad103efaa0ddaa.png

Обратите внимание на значок корзины вверху — это ваш способ сбросить контекст истории чата Code Assist. Также обратите внимание, что это взаимодействие в чате является контекстным для файлов, над которыми вы работаете в IDE.

6. Дизайн API

Нашим первым шагом будет помощь Gemini Code Assist на этапе проектирования. На этом этапе мы создадим спецификацию OpenAPI для объектов (технических сеансов в событии), по которым мы хотим выполнить поиск.

Дайте следующую подсказку:

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.

Это должно создать спецификацию OpenAPI для поиска между сеансами с помощью различных параметров запроса. Образец спецификации приведен ниже:

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

Вы можете заметить, что в спецификации есть следующее:

  • Схема, определенная для типа сеанса .
  • Определено несколько путей API:
  • /sessions
  • /sessions/{id}
  • /sessions/categories/{category}

Создайте файл с именем sessionsapi.yaml в верхней папке и скопируйте содержимое из окна чата Code Assist, используя опцию «Вставить в текущий файл» (кнопка + ), и оставьте файл открытым в Cloud Shell IDE.

В этом месте можно отметить интересную особенность Gemini Code Assist: цитирование . Эта информация предоставляется разработчику, когда сгенерированный код напрямую цитируется из другого источника, например существующего открытого исходного кода. Он предлагает исходный код и лицензию, чтобы разработчик мог решить, что с ним делать.

Предполагая, что с сгенерированным контентом все в порядке, теперь мы можем использовать этот документ спецификации для создания для него приложения Python Flask.

7. Создайте приложение.

Теперь мы попросим Code Assist сгенерировать приложение. Введите следующую подсказку, открыв файл sessionsapi.yaml .

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.

Это должно предоставить вам скелет приложения Python Flask, основанный на функциях и путях, указанных в файле спецификации OpenAPI.

Предоставленный код приложения Python Flask должен быть похож на следующий:

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

Существует существующий файл app.py , созданный в рамках предыдущего шага. Просто замените его содержимое кодом, сгенерированным Code Assist, и сохраните файл.

Мы хотели бы изменить строку app.run() , чтобы она использовала порт 8080, адрес хоста 0.0.0.0, а также запускалась в режиме отладки во время локального выполнения. Вот способ сделать это. Прежде всего, давайте выделим/выберем строку:

app.run()

Затем в интерфейсе чата Code Assist введите приглашение: Explain this.

Это должно показать подробное объяснение этой конкретной строки, пример которой показан ниже:

58ec896a32a4fb68.png

Теперь используйте следующую подсказку:

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

Сгенерированный предлагаемый код должен быть следующим:

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

Не забудьте обновить файл app.py , добавив этот фрагмент.

Запустите приложение локально

Давайте теперь запустим приложение локально, чтобы проверить требования приложения в соответствии с тем, с чего мы начали.

Первым шагом будет создание виртуальной среды Python с зависимостями пакета Python в файле require.txt , который будет установлен в виртуальной среде. Для этого перейдите на палитру команд (Ctrl+Shift+P) в Cloud Shell IDE и введите « Создать среду Python» . Выполните следующие несколько шагов, чтобы выбрать виртуальную среду (venv) , интерпретатор Python 3.x и файл require.txt .

После создания среды запустите новое окно терминала (Ctrl+Shift+`) и введите следующую команду:

python app.py

Пример выполнения показан ниже:

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

Теперь вы можете просмотреть API по следующим URL-адресам. Мы предполагаем, что ваш сервер разработки работает на порту 8080. Если нет, измените его на соответствующий номер порта.

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

Выполните следующие действия, чтобы убедиться, что вы можете получить с помощью этих URL-адресов данные JSON, содержащиеся в файле app.py :

Откройте новое окно терминала и попробуйте любую из следующих команд:

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. Рефакторинг кода

Вместо того, чтобы app.py содержал жестко закодированные образцы данных JSON, мы, вероятно, хотели бы отделить/извлечь их в другой модуль, чтобы мы могли поддерживать четкое разделение между кодом и данными. Давайте сделаем это!

Оставьте файл app.py открытым и введите следующую подсказку:

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

Это должно дать вам несколько советов о том, как это сделать. Пример предложения, которое мы получили и вы должны получить что-то похожее на него, показан ниже:

9b9c56cb527dac4c.png

Давайте последуем этому и выделим наши данные в файл sessions.py , как предлагает Code Assist.

Создайте новый файл с именем sessions.py

, содержимым которого является список JSON, согласно нашим сгенерированным данным, приведено ниже:

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.py теперь значительно упрощен и показан ниже:

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)

Убедитесь, что вы по-прежнему можете запускать приложение локально и использовать API с этими рефакторингованными изменениями. Сервер разработки Python, скорее всего, все еще работает, поэтому вам нужно только вызвать команды curl из предыдущего шага.

9. Интеграция с коллекцией Firestore.

Следующий шаг — отойти от локального списка JSON в памяти, который у нас есть для наших сеансов, и подключить наше приложение к коллекции сеансов в базе данных Firestore, которую мы создали в начале этой лаборатории кода.

Оставьте файл sessions.py открытым и введите следующую подсказку:

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. 

Мы получили следующее предложение прочитать все сессии из коллекции 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)

Включите код в sessions.py .

Если у вас локально работает сервер разработки Flask, ваше приложение могло закрыться с жалобой на то, что модуль Python не найден.

Например, вы можете спросить Code Assist о том, какой модуль Python необходимо добавить в файл requirements.txt , следующим образом:

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

Это предоставит вам имя модуля Python (например, google-cloud-firestore ). Добавьте это в файл requirements.txt .

Вам нужно будет воссоздать среду Python с помощью недавно добавленного модуля ( google-cloud-firestore ). Для этого введите следующую команду в существующем окне терминала:

pip install -r requirements.txt

Запустите приложение еще раз (перезапустите его с помощью python app.py ) и посетите URL-адрес /sessions . Теперь вы должны получить образцы документов, которые мы добавили в коллекцию sessions .

975d05e6518f1a6a.png

Не стесняйтесь запрашивать другие URI для получения определенных сеансов или всех сеансов для данной категории, как описано в предыдущих шагах.

10. Объяснение кода

Сейчас самое время использовать функцию "Explain this" Gemini Code Assist, чтобы лучше понять код. Не стесняйтесь заходить в любой из файлов или выбирать конкретные фрагменты кода и задавать Code Assist следующую подсказку: Explain this .

В качестве упражнения посетите файл sessions.py , выделите специальный код Firestore и получите пояснения к нему. Попробуйте также использовать эту функцию для других файлов вашего проекта, а не только для кода Python.

11. Создайте веб-приложение

Теперь, когда мы создали API и интегрировали его с активной коллекцией Firestore, давайте создадим веб-интерфейс для приложения. Функциональность нашего веб-интерфейса в настоящее время будет сведена к минимуму, т. е. будет иметь возможность искать сеансы, принадлежащие к определенной категории. Имейте в виду, что у нас есть путь к API для этого, то есть /sessions/categories/{category} поэтому наше веб-приложение должно вызывать его и получать результаты.

Давайте погрузимся прямо в это. Введите следующую подсказку 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.

Это создаст HTML-код веб-приложения со встроенными в него JavaScript и CSS. Он также попросит вас добавить новый маршрут в файл app.py , чтобы любой пользователь, посещающий корневой или базовый URL-адрес, получал домашнюю страницу. Если эта информация не упоминается, спросите об этом или используйте фрагмент, приведенный ниже:

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

Вы можете сохранить это как index.html , но у вас может возникнуть вопрос, где этот файл следует сохранить (т. е. в какой папке?). Мы можем задать дополнительный вопрос Code Assist.

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

Он должен дать вам четкую информацию о том, что он использует платформу render_template , и, следовательно, файл index.html необходимо будет поместить в папку templates . Вы найдете эту папку доступной, поскольку в начале этой лаборатории кода мы создали приложение на основе шаблона Flask. В результате имеется существующий файл index.html , и вам следует просто заменить его содержимое новым, созданным здесь. Code Assist также упоминает об импорте render_template в файл app.py

Сохраните код веб-приложения в файле index.html и не забудьте поместить этот файл в папку templates .

Запустите приложение локально

Давайте теперь запустим приложение локально, чтобы проверить требования приложения в соответствии с тем, с чего мы начали.

Убедитесь, что локальный сервер Flask все еще работает и не показывает никаких ошибок. В случае ошибок устраните их и запустите сервер.

После запуска посетите домашний URL-адрес приложения. Он должен показать вам файл index.html , как показано ниже:

8ca586acc4536879.png

Укажите одну из категорий данных в качестве входных данных (например, AI ) и нажмите кнопку Search . Должны отображаться сеансы, помеченные категорией AI .

165faded790a6c.png

Необязательное упражнение — показать дополнительные метаданные, такие как продолжительность, категории, докладчики и резюме для каждого сеанса.

12. Генерация тестового примера

Мы создали API сеансов, и теперь пришло время использовать Gemini Code Assist для создания случаев модульного тестирования для различных путей API.

Оставьте файл app.py открытым и введите следующую подсказку:

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

Мы получили следующий ответ:

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

Создайте файл с tests.py с приведенным выше кодом.

Примечание о создании тестовых примеров

Вы можете увидеть листинг кода, отличный от приведенного выше, и это может вызвать некоторые проблемы при запуске тестовых случаев. Например, мы увидели, что в некоторых наших запусках были пропущены следующие ключевые фрагменты кода:

from app import app

Приведенный выше код необходим для импорта существующего приложения Flask, для которого мы будем запускать тестовые примеры.

if __name__ == '__main__':

`unittest.main()`

Приведенный выше код необходим для запуска тестовых случаев.

Мы рекомендуем просмотреть каждый тестовый пример, проверить assertEqual и другие условия в сгенерированном коде, чтобы убедиться, что он будет работать. Поскольку данные являются внешними в коллекции Firestore, у него может не быть к ним доступа, и они могут использовать некоторые фиктивные данные, в результате чего тесты могут завершиться неудачно. Поэтому измените свои тестовые примеры соответствующим образом или закомментируйте некоторые тестовые примеры, которые могут вам не понадобиться в данный момент.

В качестве демонстрации мы запустили тестовые примеры с помощью следующей команды (обязательно запустите локальный сервер разработки, поскольку вызовы будут осуществляться к локальным конечным точкам API):

python tests.py

Мы получили следующий итоговый результат:

Ran 4 tests in 0.274s

FAILED (failures=2)

Это действительно правильно, поскольку идентификатор сеанса был неверным в третьем тесте и нет категории с именем category1

.

Поэтому скорректируйте тестовые примеры соответствующим образом и протестируйте их.

13. Разработка через тестирование

Давайте теперь посмотрим на добавление нового метода поиска в API наших сессий в соответствии с методологией разработки через тестирование (TDD), которая заключается в том, чтобы сначала написать тестовые примеры, сделать их неудачными из-за отсутствия реализации и использовать Gemini Code Assist для создания недостающих реализацию, чтобы тест прошел.

Перейдите к файлуtest.py (при условии, что вы исправили tests.py , чтобы все тесты прошли успешно). Спросить код Помогите, выполнив следующую подсказку:

Generate a new test case to search for sessions by speaker

Это дало нам следующую реализацию тестового примера, которую мы должным образом вставили в 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]])

Если вы запустите тесты, вы должны увидеть следующую ошибку:

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

Это связано с тем, что тестовый пример вызвал следующий путь ( /sessions/speakers/ ) и в app.py он не реализован.

Давайте попросим Code Assist предоставить нам реализацию. Перейдите к файлу app.py и дайте Code Assist следующую подсказку:

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

Мы получили следующую реализацию, предложенную Code Assist, которую мы добавили в файл 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)

Вернитесь к tests.py , и мы изменили наш тестовый пример для быстрой проверки следующим образом:

   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)

Тест прошел нормально. Мы оставляем это в качестве упражнения, чтобы вы могли просмотреть сгенерированные тестовые примеры, немного настроить их в зависимости от данных, которые у вас могут быть в Firestore, и использовать соответствующие методы assert* в случаях модульного тестирования Python.

14. Развертывание в Google Cloud Run

Теперь, когда мы уверены в качестве нашей разработки, нашим последним шагом будет развертывание этого приложения в Google Cloud Run. Но, возможно, для проверки нам следует спросить Code Assist, не забыли ли мы что-нибудь. Открыв app.py , отправьте следующее приглашение:

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

Хорошо, что вы спросили, поскольку мы действительно забыли отключить флаг отладки:

2f87ed3a811fb218.png

Как указано, отключите отладку и обратитесь к Gemini Code Assist за помощью с командой gcloud , которую можно использовать для развертывания приложения в Cloud Run непосредственно из исходного кода (без необходимости предварительной сборки контейнера).

Дайте следующую подсказку:

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

Попробуйте несколько вариантов приведенной выше подсказки. Еще один, который мы попробовали, был:

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?

В идеале вы должны получить следующую команду gcloud :

gcloud run deploy sessions --source .

Вы также можете получить:

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

Выполните указанную выше команду из корневой папки приложения. Когда вас спросят о region , выберите us-central1 , а когда вас спросят о разрешении unauthenticated invocations , выберите Y Вас также могут попросить включить Google Cloud API, такие как Artifact Registry, Cloud Build и Cloud Run, а также разрешение на создание репозитория Artifact Registry. Пожалуйста, дайте разрешение.

Процесс развертывания займет около 2 минут, поэтому наберитесь терпения.

После успешного развертывания вы увидите URL-адрес службы Cloud Run. Посетите этот общедоступный URL-адрес, и вы увидите, что то же самое веб-приложение развернуто и успешно работает.

c5322d0fd3e0f616.png

Поздравляю, молодец!

15. (Необязательно) Используйте облачную регистрацию.

Мы можем ввести ведение журнала в нашем приложении, чтобы журналы приложений были централизованы в одном из облачных сервисов Google (Cloud Logging). Затем мы можем использовать функцию Observability Gemini, чтобы получить представление о записях журнала.

Для этого нам сначала нужно будет использовать существующую библиотеку Python Cloud Logging из Google Cloud и использовать ее для регистрации информационных сообщений, предупреждений или сообщений об ошибках (в зависимости от уровня журнала/серьезности).

Давайте сначала попробуем задать этот вопрос Code Assist. Попробуйте следующую подсказку:

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

Вы должны получить ответ, содержащий некоторую информацию по этому вопросу, как показано ниже:

2472e1ccaf8a217d.png

Давайте добавим операторы журналирования в функцию, которая ищет сеансы по категориям.

Сначала добавьте пакет Python google-cloud-logging в файл requirements.txt .

Далее следует фрагмент кода, показывающий, как мы интегрировали код для реализации ведения журналов:

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

Снова разверните службу в Cloud Run, используя ту же команду, что и в предыдущем разделе, и после развертывания выполните несколько вызовов конечной точки /sessions/categories/<category> .

Перейдите в Cloud Console → Logs Explorer

59e297577570695.png

... и вы сможете фильтровать эти операторы журналирования, как показано ниже:

914f1fb6cac30a89.png

Вы можете нажать на любой оператор журнала, развернуть его и затем нажать Explain this log entry , при этом Gemini будет использовать Gemini для объяснения записи журнала. Обратите внимание: если вы не включили Gemini для Google Cloud, вам будет предложено включить Cloud AI Companion API. Пожалуйста, продолжайте и делайте это в соответствии с инструкциями.

Пример ответа приведен ниже:

7fc9783910fa92cc.png

16. Поздравления

Поздравляем, вы успешно создали приложение с нуля и использовали Gemini Code Assist для различных аспектов SDLC, включая проектирование, сборку, тестирование и развертывание.

Что дальше?

Посмотрите некоторые из этих кодовых лабораторий...

Справочная документация