mcpField
P
prowler-test-sdk

prowler-test-sdk

github.com/prowler-cloudテスト・品質15.1k66 回インストール今日更新
リポジトリ

prowler-test-sdk について

prowler-test-sdk は、Prowler SDK の規約に沿ったテストを書くためのスキルです。プロバイダー別のモック方法、テスト構成、必須シナリオ、アサーション、実行コマンドを説明します。

主な機能

  1. 01AWS には moto、それ以外には MagicMock を使用
  2. 02プロバイダー別のフィクスチャパターンに準拠
  3. 03サービスとチェックのテストファイルを構成
  4. 04準拠・非準拠・リソースなしを網羅
  5. 05ステータスとリソース情報を検証
  6. 06SDK、プロバイダー、個別チェックのテストを実行

活用シーン

  1. 01新しい Prowler セキュリティチェックをテスト
  2. 02プロバイダーに合ったモック方法を選択
  3. 03リソースがない場合の動作を確認
  4. 04プロバイダーまたは個別チェックのテストを実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/prowler-cloud/prowler --skill prowler-test-sdk

インストール後、Claude Code で/prowler-test-sdkを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
aws_test.py
azure_test.py
gcp_test.py
references/
testing-docs.md

詳細

一般的なパターン:フィクスチャ、モック、パラメータ化、マーカーなど、pytest の基本的なパターンについては、pytest スキルを参照してください。 このスキルでは、Prowler 固有の規約のみを扱います。

全ドキュメント:docs/developer-guide/unit-testing.mdx

重要:プロバイダー固有のテスト

プロバイダーモック方法デコレーター
AWSmoto ライブラリ@mock_aws
Azure、GCP、K8s、その他MagicMockなし

AWS 以外のプロバイダーに moto を使わないでください。AWS に MagicMock を使わないでください。


AWS チェックのテストパターン

from unittest import mock
from boto3 import client
from moto import mock_aws
from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider


class Test_{check_name}:
    @mock_aws
    def test_no_resources(self):
        from prowler.providers.aws.services.{service}.{service}_service import {ServiceClass}

        aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

        with mock.patch(
            "prowler.providers.common.provider.Provider.get_global_provider",
            return_value=aws_provider,
        ):
            with mock.patch(
                "prowler.providers.aws.services.{service}.{check_name}.{check_name}.{service}_client",
                new={ServiceClass}(aws_provider),
            ):
                from prowler.providers.aws.services.{service}.{check_name}.{check_name} import (
                    {check_name},
                )

                check = {check_name}()
                result = check.execute()

                assert len(result) == 0

    @mock_aws
    def test_{check_name}_pass(self):
        # Setup AWS resources with moto
        {service}_client = client("{service}", region_name=AWS_REGION_US_EAST_1)
        # Create compliant resource...

        from prowler.providers.aws.services.{service}.{service}_service import {ServiceClass}

        aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

        with mock.patch(
            "prowler.providers.common.provider.Provider.get_global_provider",
            return_value=aws_provider,
        ):
            with mock.patch(
                "prowler.providers.aws.services.{service}.{check_name}.{check_name}.{service}_client",
                new={ServiceClass}(aws_provider),
            ):
                from prowler.providers.aws.services.{service}.{check_name}.{check_name} import (
                    {check_name},
                )

                check = {check_name}()
                result = check.execute()

                assert len(result) == 1
                assert result[0].status == "PASS"

    @mock_aws
    def test_{check_name}_fail(self):
        # Setup AWS resources with moto
        {service}_client = client("{service}", region_name=AWS_REGION_US_EAST_1)
        # Create non-compliant resource...

        from prowler.providers.aws.services.{service}.{service}_service import {ServiceClass}

        aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

        with mock.patch(
            "prowler.providers.common.provider.Provider.get_global_provider",
            return_value=aws_provider,
        ):
            with mock.patch(
                "prowler.providers.aws.services.{service}.{check_name}.{check_name}.{service}_client",
                new={ServiceClass}(aws_provider),
            ):
                from prowler.providers.aws.services.{service}.{check_name}.{check_name} import (
                    {check_name},
                )

                check = {check_name}()
                result = check.execute()

                assert len(result) == 1
                assert result[0].status == "FAIL"

重要:クライアントを正しくモックするため、必ず mock.patch コンテキスト内でチェックをインポートしてください。


Azure チェックのテストパターン

moto デコレーターは使用しません。MagicMock を使ってサービスクライアントを直接モックしてください。

from unittest import mock
from uuid import uuid4

from prowler.providers.azure.services.{service}.{service}_service import {ResourceModel}
from tests.providers.azure.azure_fixtures import (
    AZURE_SUBSCRIPTION_ID,
    set_mocked_azure_provider,
)


