إنشاء وكيل "مخطِّط اختبار تأكيد الجودة" باستخدام "حزمة تطوير التطبيقات" و"منصة المحتوى التجريبي" وGemini 2.5 Flash مع "وضع التفكير"

1. مقدمة

fd4ad67ab57d9257.png

تستند إمكانية استخدام الذكاء الاصطناعي التوليدي لإنشاء خطط الاختبار إلى قدرته على حلّ اثنين من أكبر التحديات في ضمان الجودة الحديث: السرعة والشمولية. في دورات Agile وDevOps السريعة اليوم، يشكّل إنشاء خطط اختبار تفصيلية يدويًا عنق زجاجة كبيرًا، ما يؤدي إلى تأخير عملية الاختبار بأكملها. يمكن لوكيل مستند إلى الذكاء الاصطناعي التوليدي استيعاب قصص المستخدمين والمتطلبات الفنية لإنتاج خطة اختبار شاملة في غضون دقائق، وليس أيامًا، ما يضمن مواكبة عملية ضمان الجودة لعملية التطوير. علاوةً على ذلك، يتفوّق الذكاء الاصطناعي في تحديد السيناريوهات المعقّدة وحالات الاستخدام غير الشائعة والمسارات السلبية التي قد يغفل عنها الإنسان، ما يؤدي إلى تحسين تغطية الاختبار بشكل كبير وتقليل عدد الأخطاء التي تصل إلى مرحلة الإنتاج.

في هذا الدرس العملي، سنتعرّف على كيفية إنشاء وكيل من هذا النوع يمكنه استرداد مستندات متطلبات المنتج من Confluence وتقديم ملاحظات بنّاءة، بالإضافة إلى إنشاء خطة اختبار شاملة يمكن تصديرها إلى ملف CSV.

خلال هذا الدرس العملي، ستتّبع نهجًا خطوة بخطوة على النحو التالي:

  1. إعداد مشروعك على Google Cloud وتفعيل جميع واجهات برمجة التطبيقات المطلوبة فيه
  2. إعداد مساحة العمل لبيئة الترميز
  3. إعداد mcp-server محلي لـ Confluence
  4. تنظيم رمز مصدر وكيل ADK والطلب والأدوات للاتصال بخادم MCP
  5. فهم استخدام "خدمة Artifact" و"سياقات الأدوات"
  6. اختبار الوكيل باستخدام واجهة المستخدم المحلية لتطوير الويب في "حزمة تطوير التطبيقات" (ADK)
  7. إدارة متغيّرات البيئة وإعداد الملفات المطلوبة لتفعيل التطبيق على Cloud Run
  8. نشر التطبيق على Cloud Run

نظرة عامة على البنية

819179179d974c07.jpeg

المتطلبات الأساسية

  • إجادة العمل باستخدام لغة Python
  • فهم بنية أساسية كاملة الميزات باستخدام خدمة HTTP

ما ستتعلمه

  • تصميم بنية ADK Agent مع الاستفادة من إمكاناته المتعدّدة
  • استخدام الأداة مع "الأداة المخصّصة" و"إدارة العملاء المتعدّدين"
  • إعداد إخراج الملفات بواسطة الوكيل باستخدام إدارة خدمة Artifact
  • استخدام BuiltInPlanner لتحسين تنفيذ المهام من خلال التخطيط باستخدام قدرات Gemini 2.5 Flash التحليلية
  • التفاعل وتصحيح الأخطاء من خلال واجهة الويب الخاصة بـ "حزمة تطوير التطبيقات"
  • نشر التطبيق على Cloud Run باستخدام Dockerfile وتوفير متغيّرات البيئة

المتطلبات

  • متصفّح الويب Chrome
  • حساب Gmail
  • مشروع على السحابة الإلكترونية تم تفعيل الفوترة فيه
  • (اختياري) مساحة Confluence تتضمّن صفحات "مستندات متطلبات المنتج"

يستخدم هذا الدرس العملي، المصمّم للمطوّرين من جميع المستويات (بما في ذلك المبتدئين)، لغة Python في التطبيق النموذجي. ومع ذلك، لا يُشترط معرفة لغة Python لفهم المفاهيم المقدَّمة. لا داعي للقلق بشأن مساحة Confluence إذا لم يكن لديك واحدة، وسنوفّر لك بيانات الاعتماد لتجربة هذا الدرس العملي.

2. قبل البدء

اختيار المشروع النشط في Cloud Console

يفترض هذا الدرس العملي أنّ لديك مشروعًا على Google Cloud تم تفعيل الفوترة فيه. إذا لم تكن هذه الميزة متاحة لك بعد، يمكنك اتّباع التعليمات أدناه للبدء.

  1. في Google Cloud Console، في صفحة اختيار المشروع، اختَر أو أنشِئ مشروعًا على Google Cloud.
  2. تأكَّد من تفعيل الفوترة لمشروعك على Cloud. تعرَّف على كيفية التحقّق مما إذا كانت الفوترة مفعَّلة في مشروع.

3a29a3ec1306e9b4.png

إعداد مشروع Cloud في نافذة Cloud Shell

  1. ستستخدم Cloud Shell، وهي بيئة سطر أوامر تعمل في Google Cloud. انقر على "تفعيل Cloud Shell" في أعلى "وحدة تحكّم Google Cloud".

1829c3759227c19b.png

  1. بعد الاتصال بـ Cloud Shell، يمكنك التأكّد من أنّك قد تم التحقّق من هويتك وأنّه تم ضبط المشروع على معرّف مشروعك باستخدام الأمر التالي:
gcloud auth list
  1. نفِّذ الأمر التالي في Cloud Shell للتأكّد من أنّ أمر gcloud يعرف مشروعك.
gcloud config list project
  1. إذا لم يتم ضبط مشروعك، استخدِم الأمر التالي لضبطه:
gcloud config set project <YOUR_PROJECT_ID>

بدلاً من ذلك، يمكنك أيضًا الاطّلاع على معرّف PROJECT_ID في وحدة التحكّم.

4032c45803813f30.jpeg

انقر عليه وسيظهر لك كل مشروعك ورقم تعريف المشروع على الجانب الأيسر

8dc17eb4271de6b5.jpeg

  1. فعِّل واجهات برمجة التطبيقات المطلوبة من خلال الأمر الموضّح أدناه. قد تستغرق هذه العملية بضع دقائق، لذا يُرجى الانتظار.
gcloud services enable aiplatform.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       cloudresourcemanager.googleapis.com

عند تنفيذ الأمر بنجاح، من المفترض أن تظهر لك رسالة مشابهة للرسالة الموضّحة أدناه:

Operation "operations/..." finished successfully.

يمكنك بدلاً من استخدام أمر gcloud، البحث عن كل منتج من خلال وحدة التحكّم أو استخدام هذا الرابط.

في حال عدم توفّر أي واجهة برمجة تطبيقات، يمكنك تفعيلها في أي وقت أثناء عملية التنفيذ.

راجِع المستندات لمعرفة أوامر gcloud وطريقة استخدامها.

الانتقال إلى Cloud Shell Editor وإعداد دليل عمل التطبيق

الآن، يمكننا إعداد محرّر الرموز البرمجية لتنفيذ بعض مهام الترميز. سنستخدم "محرّر Cloud Shell" لهذا الغرض.

  1. انقر على الزر "فتح المحرِّر" (Open Editor)، وسيؤدي ذلك إلى فتح "محرِّر Cloud Shell" (Cloud Shell Editor)، ويمكننا كتابة الرمز هنا b16d56e4979ec951.png
  2. تأكَّد من ضبط مشروع Cloud Code في أسفل يمين (شريط الحالة) محرر Cloud Shell، كما هو موضّح في الصورة أدناه، ومن ضبطه على مشروع Google Cloud النشط الذي تم تفعيل الفوترة فيه. امنح الإذن إذا طُلب منك ذلك. إذا كنت قد اتّبعت الأمر السابق، قد يشير الزر أيضًا مباشرةً إلى مشروعك المفعّل بدلاً من زر تسجيل الدخول.

f5003b9c38b43262.png

  1. بعد ذلك، لنستنسخ دليل العمل الخاص بالنموذج لهذا الدرس العملي من Github، وننفّذ الأمر التالي. سيؤدي ذلك إلى إنشاء دليل العمل في الدليل qa-test-planner-agent.
git clone https://github.com/alphinside/qa-test-planner-agent.git qa-test-planner-agent
  1. بعد ذلك، انتقِل إلى القسم العلوي من "محرّر Cloud Shell" وانقر على ملف->فتح مجلد (File->Open Folder)، وابحث عن دليل اسم المستخدم، ثم ابحث عن دليل qa-test-planner-agent وانقر على الزر "حسنًا" (OK). سيؤدي ذلك إلى جعل الدليل الذي تم اختياره هو دليل العمل الرئيسي. في هذا المثال، اسم المستخدم هو alvinprayuda، وبالتالي يظهر مسار الدليل أدناه

2c53696f81d805cc.png

fb321426f3c848b3.png

من المفترض أن يظهر "محرّر Cloud Shell" الآن على النحو التالي

9ae344bc522d2a6f.png

إعداد البيئة

إعداد بيئة Python الافتراضية

