Codelab: Gemini להאצת פיתוח מבוסס-בדיקות

1. מבוא

ב-codelab הזה נסביר את העקרונות של פיתוח מונחה-בדיקות ( TDD), שבו כותבים בדיקות לפני שמטמיעים קוד. נפתח אפליקציית מחשבון פשוטה באמצעות Ruby כדי להדגים את הגישה הזו.

בנוסף, תלמדו איך להשתמש ב-Gemini כעוזר לתכנות. ‫Gemini יעזור לכם להאיץ את מחזור ה-TDD על ידי יצירת תרחישי בדיקה, הצעת יישומי קוד ואפילו מתן הסברים על הקוד.

לבסוף, תלמדו איך לפרוס את אפליקציית המחשבון ל-Cloud Function, פלטפורמת ה-serverless המנוהלת במלואה של Google, כדי שהאפליקציה תהיה נגישה.

2. דרישות מוקדמות

  • פרויקט ב-Google Cloud עם חיוב מופעל
  • דפדפן אינטרנט

יצירת הפרויקט

הפעלת Gemini API

  • כדי להפעיל את ה-API, עוברים אל Gemini Marketplace. אפשר גם להשתמש ב-gcloud כדי להפעיל את ה-API:
gcloud services enable cloudaicompanion.googleapis.com --project PROJECT_ID
  • נכנסים לדף Gemini ולוחצים על 'התחלת שיחה'.
  • חשוב: כדי להתחיל להשתמש ב-Gemini ולהפעיל את Gemini ב-Cloud Shell IDE, צריך לפעול לפי שלבים 1 ו-2 ב-codelab הזה.

הפעלת Cloud Functions API

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

הפעלת Cloud Shell

  • תשתמשו ב-Cloud Shell, סביבת שורת פקודה שפועלת במסוף Google Cloud, שכוללת מראש את השפות הנדרשות. ב-Cloud Console, לוחצים על Activate Cloud Shell (הפעלת Cloud Shell) בפינה הימנית העליונה:

6757b2fb50ddcc2d.png

  • אחרי שמתחברים ל-Cloud Shell, אמור להופיע אימות שכבר בוצע ושהפרויקט מוגדר לפי מזהה הפרויקט. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שהאימות בוצע:
gcloud auth list
  • מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שפקודת gcloud מכירה את הפרויקט:
gcloud config list project
  • אם הפרויקט לא מוגדר, משתמשים בפקודה הבאה כדי להגדיר אותו:
gcloud config set project <YOUR_PROJECT_ID>

אפשר לעיין במאמרי העזרה בנושא פקודות gcloud ושימוש בהן.

פתיחת העורך

  • ב-codelab הזה נשתמש בעורך Cloud המובנה. בחלון Cloud Shell, לוחצים על הלחצן 'פתיחת כלי העריכה' בפינה השמאלית העליונה. ייפתח כלי העריכה VSCode.

e5a5e95d543db556.png

הוספת תוסף Ruby

  • בתפריט צד שמימין, לוחצים על סמל התוספים 999939b067e1d0dc.png, כותבים vscode ruby בסרגל החיפוש ומתקינים את התוסף VSCode Ruby.

a6fd4e37b3d847d2.png

3. חימום של Gemini

מודלים גדולים של שפה הם לא דטרמיניסטיים. לכן, כשמנסים את ההנחיות האלה, יכול להיות שהתשובה שתקבלו תיראה שונה מהתשובות בצילומי המסך שמצורפים ל-codelab.

קודם נשאל את Gemini מה זה TDD. כדי להתחיל לשוחח עם Gemini באותו Cloud Shell Editor שבו אנחנו נמצאים, פועלים לפי השלבים הבאים:

  • בצד ימין של הדף, מאתרים את סמל Gemini ‏ 25fdcae4447d063c.png. חלון הצ'אט ייפתח בצד ימין.
  • אפשר להתחיל להקליד בתיבת הטקסט שכתוב בה Enter a prompt here

5e09b0fb6a1b44dd.png

ההנחיה:

What is Test Driven Development?

תשובה:

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

הוא מספק מבוא קצר ל-TDD והסבר על היתרונות שלו.

עכשיו נשאל את Gemini מה זה Ruby:

ההנחיה:

What is Ruby?

תשובה:

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

הוא מסביר מהי Ruby ומהם היתרונות של השימוש ב-Ruby כשפה.

4. הגדרת הפרויקט

עכשיו נתחיל ליצור אפליקציית Sinatra פשוטה.

  • ניצור תיקייה ריקה. אפשר לתת לו כל שם שרוצים. ב-codelab הזה נקרא לו gemini-tdd. בעורך הענן בצד ימין, בכרטיסייה Explorer, יוצרים תיקייה מתחת ל-/home/<YOUR-USERNAME>/.