class Test_{check_name}:
    def test_no_resources(self):
        {service}_client = mock.MagicMock
        {service}_client.{resources} = {}

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_azure_provider(),
            ),
            mock.patch(
                "prowler.providers.azure.services.{service}.{check_name}.{check_name}.{service}_client",
                new={service}_client,
            ),
        ):
            from prowler.providers.azure.services.{service}.{check_name}.{check_name} import (
                {check_name},
            )

            check = {check_name}()
            result = check.execute()
            assert len(result) == 0

    def test_{check_name}_pass(self):
        resource_id = str(uuid4())
        resource_name = "Test Resource"

        {service}_client = mock.MagicMock
        {service}_client.{resources} = {
            AZURE_SUBSCRIPTION_ID: {
                resource_id: {ResourceModel}(
                    id=resource_id,
                    name=resource_name,
                    location="westeurope",
                    # ... compliant attributes
                )
            }
        }

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_azure_provider(),
            ),
            mock.patch(
                "prowler.providers.azure.services.{service}.{check_name}.{check_name}.{service}_client",
                new={service}_client,
            ),
        ):
            from prowler.providers.azure.services.{service}.{check_name}.{check_name} import (
                {check_name},
            )

            check = {check_name}()
            result = check.execute()

            assert len(result) == 1
            assert result[0].status == "PASS"
            assert result[0].subscription == AZURE_SUBSCRIPTION_ID
            assert result[0].resource_name == resource_name

    def test_{check_name}_fail(self):
        resource_id = str(uuid4())
        resource_name = "Test Resource"

        {service}_client = mock.MagicMock
        {service}_client.{resources} = {
            AZURE_SUBSCRIPTION_ID: {
                resource_id: {ResourceModel}(
                    id=resource_id,
                    name=resource_name,
                    location="westeurope",
                    # ... non-compliant attributes
                )
            }
        }

        with (
            mock.patch(
                "prowler.providers.common.provider.Provider.get_global_provider",
                return_value=set_mocked_azure_provider(),
            ),
            mock.patch(
                "prowler.providers.azure.services.{service}.{check_name}.{check_name}.{service}_client",
                new={service}_client,
            ),
        ):
            from prowler.providers.azure.services.{service}.{check_name}.{check_name} import (
                {check_name},
            )

            check = {check_name}()
            result = check.execute()

            assert len(result) == 1
            assert result[0].status == "FAIL"

GCP/Kubernetes/その他のプロバイダー

Azure と同じ MagicMock パターンに従います。

from tests.providers.gcp.gcp_fixtures import set_mocked_gcp_provider, GCP_PROJECT_ID
from tests.providers.kubernetes.kubernetes_fixtures import set_mocked_kubernetes_provider

主な違い:各プロバイダーには、set_mocked_{provider}_provider を含む独自のフィクスチャファイルがあります。


プロバイダーのフィクスチャ一覧

プロバイダーフィクスチャファイル主な定数
AWStests/providers/aws/utils.pyAWS_REGION_US_EAST_1、AWS_ACCOUNT_NUMBER
Azuretests/providers/azure/azure_fixtures.pyAZURE_SUBSCRIPTION_ID
GCPtests/providers/gcp/gcp_fixtures.pyGCP_PROJECT_ID
K8stests/providers/kubernetes/kubernetes_fixtures.py-

テストファイルの構成

tests/providers/{provider}/services/{service}/
├── {service}_service_test.py      # Service tests
└── {check_name}/
    └── {check_name}_test.py       # Check tests

注:テストフォルダーに __init__.py ファイルを作成しないでください。


必須のテストシナリオ

すべてのチェックで、次の項目をテストする必要があります。

シナリオ期待値
リソースが準拠しているstatus == "PASS"
リソースが準拠していないstatus == "FAIL"
リソースがないlen(results) == 0

含めるべきアサーション

# Always verify these
assert result[0].status == "PASS"  # or "FAIL"
assert result[0].status_extended == "Expected message..."
assert result[0].resource_id == expected_id
assert result[0].resource_name == expected_name

# Provider-specific
assert result[0].region == "us-east-1"           # AWS
assert result[0].subscription == AZURE_SUBSCRIPTION_ID  # Azure
assert result[0].project_id == GCP_PROJECT_ID    # GCP

コマンド

# All SDK tests
uv run pytest -n auto -vvv tests/

# Specific provider
uv run pytest tests/providers/{provider}/ -v

# Specific check
uv run pytest tests/providers/{provider}/services/{service}/{check_name}/ -v

# Stop on first failure
uv run pytest -x tests/

リソース

  • テンプレート:assets/ で完全なテストテンプレートを参照してください(moto を使う AWS、MagicMock を使う Azure/GCP)
  • ドキュメント:公式の Prowler Developer Guide へのリンクは references/testing-docs.md を参照してください

コメント