الخطوة التالية هي إعداد بيئة التطوير. يجب أن تكون نافذة الجهاز النشطة الحالية داخل دليل العمل qa-test-planner-agent. سنستخدم الإصدار 3.12 من لغة Python في هذا الدرس العملي، كما سنستخدم أداة إدارة مشاريع Python‏ uv لتسهيل عملية إنشاء إصدار Python وبيئته الافتراضية وإدارتهما.

  1. إذا لم تكن قد فتحت المحطة الطرفية بعد، افتحها بالنقر على المحطة الطرفية -> محطة طرفية جديدة، أو استخدِم Ctrl + Shift + C، وسيؤدي ذلك إلى فتح نافذة محطة طرفية في الجزء السفلي من المتصفح.

f8457daf0bed059e.jpeg

  1. نزِّل uv وثبِّت الإصدار 3.12 من Python باستخدام الأمر التالي
curl -LsSf https://astral.sh/uv/0.7.19/install.sh | sh && \
source $HOME/.local/bin/env && \
uv python install 3.12
  1. لنبدأ الآن بتهيئة البيئة الافتراضية باستخدام uv، وننفّذ الأمر التالي
uv sync --frozen

سيؤدي ذلك إلى إنشاء الدليل .venv وتثبيت التبعيات. ستمنحك نظرة خاطفة سريعة على pyproject.toml معلومات عن التبعيات المعروضة على النحو التالي

dependencies = [
    "google-adk>=1.5.0",
    "mcp-atlassian>=0.11.9",
    "pandas>=2.3.0",
    "python-dotenv>=1.1.1",
]
  1. لاختبار البيئة الافتراضية، أنشئ ملفًا جديدًا باسم main.py وانسخ الرمز التالي
def main():
   print("Hello from qa-test-planner-agent")

if __name__ == "__main__":
   main()
  1. بعد ذلك، شغِّل الأمر التالي
uv run main.py

ستظهر لك نتيجة مشابهة لما يلي

Using CPython 3.12
Creating virtual environment at: .venv
Hello from qa-test-planner-agent!

يشير ذلك إلى أنّه يتم إعداد مشروع Python بشكل صحيح.

يمكننا الآن الانتقال إلى الخطوة التالية، وهي إنشاء الوكيل ثم الخدمات.

3- إنشاء الوكيل باستخدام Google ADK وGemini 2.5

مقدّمة عن بنية دليل ADK

لنبدأ باستكشاف ما يقدّمه "مجموعة أدوات تطوير التطبيقات" وكيفية إنشاء الوكيل. يمكنك الاطّلاع على المستندات الكاملة الخاصة بـ ADK من خلال عنوان URL هذا . توفّر لنا "حزمة تطوير التطبيقات" العديد من الأدوات المساعدة في تنفيذ أوامر واجهة سطر الأوامر. في ما يلي بعض هذه الحالات :

  • إعداد بنية دليل الوكلاء
  • تجربة التفاعل بسرعة من خلال إدخال وإخراج واجهة سطر الأوامر
  • إعداد واجهة ويب لواجهة مستخدم التطوير المحلي بسرعة

الآن، لننشئ بنية دليل الوكيل باستخدام أمر واجهة سطر الأوامر. نفِّذ الأمر التالي

uv run adk create qa_test_planner \
   --model gemini-2.5-flash \
   --project {your-project-id} \
   --region global

سيؤدي ذلك إلى إنشاء بنية دليل الوكيل التالية في دليل العمل الحالي

qa_test_planner/
├── __init__.py
├── .env
├── agent.py

وإذا فحصت الملفَين init.py وagent.py، سيظهر لك هذا الرمز

# __init__.py

from . import agent
# agent.py

from google.adk.agents import Agent

root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description='A helpful assistant for user questions.',
    instruction='Answer user questions to the best of your knowledge',
)

إنشاء وكيل "مخطِّط اختبار تأكيد الجودة"

لنبدأ بإنشاء وكيل تخطيط اختبار ضمان الجودة. افتح الملف qa_test_planner/agent.py وانسخ الرمز أدناه الذي سيتضمّن root_agent.

# qa_test_planner/agent.py

from google.adk.agents import Agent
from google.adk.tools.mcp_tool.mcp_toolset import (
    MCPToolset,
    StdioConnectionParams,
    StdioServerParameters,
)
from google.adk.planners import BuiltInPlanner
from google.genai import types
from dotenv import load_dotenv
import os
from pathlib import Path
from pydantic import BaseModel
from typing import Literal
import tempfile
import pandas as pd
from google.adk.tools import ToolContext


load_dotenv(dotenv_path=Path(__file__).parent / ".env")

confluence_tool = MCPToolset(
    connection_params=StdioConnectionParams(
        server_params=StdioServerParameters(
            command="uvx",
            args=[
                "mcp-atlassian",
                f"--confluence-url={os.getenv('CONFLUENCE_URL')}",
                f"--confluence-username={os.getenv('CONFLUENCE_USERNAME')}",
                f"--confluence-token={os.getenv('CONFLUENCE_TOKEN')}",
                "--enabled-tools=confluence_search,confluence_get_page,confluence_get_page_children",
            ],
            env={},
        ),
        timeout=60,
    ),
)


class TestPlan(BaseModel):
    test_case_key: str
    test_type: Literal["manual", "automatic"]
    summary: str
    preconditions: str
    test_steps: str
    expected_result: str
    associated_requirements: str


async def write_test_tool(
    prd_id: str, test_cases: list[dict], tool_context: ToolContext
):
    """A tool to write the test plan into file

    Args:
        prd_id: Product requirement document ID
        test_cases: List of test case dictionaries that should conform to these fields:
            - test_case_key: str
            - test_type: Literal["manual","automatic"]
            - summary: str
            - preconditions: str
            - test_steps: str
            - expected_result: str
            - associated_requirements: str

    Returns:
        A message indicating success or failure of the validation and writing process
    """
    validated_test_cases = []
    validation_errors = []

    # Validate each test case
    for i, test_case in enumerate(test_cases):
        try:
            validated_test_case = TestPlan(**test_case)
            validated_test_cases.append(validated_test_case)
        except Exception as e:
            validation_errors.append(f"Error in test case {i + 1}: {str(e)}")

    # If validation errors exist, return error message
    if validation_errors:
        return {
            "status": "error",
            "message": "Validation failed",
            "errors": validation_errors,
        }

    # Write validated test cases to CSV
    try:
        # Convert validated test cases to a pandas DataFrame
        data = []
        for tc in validated_test_cases:
            data.append(
                {
                    "Test Case ID": tc.test_case_key,
                    "Type": tc.test_type,
                    "Summary": tc.summary,
                    "Preconditions": tc.preconditions,
                    "Test Steps": tc.test_steps,
                    "Expected Result": tc.expected_result,
                    "Associated Requirements": tc.associated_requirements,
                }
            )

        # Create DataFrame from the test case data
        df = pd.DataFrame(data)

        if not df.empty:
            # Create a temporary file with .csv extension
            with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as temp_file:
                # Write DataFrame to the temporary CSV file
                df.to_csv(temp_file.name, index=False)
                temp_file_path = temp_file.name

            # Read the file bytes from the temporary file
            with open(temp_file_path, "rb") as f:
                file_bytes = f.read()

            # Create an artifact with the file bytes
            await tool_context.save_artifact(
                filename=f"{prd_id}_test_plan.csv",
                artifact=types.Part.from_bytes(data=file_bytes, mime_type="text/csv"),
            )

            # Clean up the temporary file
            os.unlink(temp_file_path)

            return {
                "status": "success",
                "message": (
                    f"Successfully wrote {len(validated_test_cases)} test cases to "
                    f"CSV file: {prd_id}_test_plan.csv"
                ),
            }
        else:
            return {"status": "warning", "message": "No test cases to write"}
    except Exception as e:
        return {
            "status": "error",
            "message": f"An error occurred while writing to CSV: {str(e)}",
        }


root_agent = Agent(
    model="gemini-2.5-flash",
    name="qa_test_planner_agent",
    description="You are an expert QA Test Planner and Product Manager assistant",
    instruction=f"""
Help user search any product requirement documents on Confluence. Furthermore you also can provide the following capabilities when asked:
- evaluate product requirement documents and assess it, then give expert input on what can be improved 
- create a comprehensive test plan following Jira Xray mandatory field formatting, result showed as markdown table. Each test plan must also have explicit mapping on 
    which user stories or requirements identifier it's associated to 

Here is the Confluence space ID with it's respective document grouping:

- "{os.getenv("CONFLUENCE_PRD_SPACE_ID")}" : space to store Product Requirements Documents

Do not making things up, Always stick to the fact based on data you retrieve via tools.
""",
    tools=[confluence_tool, write_test_tool],
    planner=BuiltInPlanner(
        thinking_config=types.ThinkingConfig(
            include_thoughts=True,
            thinking_budget=2048,
        )
    ),
)

إعداد ملفات الإعداد

الآن، سنحتاج إلى إضافة إعدادات تهيئة إضافية لهذا المشروع، لأنّ هذا البرنامج سيحتاج إلى الوصول إلى Confluence

افتح الملف qa_test_planner/.env وأضِف إليه قيم متغيرات البيئة التالية، وتأكَّد من أنّ الملف .env الناتج يبدو على النحو التالي

GOOGLE_GENAI_USE_VERTEXAI=1
GOOGLE_CLOUD_PROJECT={YOUR-CLOUD-PROJECT-ID}
GOOGLE_CLOUD_LOCATION=global
CONFLUENCE_URL={YOUR-CONFLUENCE-DOMAIN}
CONFLUENCE_USERNAME={YOUR-CONFLUENCE-USERNAME}
CONFLUENCE_TOKEN={YOUR-CONFLUENCE-API-TOKEN}
CONFLUENCE_PRD_SPACE_ID={YOUR-CONFLUENCE-SPACE-ID}

لا يمكن إتاحة مساحة Confluence هذه للجميع، لذا يمكنك فحص هذه الملفات لقراءة مستندات متطلبات المنتج المتاحة والتي ستكون متاحة باستخدام بيانات الاعتماد المذكورة أعلاه.

شرح الرمز

يحتوي هذا النص البرمجي على عملية بدء تشغيل الوكيل حيث نضبط القيم الأولية لما يلي:

  • اضبط النموذج الذي سيتم استخدامه على gemini-2.5-flash
  • إعداد أدوات Confluence MCP التي ستتواصل عبر Stdio
  • إعداد أداة write_test_tool مخصّصة لكتابة خطة الاختبار وتصدير ملف csv إلى العنصر
  • إعداد وصف الوكيل وتعليماته
  • تفعيل التخطيط قبل إنشاء الردّ النهائي أو تنفيذه باستخدام إمكانات التفكير في Gemini 2.5 Flash

يمكن للوكيل نفسه، عندما يكون مزوّدًا بنموذج Gemini مع إمكانات التفكير المضمّنة وتم إعداده باستخدام وسيطات المخطّط، أن يعرض إمكانات التفكير ويظهر أيضًا على واجهة الويب. يظهر أدناه الرمز البرمجي اللازم لإعداد ذلك

# qa-test-planner/agent.py

from google.adk.planners import BuiltInPlanner
from google.genai import types

...

# Provide the confluence tool to agent

root_agent = Agent(
    model="gemini-2.5-flash",
    name="qa_test_planner_agent",
    ...,
    tools=[confluence_tool, write_test_tool],
    planner=BuiltInPlanner(
        thinking_config=types.ThinkingConfig(
            include_thoughts=True,
            thinking_budget=2048,
        )
    ),

...

وقبل اتخاذ أي إجراءات، يمكننا الاطّلاع على عملية التفكير التي يتّبعها

185371e0e7e5995e.png

أداة Confluence MCP

للاتصال بخادم MCP من ADK، علينا استخدام MCPToolSet الذي يمكن استيراده من الوحدة google.adk.tools.mcp_tool.mcp_toolset. الرمز المراد تهيئته هنا معروض أدناه ( تم اقتطاعه لتحسين الكفاءة)

# qa-test-planner/agent.py

from google.adk.tools.mcp_tool.mcp_toolset import (
    MCPToolset,
    StdioConnectionParams,
    StdioServerParameters,
)

...

# Initialize the Confluence MCP Tool via Stdio Output

confluence_tool = MCPToolset(
    connection_params=StdioConnectionParams(
        server_params=StdioServerParameters(
            command="uvx",
            args=[
                "mcp-atlassian",
                f"--confluence-url={os.getenv('CONFLUENCE_URL')}",
                f"--confluence-username={os.getenv('CONFLUENCE_USERNAME')}",
                f"--confluence-token={os.getenv('CONFLUENCE_TOKEN')}",
                "--enabled-tools=confluence_search,confluence_get_page,confluence_get_page_children",
            ],
            env={},
        ),
        timeout=60,
    ),
)


...

# Provide the confluence tool to agent

root_agent = Agent(
    model="gemini-2.5-flash",
    name="qa_test_planner_agent",
    ...,
    tools=[confluence_tool, write_test_tool],

...

باستخدام هذا الإعداد، سيُفعّل العامل خادم Confluence MCP كعملية منفصلة وسيتعامل مع عمليات الاتصال هذه من خلال Studio I/O. يتم توضيح هذا المسار في صورة بنية MCP التالية التي تم وضع علامة عليها داخل المربّع الأحمر أدناه.

85d51458405f9217.png

بالإضافة إلى ذلك، ضمن وسيطات الأوامر الخاصة بتهيئة MCP، نحصر أيضًا الأدوات التي يمكن استخدامها في هذه الأدوات فقط: confluence_search وconfluence_get_page وconfluence_get_page_children التي تتوافق مع حالات استخدام وكيل اختبار ضمان الجودة. نستخدم خادم Atlassian MCP الذي ساهم فيه المنتدى ( راجِع المستندات الكاملة لمزيد من التفاصيل) في هذا الدرس التطبيقي.

أداة "كتابة"

بعد أن يتلقّى الوكيل السياق من أداة Confluence MCP، يمكنه إنشاء خطة الاختبار اللازمة للمستخدم. ومع ذلك، نريد إنشاء ملف يحتوي على خطة الاختبار هذه حتى يمكن حفظها ومشاركتها مع الشخص الآخر. لإتاحة ذلك، نوفّر الأداة المخصّصة write_test_tool أدناه

# qa-test-planner/agent.py

...

async def write_test_tool(
    prd_id: str, test_cases: list[dict], tool_context: ToolContext
):
    """A tool to write the test plan into file

    Args:
        prd_id: Product requirement document ID
        test_cases: List of test case dictionaries that should conform to these fields:
            - test_case_key: str
            - test_type: Literal["manual","automatic"]
            - summary: str
            - preconditions: str
            - test_steps: str
            - expected_result: str
            - associated_requirements: str

    Returns:
        A message indicating success or failure of the validation and writing process
    """
    validated_test_cases = []
    validation_errors = []

    # Validate each test case
    for i, test_case in enumerate(test_cases):
        try:
            validated_test_case = TestPlan(**test_case)
            validated_test_cases.append(validated_test_case)
        except Exception as e:
            validation_errors.append(f"Error in test case {i + 1}: {str(e)}")

    # If validation errors exist, return error message
    if validation_errors:
        return {
            "status": "error",
            "message": "Validation failed",
            "errors": validation_errors,
        }

    # Write validated test cases to CSV
    try:
        # Convert validated test cases to a pandas DataFrame
        data = []
        for tc in validated_test_cases:
            data.append(
                {
                    "Test Case ID": tc.test_case_key,
                    "Type": tc.test_type,
                    "Summary": tc.summary,
                    "Preconditions": tc.preconditions,
                    "Test Steps": tc.test_steps,
                    "Expected Result": tc.expected_result,
                    "Associated Requirements": tc.associated_requirements,
                }
            )

        # Create DataFrame from the test case data
        df = pd.DataFrame(data)

        if not df.empty:
            # Create a temporary file with .csv extension
            with tempfile.NamedTemporaryFile(suffix=".csv", delete=False) as temp_file:
                # Write DataFrame to the temporary CSV file
                df.to_csv(temp_file.name, index=False)
                temp_file_path = temp_file.name

            # Read the file bytes from the temporary file
            with open(temp_file_path, "rb") as f:
                file_bytes = f.read()

            # Create an artifact with the file bytes
            await tool_context.save_artifact(
                filename=f"{prd_id}_test_plan.csv",
                artifact=types.Part.from_bytes(data=file_bytes, mime_type="text/csv"),
            )

            # Clean up the temporary file
            os.unlink(temp_file_path)

            return {
                "status": "success",
                "message": (
                    f"Successfully wrote {len(validated_test_cases)} test cases to "
                    f"CSV file: {prd_id}_test_plan.csv"
                ),
            }
        else:
            return {"status": "warning", "message": "No test cases to write"}
    except Exception as e:
        return {
            "status": "error",
            "message": f"An error occurred while writing to CSV: {str(e)}",
        }


...

تم إنشاء الدالة الموضّحة أعلاه لإتاحة الوظائف التالية:

  1. تحقَّق من خطة الاختبار التي تم إنشاؤها للتأكّد من أنّها تتوافق مع مواصفات الحقول الإلزامية، ونتحقق من ذلك باستخدام نموذج Pydantic، وفي حال حدوث خطأ، نرسل رسالة الخطأ إلى الوكيل.
  2. تصدير النتيجة إلى ملف CSV باستخدام وظيفة pandas
  3. يتم بعد ذلك حفظ الملف الذي تم إنشاؤه كعنصر باستخدام إمكانات "خدمة العناصر" التي يمكن الوصول إليها باستخدام عنصر ToolContext الذي يمكن الوصول إليه في كل طلبات الأدوات.

إذا حفظنا الملفات التي تم إنشاؤها كعنصر، سيتم وضع علامة عليها كحدث في وقت تشغيل ADK، ويمكن عرضها في تفاعل الوكيل لاحقًا على واجهة الويب.

57f5ab95f4ae86e7.png

باستخدام هذه الميزة، يمكننا إعداد استجابة الملف بشكل ديناميكي من البرنامج، ليتم تقديمها للمستخدم.

4. اختبار الوكيل

لنحاول الآن التواصل مع البرنامج من خلال واجهة سطر الأوامر، وننفّذ الأمر التالي

uv run adk run qa_test_planner

ستظهر لك نتيجة مشابهة لما يلي، حيث يمكنك التحدّث بالتناوب مع الوكيل، ولكن يمكنك إرسال نص فقط من خلال هذه الواجهة

Log setup complete: /tmp/agents_log/agent.xxxx_xxx.log
To access latest log: tail -F /tmp/agents_log/agent.latest.log
Running agent qa_test_planner_agent, type exit to exit.
user: hello
[qa_test_planner_agent]: Hello there! How can I help you today?
user: 

من الجيد أن تتمكّن من الدردشة مع الموظف من خلال واجهة سطر الأوامر. ولكن سيكون من الأفضل لو توفّرت محادثة ويب لطيفة معها، ويمكننا توفير ذلك أيضًا. تتيح لنا حزمة تطوير التطبيقات أيضًا توفير واجهة مستخدم خاصة بالمطوّرين للتفاعل مع ما يحدث أثناء التفاعل وفحصه. نفِّذ الأمر التالي لبدء خادم واجهة مستخدم التطوير المحلي

uv run adk web --port 8080

سيؤدي ذلك إلى إنشاء ناتج مثل المثال التالي، ما يعني أنّه يمكننا الوصول إلى واجهة الويب

INFO:     Started server process [xxxx]
INFO:     Waiting for application startup.

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://localhost:8080.                         |
+-----------------------------------------------------------------------------+

INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)

الآن، للتحقّق من ذلك، انقر على الزر معاينة الويب في أعلى مساحة Cloud Shell Editor واختَر معاينة على المنفذ 8080.

e7c9f56c2463164.png

ستظهر لك صفحة الويب التالية حيث يمكنك اختيار الوكلاء المتاحين من زر القائمة المنسدلة في أعلى اليمين ( في حالتنا، يجب أن يكون qa_test_planner) والتفاعل مع الروبوت. ستظهر لك العديد من المعلومات حول تفاصيل السجلّ أثناء وقت تشغيل الوكيل في النافذة اليمنى.

8ed90debb774207f.png

لنبدأ بتجربة بعض الإجراءات. يمكنك الدردشة مع الموظفين باستخدام الطلبات التالية:

  • يُرجى إدراج جميع المنتجات الترويجية المتاحة
  • " كتابة خطة اختبار لمتطلبات منتج Snaprecipe "

عند استخدام بعض الأدوات، يمكنك فحص ما يحدث في واجهة مستخدم التطوير

3469a0785b507be3.png

اطّلِع على طريقة استجابة الوكيل لك، وتفقَّد أيضًا متى نطلب ملفًا تجريبيًا، إذ سيتم إنشاء خطة الاختبار في ملف CSV كعنصر

94b73fb4d447ad62.png

يمكنك الآن التحقّق من محتوى ملف CSV من خلال استيراده إلى "جدول بيانات Google" مثلاً.

89e3fc18d6e92d82.png

تهانينا! أصبح لديك الآن وكيل "مخطّط اختبار ضمان الجودة" يعمل على جهازك. لنرى الآن كيف يمكننا نشرها على Cloud Run ليتمكّن المستخدمون الآخرون أيضًا من استخدامها.

5- النشر على Cloud Run

بالطبع، نريد الوصول إلى هذا التطبيق الرائع من أي مكان. ولإجراء ذلك، يمكننا تجميع هذا التطبيق ونشره على Cloud Run. لأغراض هذا العرض التوضيحي، سيتم عرض هذه الخدمة كخدمة عامة يمكن للآخرين الوصول إليها. ومع ذلك، يجب الأخذ في الاعتبار أنّ هذه ليست أفضل ممارسة.

819179179d974c07.jpeg

في دليل العمل الحالي، تتوفّر لدينا جميع الملفات اللازمة لنشر تطبيقاتنا على Cloud Run، وهي دليل الوكيل وDockerfile وserver.py (نص برمجي الخدمة الرئيسي)، لننشره. انتقِل إلى "وحدة Cloud Shell الطرفية" وتأكَّد من ضبط المشروع الحالي على مشروعك النشط. وإذا لم يكن كذلك، عليك استخدام الأمر gcloud configure لضبط رقم تعريف المشروع:

gcloud config set project [PROJECT_ID]

بعد ذلك، شغِّل الأمر التالي لنشره على Cloud Run.

gcloud run deploy qa-test-planner-agent \
                  --source . \
                  --port 8080 \
                  --project {YOUR_PROJECT_ID} \
                  --allow-unauthenticated \
                  --region us-central1 \
                  --update-env-vars GOOGLE_GENAI_USE_VERTEXAI=1 \
                  --update-env-vars GOOGLE_CLOUD_PROJECT={YOUR_PROJECT_ID} \
                  --update-env-vars GOOGLE_CLOUD_LOCATION=global \
                  --update-env-vars CONFLUENCE_URL={YOUR_CONFLUENCE_URL} \
                  --update-env-vars CONFLUENCE_USERNAME={YOUR_CONFLUENCE_USERNAME} \
                  --update-env-vars CONFLUENCE_TOKEN={YOUR_CONFLUENCE_TOKEN} \
                  --update-env-vars CONFLUENCE_PRD_SPACE_ID={YOUR_PRD_SPACE_ID} \
                  --memory 1G

إذا طُلب منك تأكيد إنشاء سجلّ عناصر في مستودع Docker، ما عليك سوى الإجابة بـ Y. يُرجى العِلم أنّنا نسمح بالوصول غير المصادَق عليه هنا لأنّ هذا التطبيق هو تطبيق تجريبي. ننصحك باستخدام المصادقة المناسبة لتطبيقات المؤسسة والإنتاج.

بعد اكتمال عملية النشر، من المفترض أن تحصل على رابط مشابه لما يلي:

https://qa-test-planner-agent-*******.us-central1.run.app

عند الوصول إلى عنوان URL، ستنتقل إلى واجهة مستخدم مطوّري الويب المشابهة لتلك التي تظهر عند تجربة الأداة محليًا. يمكنك المتابعة واستخدام تطبيقك من نافذة التصفّح المتخفي أو جهازك الجوّال. من المفترض أن يكون قد تم نشره.

والآن، لنحاول إدخال هذه الطلبات المختلفة مرة أخرى بالتسلسل، ونرى ما سيحدث:

  • " هل يمكنك العثور على مستند متطلبات المنتج (PRD) المتعلّق بأداة تقدير الرهن العقاري؟ "
  • " أريد الحصول على ملاحظات حول ما يمكننا تحسينه في هذا الشأن"
  • اكتب خطة الاختبار الخاصة به"

بالإضافة إلى ذلك، بما أنّنا نشغّل الوكيل كتطبيق FastAPI، يمكننا أيضًا فحص جميع مسارات واجهة برمجة التطبيقات في المسار /docs. على سبيل المثال، إذا وصلت إلى عنوان URL على النحو التالي https://qa-test-planner-agent-*******.us-central1.run.app/docs، ستظهر لك صفحة مستندات Swagger كما هو موضّح أدناه

c6f613b7bdc91ef3.png

شرح الرمز

الآن، لنفحص الملف الذي نحتاج إليه هنا للنشر، بدءًا من server.py

# server.py

import os

from fastapi import FastAPI
from google.adk.cli.fast_api import get_fast_api_app

AGENT_DIR = os.path.dirname(os.path.abspath(__file__))

app_args = {"agents_dir": AGENT_DIR, "web": True}

app: FastAPI = get_fast_api_app(**app_args)

app.title = "qa-test-planner-agent"
app.description = "API for interacting with the Agent qa-test-planner-agent"


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8080)