d1d920b074cd7c79.png

  • בוא נפתח את התיקייה שיצרנו עכשיו. בתפריט הימני ביותר, לוחצים על הסמל 1d080370a3ccad53.png, לוחצים על קובץ -> פתיחת תיקייה.
  • ניצור קובץ Ruby חדש בתיקיית הבסיס הזו, שישמש כנקודת התחלה לאפליקציה. אפשר לתת לו כל שם שרוצים. ב-codelab הזה נקרא לו app.rb. 7beab8d21c59eee7.png
  • נוסיף גם Gemfile לתיקיית הבסיס. כדאי גם לשאול את Gemini על Gemfile.
  • ניצור גם קובץ app_test.rb כדי לכתוב את תרחישי הבדיקה שלנו.

5. הטמעה מבוססת-Gemini

עכשיו נתחיל בכך שנספק ל-Gemini הקשר לגבי מה שאנחנו מנסים לעשות ונבקש ממנו ליצור תרחישי בדיקה לאותו דבר. מעתיקים את ההנחיה הבאה להנחיה בשיחה עם Gemini.

ההנחיה:

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.

תשובה:

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

הוא מספק לכם מקרה בדיקה לדוגמה לאפליקציית המחשבון, כלומר לחיבור של שני מספרים. הוא גם ייבא את התלות הנדרשת minitest/autorun לבדיקות. אני רוצה להעתיק את התוכן אל app_test.rb. ננסה להריץ את הבדיקה הזו עכשיו. מכיוון שלא כתבנו קוד, היא תיכשל בוודאות.

יש לך שאלה ל-Gemini איך להריץ את הבדיקה הזו?

ההנחיה:

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

תשובה:

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.

אז בואו נריץ את הבדיקה. לוחצים לחיצה ימנית על app_test.rb בכרטיסייה Explorer ואז לוחצים על Open in Integrated Terminal (פתיחה בטרמינל משולב).

66b4bb9598c1feca.png

מוודאים שאתם באותה תיקייה שבה נמצא הקובץ app_test.rb. אם לא, משתמשים בפקודה cd כדי להגיע לתיקייה. במסוף, מריצים את הפקודה ש-Gemini החזיר:

ruby app_test.rb

תופיע השגיאה הבאה:

NameError: uninitialized constant Calculator

אפשר לבקש מ-Gemini איך לפתור את הבעיה ישירות מהכלי לעריכה. לוחצים על סמל הצ'אט בחלונית הניווט של Cloud Shell Editor ומזינים את ההנחיה הבאה:

ההנחיה:

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

תשובה:

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 אומר שאין לנו כיתה בשם Calculator ושאנחנו צריכים ליצור כיתה כזו. הוא גם נתן לנו את הקוד ליצירת הכיתה Calculator. נשתמש בקוד הזה. פותחים את app.rb מהכרטיסייה 'סייר' ומעתיקים לתוכו את הקוד ש-Gemini סיפק. במהלך השינוי של התוכן בקובץ app.rb, יכול להיות ש-Gemini יציע לכם השלמה אוטומטית. אם אתם רוצים לקבל את ההצעה, אתם צריכים ללחוץ על tab, ואם לא, על Esc.

עכשיו נריץ את הבדיקה שוב. מקלידים את הפקודה הבאה בטרמינל המשולב:

ruby app_test.rb

אבל עדיין תופיע השגיאה NameError: uninitialized constant Calculator. בואו נשאל את Gemini איך לתקן אותה.

6. פיתוח מונחה-בדיקות איטרטיבי באמצעות Gemini

ההנחיה:

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

תשובה:

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

הוא נתן לנו תשובה כלשהי, יכול להיות שהיא זהה לתשובה שלמעלה ויכול להיות שלא. לכן, נגיד ל-Gemini באופן מפורש שהגדרנו את המחלקה Calculator בקובץ app.rb .

ההנחיה:

Calculator class is defined in app.rb already.

תשובה:

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"

קיבלנו מ-Gemini את התשובה לייבוא של הקובץ app.rb שבו מוגדרת המחלקה Calculator. לפעמים צריך לנסות 2-3 פעמים לשלוח הנחיות כדי לקבל את התשובה הנכונה, אבל ככל שתתרגלו, התשובות יהיו טובות יותר. שימו לב: יכול להיות שבתשובה מ-Gemini תופיע גם האפשרות require "./app". נוסיף את זה ל-app.rb ב-app_test.rb ונריץ שוב את אותה בדיקה.

בשלב הזה, הקובץ app_test.rb אמור להיראות כך:

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

מריצים את הפקודה הבאה מ-Cloud Shell Terminal בתוך תיקיית הפרויקט:

ruby app_test.rb

אם הכול ילך כשורה, הבדיקה תעבור. לכן פיתחנו אפליקציית Ruby פשוטה מאוד באמצעות גישת TDD, ונעזרנו ב-Gemini. התשובות להנחיות לא יהיו זהות בכל פעם, וזה טבעם של מודלים של LLM. יכול להיות שתקבלו מ-Gemini יותר פעולות של המחשבון, אבל באופן כללי, התהליך שתיארנו אמור לעבוד.

