Heim > Backend-Entwicklung > Python-Tutorial > Python-typisierte parametrisierte Dekoratoren in der Testautomatisierung

Python-typisierte parametrisierte Dekoratoren in der Testautomatisierung

Patricia Arquette
Freigeben: 2025-01-22 20:12:14
Original
510 Leute haben es durchsucht

Python Typed Parameterized Decorators in Test Automation

Der Dekoratormechanismus von Python verbessert in Kombination mit modernen Typhinweisfunktionen die Testautomatisierung erheblich. Diese leistungsstarke Kombination nutzt die Flexibilität von Python und die Typensicherheit des typing-Moduls und führt zu wartbareren, lesbareren und robusteren Testsuiten. In diesem Artikel werden fortgeschrittene Techniken untersucht, wobei der Schwerpunkt auf deren Anwendung innerhalb von Testautomatisierungs-Frameworks liegt.

Nutzung der Verbesserungen des typing Moduls

Das Modul typing wurde erheblich verbessert:

  • PEP 585: Native Unterstützung für generische Typen in Standardsammlungen minimiert die Abhängigkeit vom typing-Modul für gängige Typen.
  • PEP 604: Der |-Operator vereinfacht Annotationen vom Typ Union.
  • PEP 647: TypeAlias klärt Typaliasdefinitionen.
  • PEP 649: Die verzögerte Anmerkungsauswertung beschleunigt den Start großer Projekte.

Gebäudetypisierte parametrisierte Dekorateure

So erstellen Sie einen Dekorateur mit diesen aktualisierten Eingabefunktionen:

<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>
Nach dem Login kopieren

Dieser Dekorator verwendet Protocol, um die Struktur einer Testfunktion zu definieren und so die Flexibilität für verschiedene Funktionssignaturen in Test-Frameworks zu erhöhen.

Anwenden von Dekoratoren auf die Testautomatisierung

Lassen Sie uns untersuchen, wie diese Dekoratoren die Testautomatisierung verbessern:

1. Plattformspezifische Tests mit 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>
Nach dem Login kopieren

Literal stellt sicher, dass Typprüfer gültige platform Werte erkennen und verdeutlicht, welche Tests auf welchen Plattformen ausgeführt werden – entscheidend für plattformübergreifende Tests.

2. Timeout-Dekoratoren mit Threading

<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>
Nach dem Login kopieren

Dies nutzt Threading für eine zuverlässige Timeout-Funktionalität, die für die Kontrolle der Testausführungszeit unerlässlich ist.

3. Wiederholungsmechanismus mit Union-Typen

<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>
Nach dem Login kopieren

Diese verfeinerte Version verwendet umfassende Typhinweise, eine robuste Ausnahmebehandlung und eine konfigurierbare Wiederholungsverzögerung. UnionTypen ermöglichen Flexibilität bei der Angabe von Ausnahmetypen.

Fazit

Die Integration der erweiterten Eingabefunktionen von Python in Dekoratoren verbessert sowohl die Typsicherheit als auch die Lesbarkeit des Codes und verbessert so die Testautomatisierungs-Frameworks erheblich. Explizite Typdefinitionen stellen sicher, dass Tests unter korrekten Bedingungen mit angemessener Fehlerbehandlung und Leistungseinschränkungen ausgeführt werden. Dies führt zu robusteren, wartbareren und effizienteren Tests, was insbesondere in großen, verteilten oder plattformübergreifenden Testumgebungen wertvoll ist.

Das obige ist der detaillierte Inhalt vonPython-typisierte parametrisierte Dekoratoren in der Testautomatisierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage