Codelab: Mit Gemini die testgesteuerte Entwicklung beschleunigen

1. Einführung

In diesem Codelab werden die Grundlagen der testgetriebenen Entwicklung ( Test-Driven Development, TDD) vorgestellt, bei der Sie Tests schreiben, bevor Sie Code implementieren. Wir erstellen eine einfache Taschenrechner-App mit Ruby, um diesen Ansatz zu veranschaulichen.

Außerdem erfahren Sie, wie Sie Gemini als Programmierassistenten verwenden. Gemini kann den TDD-Zyklus beschleunigen, indem es Testläufe generiert, Codeimplementierungen vorschlägt und sogar Erklärungen für den Code liefert.

Schließlich erfahren Sie, wie Sie die Taschenrechner-App in Cloud Functions bereitstellen, der vollständig verwalteten serverlosen Plattform von Google, damit Ihre App zugänglich ist.

2. Vorbereitung

  • Ein Google Cloud-Projekt mit aktivierter Abrechnung
  • Webbrowser

Projekt erstellen

Gemini API aktivieren

  • Rufen Sie den Gemini Marketplace auf, um die API zu aktivieren. Sie können die API auch mit gcloud aktivieren:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID

Cloud Functions API aktivieren

gcloud services enable cloudfunctions.googleapis.com --project PROJECT_ID

Cloud Shell aktivieren

  • Sie verwenden die Cloud Shell, eine Befehlszeilenumgebung, die in der Google Cloud Console ausgeführt wird und in der die erforderlichen Sprachen bereits vorinstalliert sind. Klicken Sie in der Cloud Console rechts oben auf Cloud Shell aktivieren:

6757b2fb50ddcc2d.png

  • Sobald die Verbindung mit der Cloud Shell hergestellt ist, sehen Sie, dass Sie bereits authentifiziert sind und für das Projekt schon Ihre Projekt-ID eingestellt ist. Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie authentifiziert sind:
gcloud auth list
  • Führen Sie den folgenden Befehl in Cloud Shell aus, um zu bestätigen, dass der gcloud-Befehl Ihr Projekt kennt:
gcloud config list project
  • Wenn Ihr Projekt nicht festgelegt ist, verwenden Sie den folgenden Befehl, um es festzulegen:
gcloud config set project <YOUR_PROJECT_ID>

Informationen zu gcloud-Befehlen und deren Verwendung finden Sie in der Dokumentation.

Editor öffnen

  • In diesem Codelab verwenden wir den integrierten Cloud-Editor. Klicken Sie im Cloud Shell-Fenster rechts oben auf die Schaltfläche „Editor öffnen“. Dadurch wird ein VSCode-Editor geöffnet.

e5a5e95d543db556.png

Ruby-Erweiterung hinzufügen

  • Klicken Sie im Menü auf der linken Seite auf das Symbol für Erweiterungen 999939b067e1d0dc.png, geben Sie vscode ruby in die Suchleiste ein und installieren Sie die VSCode Ruby-Erweiterung.

a6fd4e37b3d847d2.png

3. Gemini-Warm-up

LLMs sind nicht deterministisch. Daher kann die Antwort, die Sie erhalten, anders aussehen als die in den Screenshots im Codelab.

Fragen wir Gemini zuerst, was ein TDD ist. So können Sie mit Gemini im selben Cloud Shell-Editor interagieren:

  • Suchen Sie auf der linken Seite der Seite nach dem Gemini-Symbol 25fdcae4447d063c.png. Dadurch wird das Chatfenster auf der linken Seite geöffnet.
  • Sie können mit der Eingabe in das Textfeld mit dem Platzhalter Enter a prompt here beginnen.

5e09b0fb6a1b44dd.png

Prompt:

What is Test Driven Development?

Antwort:

Test-driven development (TDD) is a software development methodology that requires developers to write automated tests before writing any production code. This helps ensure the code is correct and meets the requirement.
....

