test: add comprehensive unit, integration, and e2e test suites

Introduce complete test coverage for the ARTEMIS platform across multiple layers:
Unit tests: Add tests for agent nodes (Planner, Operator, Validator, Diagnoser, FlashRunner, Explorer), tools, utils (OCR/XML fusion, UI hierarchy), and data engine.
Integration tests: Add live tool verification, reactive runner, IME, and standalone workflow tests.
E2E tests: Add end-to-end scenario tests for media playback and failure recovery flows.
Fixtures & mocks: Add mock inputs (audio, video, screenshot) and test utilities.
This commit is contained in:
chiwanko11 committed 2026-08-13 12:18:32 -07:00
1 parent c1803fcb86
commit 5d2283deaa
115 files changed
+22813

No files matched your search

@@ -0,0 +1,103 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
from artemis.agents.video_analyzer.video_analyzer import VideoAnalyzer
@pytest.mark.asyncio
async def test_video_analyzer_tools(artemis_context, mock_state, inputs_dir):
artemis_context.device.mobile_platform = "android"
artemis_context.adb_client = artemis_context.ui_adb_client
agent = VideoAnalyzer(ctx=artemis_context)
agent.local_files_to_cleanup = set()
agent.local_dirs_to_cleanup = set()
agent.cloud_files_to_cleanup = set()
agent.blackboard_entries = []
agent.sub_system_prompt = "You are a sub agent"
agent.audio_system_prompt = "You are an audio sub agent"
agent.model_name = "gemini-3.6-flash"
# We must provide a valid FunctionDeclaration for the tool otherwise Pydantic will complain
from google.genai import types
agent.submit_answer_tool = types.FunctionDeclaration(
name="submit_answer",
description=("Submit the final findings for the requested segment analysis."),
parameters=types.Schema(
type=types.Type.OBJECT,
properties={
"summary": types.Schema(type=types.Type.STRING, description="summary"),
"analysis": types.Schema(type=types.Type.STRING, description="analysis"),
"timeline_events": types.Schema(
type=types.Type.ARRAY,
items=types.Schema(
type=types.Type.OBJECT,
properties={
"start_time": types.Schema(type=types.Type.NUMBER),
"end_time": types.Schema(type=types.Type.NUMBER),
"transcription": types.Schema(type=types.Type.STRING),
"confidence_score": types.Schema(type=types.Type.NUMBER),
"verification_timestamp_secs": types.Schema(type=types.Type.NUMBER),
},
),
),
},
),
)
import google.genai as genai
from artemis.config import settings
agent.client = genai.Client(
api_key=settings.GOOGLE_API_KEY.get_secret_value() if settings.GOOGLE_API_KEY else None
)
artemis_context._genai_client = agent.client
mock_session = MagicMock()
mock_session.local_video_path = Path(inputs_dir) / "recording.mp4"
mock_session.start_time = 0.0
mock_session.data_engine_start_time = None
mock_session.process = MagicMock()
mock_session.process.returncode = None
mock_session.android_video_segments = []
mock_session.android_segment_index = 0
from unittest.mock import AsyncMock
sample_video = Path(inputs_dir) / "recording.mp4"
mock_driver = MagicMock()
mock_driver.stop_video_recording = AsyncMock(return_value=sample_video)
artemis_context._active_driver = mock_driver
with patch(
"artemis.controllers.android_controller.get_active_session",
return_value=mock_session,
):
result = await agent.exec_extract_segment_metadata(start_time=0.0, end_time=1.0)
assert isinstance(result, str)
assert len(result) > 0
# Test sub-agent with extremely short audio query to not waste resources and time
audio_result = await agent.exec_analyze_audio_only(
start_time=0.0,
end_time=1.0,
specific_query="Reply with a short summary only.",
)
assert isinstance(audio_result, str)