ホームページ >バックエンド開発 >Python チュートリアル >テスト自動化における Python の型付きパラメーター化デコレーター

テスト自動化における Python の型付きパラメーター化デコレーター

Patricia Arquette
Patricia Arquetteオリジナル
2025-01-22 20:12:14514ブラウズ

Python Typed Parameterized Decorators in Test Automation

Python のデコレータ メカニズムと最新の型ヒント機能を組み合わせることで、テストの自動化が大幅に向上します。 Python の柔軟性と typing モジュールのタイプ セーフを活用したこの強力な組み合わせにより、より保守しやすく、読みやすく、堅牢なテスト スイートが実現します。この記事では、テスト自動化フレームワーク内での応用に焦点を当てながら、高度なテクニックについて説明します。

typing モジュールの拡張機能の活用

typing モジュールは大幅な改善を受けました:

  • PEP 585: 標準コレクションのジェネリック型のネイティブ サポートにより、共通型の typing モジュールへの依存が最小限に抑えられます。
  • PEP 604: | 演算子は Union 型の注釈を簡素化します。
  • PEP 647: TypeAlias は型別名の定義を明確にします。
  • PEP 649: 注釈評価の遅延により、大規模プロジェクトの起動が高速化されます。

型指定されたパラメータ化されたデコレータの構築

これらの更新された入力機能を使用してデコレーターを作成する方法は次のとおりです。

<code class="language-python">from typing import Protocol, TypeVar, Generic, Callable, Any
from functools import wraps

# TypeVar for generic typing
T = TypeVar('T')

# Protocol for defining function structure
class TestProtocol(Protocol):
    def __call__(self, *args: Any, **kwargs: Any) -> Any:
        ...

def generic_decorator(param: str) -> Callable[[Callable[..., T]], Callable[..., T]]:
    """
    Generic decorator for functions returning type T.

    Args:
        param:  A string parameter.

    Returns:
        A callable wrapping the original function.
    """
    def decorator(func: Callable[..., T]) -> Callable[..., T]:
        @wraps(func)  # Preserves original function metadata
        def wrapper(*args: Any, **kwargs: Any) -> T:
            print(f"Decorator with param: {param}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@generic_decorator("test_param")
def test_function(x: int) -> int:
    """Returns input multiplied by 2."""
    return x * 2</code>

このデコレータは Protocol を使用してテスト関数の構造を定義し、テスト フレームワークでのさまざまな関数シグネチャの柔軟性を高めます。

テスト自動化へのデコレータの適用

これらのデコレーターがテストの自動化をどのように強化するかを調べてみましょう:

1. Literal

を使用したプラットフォーム固有のテスト
<code class="language-python">from typing import Literal, Callable, Any
import sys

def run_only_on(platform: Literal["linux", "darwin", "win32"]) -> Callable:
    """
    Runs a test only on the specified platform.

    Args:
        platform: Target platform.

    Returns:
        A callable wrapping the test function.
    """
    def decorator(func: Callable) -> Callable:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            if sys.platform == platform:
                return func(*args, **kwargs)
            print(f"Skipping test on platform: {sys.platform}")
            return None
        return wrapper
    return decorator

@run_only_on("linux")
def test_linux_feature() -> None:
    """Linux-specific test."""
    pass</code>

Literal は、型チェッカーが有効な platform 値を認識することを保証し、どのテストがどのプラットフォームで実行されるかを明確にし、クロスプラットフォーム テストにとって重要です。

2.スレッド化を使用したタイムアウト デコレータ

<code class="language-python">from typing import Callable, Any, Optional
import threading
import time
from concurrent.futures import ThreadPoolExecutor, TimeoutError

def timeout(seconds: int) -> Callable:
    """
    Enforces a timeout on test functions.

    Args:
        seconds: Maximum execution time.

    Returns:
        A callable wrapping the function with timeout logic.
    """
    def decorator(func: Callable) -> Callable:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Optional[Any]:
            with ThreadPoolExecutor(max_workers=1) as executor:
                future = executor.submit(func, *args, **kwargs)
                try:
                    return future.result(timeout=seconds)
                except TimeoutError:
                    print(f"Function {func.__name__} timed out after {seconds} seconds")
                    return None
        return wrapper
    return decorator

@timeout(5)
def test_long_running_operation() -> None:
    """Test that times out if it takes too long."""
    time.sleep(10)  # Triggers timeout</code>

これは、テストの実行時間を制御する際に不可欠な、信頼性の高いタイムアウト機能のためにスレッドを使用します。

3. Union タイプを使用した再試行メカニズム

<code class="language-python">from typing import Callable, Any, Union, Type, Tuple, Optional
import time

def retry_on_exception(
    exceptions: Union[Type[Exception], Tuple[Type[Exception], ...]], 
    attempts: int = 3,
    delay: float = 1.0
) -> Callable:
    """
    Retries a function on specified exceptions.

    Args:
        exceptions: Exception type(s) to catch.
        attempts: Maximum retry attempts.
        delay: Delay between attempts.

    Returns:
        A callable wrapping the function with retry logic.
    """
    def decorator(func: Callable) -> Callable:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            last_exception: Optional[Exception] = None
            for attempt in range(attempts):
                try:
                    return func(*args, **kwargs)
                except exceptions as e:
                    last_exception = e
                    print(f"Attempt {attempt + 1} failed with {type(e).__name__}: {str(e)}")
                    time.sleep(delay)
            if last_exception:
                raise last_exception
        return wrapper
    return decorator

@retry_on_exception(Exception, attempts=5)
def test_network_connection() -> None:
    """Test network connection with retry logic."""
    pass</code>

この洗練されたバージョンでは、包括的な型ヒント、堅牢な例外処理、構成可能な再試行遅延が使用されます。 Union タイプを使用すると、例外タイプを柔軟に指定できます。

結論

Python の高度な型指定機能をデコレーターに統合すると、型安全性とコードの可読性の両方が向上し、テスト自動化フレームワークが大幅に強化されます。 明示的な型定義により、適切なエラー処理とパフォーマンス制約を備えた正しい条件下でテストが実行されることが保証されます。これにより、より堅牢で保守性が高く、効率的なテストが可能になり、特に大規模な分散テスト環境、またはマルチプラットフォームのテスト環境で価値があります。

以上がテスト自動化における Python の型付きパラメーター化デコレーターの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。