Sie erhalten eine kurze Einführung in TDD und seine Vorteile.

Fragen wir Gemini, was Ruby ist:

Prompt:

What is Ruby?

Antwort:

Ruby is a general-purpose, interpreted, object-oriented programming language. It is designed to be easy to read and write. Ruby is dynamically typed, meaning that the type of a variable is not declared and can change during execution.
....

Darin wird erklärt, was Ruby ist und welche Vorteile die Verwendung von Ruby als Sprache bietet.

4. Projekt einrichten

Erstellen wir nun eine einfache Sinatra-App.

  • Erstellen wir einen leeren Ordner. Sie können ihm einen beliebigen Namen geben. In diesem Codelab nennen wir es gemini-tdd. Erstellen Sie im Cloud-Editor auf der linken Seite auf dem Tab „Explorer“ einen Ordner unter /home/<YOUR-USERNAME>/.

d1d920b074cd7c79.png

  • Öffnen wir den Ordner, den wir gerade erstellt haben. Klicken Sie im Menü ganz links auf das Symbol 1d080370a3ccad53.png und dann auf „Datei“ > „Ordner öffnen“.
  • Erstellen wir in diesem Stammordner eine neue Ruby-Datei, die als Ausgangspunkt für die App dient. Sie können sie beliebig benennen. In diesem Codelab nennen wir es app.rb. 7beab8d21c59eee7.png
  • Fügen wir auch eine Gemfile im Stammordner hinzu. Es ist auch gut, Gemini nach Gemfile zu fragen.
  • Außerdem erstellen wir eine app_test.rb-Datei, in die wir unsere Testläufe schreiben.

5. Gemini-basierte Implementierung

Zuerst geben wir Gemini etwas Kontext dazu, was wir tun möchten, und bitten das Modell, Testläufe dafür zu generieren. Kopieren Sie den folgenden Prompt in den Gemini-Chat-Prompt.

Prompt:

Answer as a software engineer with Ruby expertise. We want to build a Ruby calculator application with a test driven development approach. Let's start by writing some tests for the calculator app using minitest gem.

Antwort:

Here is a simple test for a calculator app that adds two numbers:
require "minitest/autorun"

describe "Calculator" do
  it "should add two numbers" do
    calculator = Calculator.new
    assert_equal 5, calculator.add(2, 3)
  end
end
This test uses the assert_equal method to verify that the result of the add method is correct. 
.....

Sie enthält einen Beispieltestfall für die Rechner App, in dem zwei Zahlen addiert werden. Außerdem wurde die erforderliche Abhängigkeit minitest/autorun für die Tests importiert. Kopieren wir den Inhalt nach app_test.rb. Lassen Sie uns diesen Test jetzt ausführen. Da wir keinen Code geschrieben haben, wird er mit Sicherheit fehlschlagen.

Fragen wir Gemini, wie wir diesen Test durchführen können.

Prompt:

How do we run the tests written in app_test.rb using ruby command?

Antwort:

To run the tests written in app_test.rb using the ruby command, you can use the following steps:
1.Make sure that you are in the same directory as the app_test.rb file.
2.Open a terminal window.
3.Type the following command:
ruby app_test.rb
This will run all of the tests in the app_test.rb file and report the results.

Führen wir den Test aus. Klicken Sie im Tab „Explorer“ mit der rechten Maustaste auf app_test.rb und dann auf „Open in Integrated Terminal“ (Im integrierten Terminal öffnen).

66b4bb9598c1feca.png

Achten Sie darauf, dass Sie sich im selben Ordner wie die Datei „app_test.rb“ befinden. Falls nicht, verwenden Sie den Befehl cd, um dorthin zu wechseln. Führen Sie im Terminal den von Gemini zurückgegebenen Befehl aus:

ruby app_test.rb

Es wird der folgende Fehler angezeigt:

NameError: uninitialized constant Calculator