يمكننا بسهولة تحويل الوكيل إلى تطبيق fastapi باستخدام الدالة get_fast_api_app. في هذه الدالة، يمكننا إعداد وظائف مختلفة، مثل إعداد خدمة الجلسات أو خدمة العناصر أو حتى تتبُّع البيانات إلى السحابة الإلكترونية.

يمكنك أيضًا ضبط مدة بقاء التطبيق هنا إذا أردت. بعد ذلك، يمكننا استخدام uvicorn لتشغيل تطبيق Fast API

بعد ذلك، سيزوّدنا Dockerfile بالخطوات اللازمة لتشغيل التطبيق.

# Dockerfile

FROM python:3.12-slim

RUN pip install --no-cache-dir uv==0.7.13

WORKDIR /app

COPY . .

RUN uv sync --frozen

EXPOSE 8080

CMD ["uv", "run", "uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8080"]

6. التحدي

حان الوقت الآن للتألق وصقل مهاراتك الاستكشافية. هل يمكنك أيضًا إنشاء أداة لتسجيل الملاحظات حول مراجعة مستند متطلبات المنتج في ملف؟

7. تَنظيم

لتجنُّب تحمّل رسوم في حسابك على Google Cloud مقابل الموارد المستخدَمة في هذا الدرس العملي، اتّبِع الخطوات التالية:

  1. في Google Cloud Console، انتقِل إلى صفحة إدارة الموارد.
  2. في قائمة المشاريع، اختَر المشروع الذي تريد حذفه، ثم انقر على حذف.
  3. في مربّع الحوار، اكتب رقم تعريف المشروع، ثم انقر على إيقاف لحذف المشروع.
  4. بدلاً من ذلك، يمكنك الانتقال إلى Cloud Run في وحدة التحكّم، واختيار الخدمة التي نشرتها للتو وحذفها.