Modern QA2026Comprehensive Drift Scanner — tiles
Log inJoin
81 / 89 · 04 API & Contract Testing with AI · Schema Drift Detection← prev⊞ allnext →☰ Read as one page

12.5Comprehensive Drift Scanner

class FullDriftScanner:
    """Scan all endpoints for all types of drift."""

    def __init__(self, spec: dict, base_url: str, auth_token: str = None):
        self.spec = spec
        self.base_url = base_url
        self.headers = {}
        if auth_token:
            self.headers["Authorization"] = f"Bearer {auth_token}"

    def scan_all(self) -> dict:
        """Scan every endpoint in the spec."""
        report = {
            "timestamp": datetime.now().isoformat(),
            "base_url": self.base_url,
            "endpoints_scanned": 0,
            "drifts": [],
        }

        for path, methods in self.spec["paths"].items():
            for method, details in methods.items():
                if method not in ("get", "post", "put", "patch", "delete"):
                    continue

                report["endpoints_scanned"] += 1

                try:
                    drifts = self.check_endpoint(path, method, details)
                    report["drifts"].extend(drifts)
                except Exception as e:
                    report["drifts"].append(Drift(
                        type="SCAN_ERROR",
                        field=f"{method.upper()} {path}",
                        severity="MEDIUM",
                        message=f"Could not scan: {e}"
                    ))

        return report

    def check_endpoint(self, path, method, details) -> list[Drift]:
        """Check a single endpoint for drift."""
        drifts = []

        # Check response schema drift
        if "200" in details.get("responses", {}):
            response_drifts = self.check_response_drift(path, method, details)
            drifts.extend(response_drifts)

        # Check if documented error codes are actually returned
        for status_code in details.get("responses", {}):
            if status_code.startswith("4") or status_code.startswith("5"):
                # Attempt to trigger this error code
                pass  # Requires endpoint-specific logic

        return drifts