Fragen wir Gemini direkt im Editor, wie wir das Problem beheben können. Klicken Sie im Navigationsbereich des Cloud Shell-Editors auf das Chatsymbol und stellen Sie den folgenden Prompt:

Prompt:

NameError: uninitialized constant Calculator. Give me Calculator class code.

Antwort:

The error you are getting is because you have not defined the Calculator class. You need to define the Calculator class before you can use it in your tests.
Here is the code for the Calculator class:
Class Calculator
  def add(a, b)
    a + b
  end
end
Once you have defined the Calculator class, you can run the tests again and they will pass.
.....

Gemini teilt uns mit, dass wir keinen Kurs mit dem Namen Calculator haben und dass wir einen erstellen müssen. Außerdem wurde uns der Code zum Erstellen der Klasse Calculator zur Verfügung gestellt. Wir verwenden diesen Code. Öffnen Sie app.rb über den Tab „Explorer“ und kopieren Sie den von Gemini bereitgestellten Code hinein. Während Sie den Inhalt in der Datei „app.rb“ ändern, erhalten Sie möglicherweise einige Vorschläge von Gemini als automatische Vervollständigung. Drücken Sie tab, wenn Sie den Vorschlag annehmen möchten, oder Esc, wenn nicht.

Lassen Sie uns den Test noch einmal ausführen. Geben Sie den folgenden Befehl in Ihr integriertes Terminal ein:

ruby app_test.rb

Sie erhalten aber weiterhin die Fehlermeldung „NameError: uninitialized constant Calculator“. Fragen wir Gemini, wie wir das Problem beheben können.

6. Iteratives TDD mit Gemini

Prompt:

I am still getting this error: "NameError: uninitialized constant Calculator".

Antwort:

The error you are getting is because you have not defined the Calculator class. You need to define the Calculator class before you can use it in your tests.
Here is the code for the Calculator class:
class Calculator
  def add(a, b)
    a + b
  end

  def subtract(a, b)
    a - b
  end

  def multiply(a, b)
    a * b
  end

  def divide(a, b)
    a / b
  end
end
....

Wir haben eine Antwort erhalten, die möglicherweise mit der oben genannten übereinstimmt. Wir müssen Gemini also explizit mitteilen, dass die Klasse „Calculator“ in „app.rb“ definiert ist .

Prompt:

Calculator class is defined in app.rb already.

Antwort:

I see that the Calculator class is defined in the app.rb file. However, you are getting the NameError error because you are trying to use the Calculator class in the app_test.rb file without requiring the app.rb file.
To fix this, you need to add the following line to the top of the app_test.rb file:
require_relative "app"

Wir haben die Antwort von Gemini erhalten, um die Datei „app.rb“ zu importieren, in der die Klasse „Calculator“ definiert ist. Manchmal sind zwei bis drei Iterationen von Prompts erforderlich, um die richtige Antwort zu erhalten. Mit der Zeit werden Sie aber ein Gefühl dafür entwickeln. Möglicherweise sehen Sie in der Antwort von Gemini auch require "./app". Fügen wir das in app.rb in app_test.rb hinzu und führen wir denselben Test noch einmal aus.

Die Datei „app_test.rb“ sollte jetzt so aussehen:

require "minitest/autorun"
require "./app"

describe "Calculator" do
  it "should add two numbers" do
    calculator = Calculator.new
    assert_equal 5, calculator.add(2, 3)
  end
end

Führen Sie den folgenden Befehl im Cloud Shell-Terminal im Projektordner aus:

ruby app_test.rb

Wenn alles wie geplant ausgeführt wird, sollte der Test erfolgreich sein. Wir haben also eine sehr einfache Ruby-App mit dem TDD-Ansatz entwickelt und Gemini um Unterstützung gebeten. Die Antworten auf Prompts sind nicht immer gleich. Das liegt in der Natur von LLM-Modellen. Gemini kann mehr Operationen des Rechners ausführen, aber insgesamt sollte der gerade beschriebene Prozess funktionieren.

