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.
127 lines
4.3 KiB
Python
127 lines
4.3 KiB
Python
# 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.
|
|
|
|
import asyncio
|
|
import base64
|
|
import logging
|
|
import os
|
|
import sys
|
|
from dotenv import load_dotenv
|
|
|
|
# Ensure we can import from project
|
|
sys.path.append(os.path.dirname(__file__))
|
|
|
|
from artemis.sdk import Agent
|
|
from artemis.sdk.builders import Builders
|
|
from artemis.sdk.types import AgentProfile
|
|
from artemis.context import ArtemisContext
|
|
from artemis.graph.state import State
|
|
from artemis.agents.validator.failure_analyzer import FailureAnalyzer, ValidationErrorCategory
|
|
from artemis.controllers.unified_controller import UnifiedMobileController
|
|
from artemis.utils.notes import get_note_file_path
|
|
|
|
logging.basicConfig(level=logging.INFO)
|
|
logger = logging.getLogger("test_fa_standalone")
|
|
|
|
|
|
async def main():
|
|
load_dotenv()
|
|
|
|
# 1. Initialize Agent to set up device and connection pools
|
|
logger.info("Initializing Agent and connecting to device...")
|
|
profile = AgentProfile(name="default", from_file="llm-config.override.jsonc")
|
|
config = Builders.AgentConfig.with_default_profile(profile).build()
|
|
|
|
agent = Agent(config=config)
|
|
await agent.init()
|
|
|
|
# Create the ArtemisContext manually using agent's initialized clients
|
|
context = ArtemisContext(
|
|
device=agent._device_context,
|
|
adb_client=agent._adb_client,
|
|
ui_adb_client=agent._ui_adb_client,
|
|
llm_config=profile.llm_config,
|
|
agent_config=config,
|
|
)
|
|
|
|
# Set up trace session and data engine
|
|
from artemis.data_engine.engine import DataEngine
|
|
|
|
data_engine = DataEngine(ctx=context)
|
|
context.data_engine = data_engine
|
|
data_engine.start_session(goal="Play a video in full screen on YouTube in Chrome")
|
|
|
|
# Write the task plan note
|
|
task_plan_content = (
|
|
"- [ ] Open Chrome and navigate to the YouTube website (youtube.com)\n"
|
|
"- [ ] Select and play any video\n"
|
|
"- [ ] Make the playing video full screen"
|
|
)
|
|
task_plan_path = get_note_file_path(data_engine.base_dir, "task_plan")
|
|
task_plan_path.parent.mkdir(parents=True, exist_ok=True)
|
|
task_plan_path.write_text(task_plan_content, encoding="utf-8")
|
|
|
|
# 2. Get initial screenshot
|
|
controller = UnifiedMobileController(context)
|
|
screen_data = await controller.controller.get_screen_data()
|
|
screenshot_b64 = screen_data.base64
|
|
|
|
# Set up State
|
|
state = State(
|
|
messages=[],
|
|
initial_goal="Play a video in full screen on YouTube in Chrome",
|
|
latest_ui_hierarchy=screen_data.elements,
|
|
latest_screenshot=str(
|
|
data_engine.get_image_path(
|
|
data_engine.get_or_create_image(base64.b64decode(screenshot_b64))
|
|
)
|
|
),
|
|
focused_app_info="",
|
|
device_date="",
|
|
structured_decisions="",
|
|
complete_subgoals_by_ids=[],
|
|
validator_messages=[],
|
|
)
|
|
|
|
# 3. Instantiate and run Failure Analyzer directly
|
|
logger.info("Starting Failure Analyzer directly...")
|
|
analyzer = FailureAnalyzer(context)
|
|
analyzer.max_iterations = 45
|
|
|
|
# We pass a dummy failed action representing the fullscreen button tap
|
|
dummy_failed_action = {
|
|
"action": "tap",
|
|
"coordinates": [968, 883],
|
|
"target_text": "fullscreen button",
|
|
}
|
|
|
|
try:
|
|
result = await analyzer.analyze(
|
|
state=state,
|
|
failed_action=dummy_failed_action,
|
|
error_msg="Simulated launch failure to trigger standalone FA run",
|
|
pre_screenshot=screenshot_b64,
|
|
post_screenshot=screenshot_b64,
|
|
error_category=ValidationErrorCategory.TARGET_DISAPPEARED,
|
|
)
|
|
logger.info(f"Failure Analyzer direct execution finished! Result: {result}")
|
|
except Exception:
|
|
logger.exception("Error during Failure Analyzer execution:")
|
|
finally:
|
|
await agent.clean()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|