7. פריסת האפליקציה ב-Cloud Functions

עכשיו נבקש מ-Gemini לפרוס את זה ב-Cloud Functions:

ההנחיה:

Let's deploy this app to Cloud Functions

תשובה:

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 מסביר איך לפרוס אותו באופן ידני באמצעות ממשק המשתמש של Cloud Functions. אבל אני לא רוצה לעשות את זה. אני רוצה לבקש מ-Gemini את הפקודה gcloud שאוכל להריץ ישירות מהטרמינל המשולב.

ההנחיה:

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

תשובה:

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

נריץ את פקודת gcloud ש-Gemini נתן במסוף.

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

תופיע השגיאה הבאה:

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

נשתמש ב-Gemini כדי לתקן את השגיאה.

ההנחיה:

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

תשובה:

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

מריצים את הפקודה bundle install בטרמינל כדי ליצור את הקובץ Gemfile.lock . אחרי שמריצים את הפקודה, בודקים את הכרטיסייה של סייר הקבצים. אמורה להופיע שם Gemfile.lock.

ננסה לפרוס שוב ל-Cloud Functions. מריצים את אותה פקודת פריסה במסוף:

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

תופיע שגיאה נוספת:

"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 for Ruby

יש לך שאלה ל-Gemini על השגיאה:

ההנחיה:

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

תשובה:

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

לכן, בעצם, חסר לנו קובץ ה-gem של functions_framework באפליקציה. נוסיף את השורה הזו לקובץ Gemfile:

gem "functions_framework"

מריצים את הפקודה bundle install בטרמינל. יכול להיות שתיתקלו בשגיאה 'No explicit global resource in Gemfile' (אין משאב גלובלי מפורש ב-Gemfile), ויכול להיות שלא. אם נתקלתם בבעיה הזו, ודאו שהשורה הראשונה בקובץ Gemfile היא:

source "https://rubygems.org"

ואז מריצים שוב את הפקודה bundle install מהטרמינל. עכשיו מריצים שוב את פקודת הפריסה:

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

עכשיו תופיע השגיאה הבאה:

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

כדי לפתור את הבעיה, ננסה את התכונה Generate Code של Gemini. נפתח את הקובץ app.rb מהכרטיסייה 'סייר', שבה כבר יש לנו את הקוד של אפליקציית המחשבון. ב-app.rb, בשורה הראשונה, מתחילים להקליד FunctionsFramework ואז מקלידים ".". יופיעו כמה הצעות בטקסט אפור :

9e17476a4a586433.png

מקישים על Tab כדי לאשר את ההצעה. אחרי שההצעה תאושר, יוצגו לכם עוד הצעות כמו אלה שמופיעות בהמשך:

f3c35d1539789acc.png

מקישים על Tab כדי לאשר הצעות נוספות. לכן, הקובץ app.rb אמור להיראות כך:

( שינוי שם הפונקציה מ-add ל-app )

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

הרגע יצרנו את נקודת הכניסה לאפליקציית Cloud Functions, ולמדנו איך להשתמש בהצעות הקוד של Gemini בעורך. עכשיו ננסה לפרוס את האפליקציה שוב.

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

אם הכול ילך כשורה, הפריסה תתבצע ותוכלו לראות את כתובת ה-URL שבה האפליקציה מתארחת. אוקיי, נשנה קצת את הקובץ app.rb כדי להחזיר את תוצאת החיבור. הקובץ הסופי app.rb אמור להיראות כך:

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. בדיקות מקצה לקצה

פותחים את כתובת ה-URL ומעבירים את הפרמטרים של השאילתה a ו-b כמו שמוצג בהמשך:

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

התגובה אמורה להופיע כך : "Result: 5". מחשבון יכול לבצע הרבה פעולות. אתם יכולים להרחיב את האפליקציה הזו כדי לבצע גם את הפעולות האלה, ולהיעזר ב-Gemini.

10. סיכום

ראינו איך לפתח אפליקציית Ruby היום באמצעות גישת TDD בעזרת Gemini. כמו ששמת לב, יכול להיות ש-Gemini ייתן לך תוצאות שונות, אבל הוא בהחלט יכול לעזור לך להאיץ את תהליך הפיתוח בשפה שאתה לא מכיר הכי טוב, ועדיין להציג לך פונקציות או קטעי קוד כדי לקצר את עקומת הלמידה.

כל מפתח ( ללא קשר לניסיון שלו) יכול לקבל עזרה מ-Gemini בתהליך הפיתוח. אם לא מפתחים, אפשר להשתמש ב-Gemini כדי לקבל הסבר על קוד קיים, או לבקש ממנו ליצור בדיקות לקוד הקיים. לדעתי, זו העבודה הכי משעממת 🙂

תכנות מהנה עם Gemini!