yomitalk / tests /e2e /conftest.py
Kyosuke Ichikawa
refactor: remove unused methods identified by vulture (#6)
c3b6480 unverified
"""E2Eテスト用のフィクスチャとユーティリティ。
テスト環境の初期化とページオブジェクトを提供します。
元々 tests/e2e/steps/conftest.py に分かれていた機能を統合しています。
"""
import os
import time
from pathlib import Path
from typing import Generator
import pytest
from playwright.sync_api import Browser, Page, sync_playwright
from tests.utils.logger import test_logger as logger
from tests.utils.test_environment import TestEnvironment
from yomitalk.components.audio_generator import initialize_global_voicevox_manager
# Test data path
TEST_DATA_DIR = Path(__file__).parent.parent / "data"
@pytest.fixture(scope="session", autouse=True)
def initialize_voicevox():
"""Initialize global VOICEVOX manager for all tests."""
try:
manager = initialize_global_voicevox_manager()
if manager:
logger.info("Global VOICEVOX manager initialized successfully for tests")
else:
logger.warning("VOICEVOX manager initialization returned None")
except Exception as e:
logger.warning(f"VOICEVOX initialization failed in tests: {e}")
yield
# No cleanup needed as this is a global singleton
@pytest.fixture(scope="session", autouse=True)
def app_environment() -> Generator[TestEnvironment, None, None]:
"""
バックエンド側のテスト環境を提供するフィクスチャ
セッション全体で一度だけアプリケーションを起動し、
全テスト終了時に自動的に終了する
"""
test_env = TestEnvironment()
try:
# バックエンド側のテスト環境のセットアップ
app_url = test_env.setup()
logger.info(f"Application backend is running at {app_url}")
yield test_env # テスト実行を許可、TestEnvironmentインスタンスを返す
except Exception as e:
# セットアップに失敗した場合の詳細エラー表示
logger.error(f"ERROR setting up test environment: {e}")
raise
finally:
# 必ず後片付けを実行
test_env.teardown()
@pytest.fixture(scope="function")
def page(browser: Browser) -> Generator[Page, None, None]:
"""
Provides a test page fixture
This creates a new page for each test function but does not navigate to any URL.
Navigation should be handled by the 'the application is running' step in the Background
section of each feature file.
Args:
browser: Playwright browser instance
Returns:
Page: Configured page object
"""
# Create page
page = browser.new_page(viewport={"width": 1280, "height": 720})
# Set timeout
page.set_default_timeout(8000) # 8 seconds
yield page
# Close page after test completion
page.close()
@pytest.fixture(scope="session")
def browser():
"""
ブラウザインスタンスを提供するフィクスチャ
Returns:
Browser: Playwrightブラウザインスタンス
"""
with sync_playwright() as playwright:
# Launch browser with optimized settings for faster execution
launch_args = [
"--no-sandbox",
"--disable-dev-shm-usage",
"--disable-gpu",
"--disable-extensions",
"--disable-background-timer-throttling",
"--disable-backgrounding-occluded-windows",
"--disable-renderer-backgrounding",
"--disable-features=TranslateUI",
"--disable-component-extensions-with-background-pages",
]
if os.environ.get("HEADLESS", "true").lower() == "true":
browser = playwright.chromium.launch(headless=True, args=launch_args)
else:
browser = playwright.chromium.launch(
headless=False,
slow_mo=50, # Reduced from 100
args=launch_args,
)
yield browser
# セッション終了時にブラウザを閉じる
browser.close()
def pytest_bdd_apply_tag(tag, function):
"""
タグに基づいてテストをスキップするためのフック
Args:
tag: BDDタグ
function: テスト関数(未使用)
Returns:
bool: スキップするかどうか
"""
if tag == "skip":
return pytest.mark.skip(reason="明示的にスキップされました")
if tag == "slow" and os.environ.get("SKIP_SLOW_TESTS", "false").lower() == "true":
return pytest.mark.skip(reason="遅いテストはスキップします")
return None
def pytest_bdd_step_error(request, feature, scenario, step, step_func, step_func_args, exception):
"""
ステップが失敗した場合のフック
Args:
request: Pytestリクエストオブジェクト
feature: BDD機能(未使用)
scenario: BDDシナリオ
step: BDDステップ
step_func: ステップ関数(未使用)
step_func_args: ステップ関数引数
exception: 発生した例外(未使用)
"""
logger.error(f"Error in step: {step}")
# Playwrightページオブジェクトが存在する場合、スクリーンショットを撮る
page = step_func_args.get("page")
if page and hasattr(page, "screenshot"):
screenshot_dir = os.path.join("tests", "e2e", "screenshots")
os.makedirs(screenshot_dir, exist_ok=True)
scenario_name = scenario.name.replace(" ", "_")
step_name = step.name.replace(" ", "_")
timestamp = int(time.time())
screenshot_path = os.path.join(screenshot_dir, f"error_{scenario_name}_{step_name}_{timestamp}.png")
page.screenshot(path=screenshot_path)
logger.error(f"スクリーンショットが保存されました: {screenshot_path}")