7. App in Cloud Functions bereitstellen

Bitten wir Gemini nun, die Funktion in Cloud Functions bereitzustellen:

Prompt:

Let's deploy this app to Cloud Functions

Antwort:

To deploy your app to Cloud Functions, you can use the following steps:
1.Create a new Cloud Functions project.
2.Create a new Cloud Function.
3.Set the trigger for the Cloud Function to be an HTTP request.
4.Set the entry point for the Cloud Function to be the app method in the app.rb file.
5.Deploy the Cloud Function.
Once you have deployed the Cloud Function, you can test it by sending an HTTP request to the function's URL. 
....

Gemini erklärt, wie Sie die Funktion manuell über die Cloud Functions-UI bereitstellen. Aber ich möchte das nicht tun. Ich frage Gemini nach dem gcloud-Befehl, den ich direkt über das integrierte Terminal ausführen kann.

Prompt:

How do I deploy this app to Cloud Functions gen2 using the gcloud command?

Antwort:

...
Here are the specific commands you can use to deploy your app to Cloud Functions using the gcloud command:

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app

This command will create a new Cloud Function called calculator that is triggered by an HTTP request and uses the app method in the app.rb file as the entry point.

Once the Cloud Function is deployed, you can test it by sending an HTTP request to the function's URL. For example, you can use the following command to send a request to the function:

curl -X POST -H "Content-Type: application/json" -d '{"a": 2, "b": 3}' https://REGION-PROJECT_ID.cloudfunctions.net/calculator

Führen wir den von Gemini bereitgestellten gcloud-Befehl im Terminal aus.

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app

Der folgende Fehler tritt auf:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: Could not find Gemfile.lock file in your app. Please make sure your bundle is up to date before deploying.; Error ID: 7916f05c

Lassen Sie uns Gemini nutzen, um den Fehler zu beheben.

Prompt:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: Could not find Gemfile.lock file in your app. Please make sure your bundle is up to date before deploying.; Error ID: 7916f05c

Antwort:

It looks like you're trying to deploy a function to Cloud Functions, but you don't have a Gemfile.lock file in your app. To fix this, run the following command in your app directory:
bundle install
This will create a Gemfile.lock file that lists all of the gems that your app uses.
...

Führen Sie bundle install im Terminal aus, um Gemfile.lock zu erstellen . Sehen Sie nach der Ausführung des Befehls auf dem Tab „Explorer“ nach. Dort sollte Gemfile.lock angezeigt werden.

Versuchen wir noch einmal, die Funktion in Cloud Functions bereitzustellen. Führen Sie denselben Bereitstellungsbefehl im Terminal aus:

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app

Der folgende Fehler tritt auf:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: unable to execute functions-framework-ruby; please ensure a recent version of the functions_framework gem is in your Gemfile; Error ID: 89ae7dda

8. Functions Framework für Ruby

Fragen wir Gemini nach dem Fehler:

Prompt:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: unable to execute functions-framework-ruby; please ensure a recent version of the functions_framework gem is in your Gemfile; Error ID: 89ae7dda

Antwort:

It looks like you're trying to deploy a function to Cloud Functions, but the build is failing because the functions_framework gem is not in your Gemfile. To fix this, add the following line to your Gemfile:

gem "functions_framework"

Then, run the following command to install the gem:

bundle install

Once the gem is installed, you can try deploying your function again.
....

Im Grunde fehlt in unserer App das Gem „functions_framework“. Fügen wir diese Zeile in unser Gemfile ein:

gem "functions_framework"

Führen Sie nun bundle install im Terminal aus. Möglicherweise wird der Fehler „No explicit global resource in Gemfile“ (Keine explizite globale Ressource in Gemfile) angezeigt. Wenn dieses Problem auftritt, muss die erste Zeile Ihres Gemfile so aussehen:

source "https://rubygems.org"

Führen Sie dann bundle install noch einmal über das Terminal aus. Führen Sie nun den Bereitstellungsbefehl noch einmal aus:

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app --project PROJECT_ID

Es wird der folgende Fehler angezeigt:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: failed to verify function target "app" in source "app.rb": Undefined function: "app"; Error ID: e12ab0f9

Um dieses Problem zu beheben, probieren wir die Generate Code-Funktion von Gemini aus. Öffnen wir die Datei „app.rb“ über den Tab „Explorer“. Dort befindet sich bereits der Code für die Rechner-App. Geben Sie in der ersten Zeile von app.rb FunctionsFramework ein und dann .. Es werden einige Vorschläge in grauem Text angezeigt :

9e17476a4a586433.png

Drücken Sie die Tabulatortaste, um den Vorschlag zu akzeptieren. Sobald das akzeptiert wurde, sehen Sie weitere Vorschläge wie unten dargestellt:

f3c35d1539789acc.png

Drücken Sie die Tabulatortaste, um weitere Vorschläge zu akzeptieren. Ihre Datei „app.rb“ sollte also so aussehen:

( Benennen Sie den Funktionsnamen von add in app um.)

require "functions_framework"

FunctionsFramework.http "app" do |request|
 a = request.params["a"].to_i
 b = request.params["b"].to_i
 Calculator.new.add(a, b)
end

class Calculator
 def add(a, b)
   a + b
 end
end

Wir haben gerade den Einstiegspunkt für die Cloud Functions-App erstellt und gelernt, wie wir die Codevorschläge von Gemini im Editor verwenden. Lassen Sie uns nun noch einmal versuchen, die App bereitzustellen.

gcloud functions deploy calculator --runtime ruby32 --trigger-http --entry-point app --project PROJECT_ID

Wenn alles gut geht, sollte die Bereitstellung abgeschlossen werden und Sie sollten die URL sehen, unter der Ihre App gehostet wird. Gut, ändern wir die Datei „app.rb“ ein wenig, damit das Ergebnis der Addition zurückgegeben wird. Ihre endgültige app.rb-Datei sollte so aussehen:

require "functions_framework"

FunctionsFramework.http "app" do |request|
 a = request.params["a"].to_i
 b = request.params["b"].to_i
 calculator = Calculator.new
 add = calculator.add(a, b)
 "Result: #{add}"
end

class Calculator
 def add(a, b)
   a + b
 end
end

9. End-to-End-Tests

Öffnen Sie die URL und übergeben Sie die Abfrageparameter a und b wie unten gezeigt:

https://[APP-URL]/?a=2&b=3

Die Antwort sollte so aussehen : "Result: 5". Ein Taschenrechner kann viele Operationen ausführen. Sie können diese App so erweitern, dass sie auch diese Aufgaben ausführt, und dabei die Hilfe von Gemini in Anspruch nehmen.

10. Fazit

Wir haben heute gesehen, wie man mit dem TDD-Ansatz und Gemini eine Ruby-App entwickelt. Wie Sie bemerkt haben, kann Gemini unterschiedliche Ergebnisse liefern. Das Tool kann jedoch den Entwicklungsprozess in einer Sprache, mit der Sie möglicherweise nicht so vertraut sind, beschleunigen und Ihnen Funktionen oder Snippets zeigen, um Ihre Lernkurve zu beschleunigen.

Jeder Entwickler ( unabhängig von der Erfahrung) kann Gemini für seinen Entwicklungsprozess nutzen. Wenn Sie Gemini nicht zum Entwickeln verwenden, können Sie es verwenden, um vorhandenen Code zu erklären. Sie können es auch bitten, Tests für den vorhandenen Code zu generieren. Das ist zumindest für mich der langweiligste Job 🙂

Viel Spaß beim Programmieren mit Gemini!