New to Claude Skills? Learn how to install them →

Pprowler-cloud on GitHub

Prowler Test SDK

Free

Streamline unit testing for Prowler SDK components.

Get this skill

Free · Opens the source repo

What Prowler Test SDK does

The Prowler Test SDK is designed specifically for developers working with the Prowler SDK, providing essential testing patterns and conventions for unit tests. It focuses on ensuring that checks and services for various cloud providers—particularly AWS, Azure, and GCP—are thoroughly tested. By utilizing this SDK, developers can implement effective testing strategies that adhere to provider-specific requirements, enhancing the reliability of their cloud security checks.

This skill includes provider-specific mocking rules that are critical for testing. For AWS, it leverages the moto library to mock AWS services, while for Azure and GCP, it employs MagicMock. The SDK emphasizes the importance of using the correct mocking approach for each provider to avoid potential pitfalls, such as using moto for non-AWS providers, which is explicitly discouraged. This guidance is crucial for maintaining the integrity of your tests and ensuring that they accurately reflect the behavior of the services being tested.

Included in the SDK are example test patterns that illustrate how to set up and execute tests for AWS and Azure services. These examples serve as a practical reference for developers, making it easier to implement their own tests. The documentation provides a comprehensive guide on unit testing with the Prowler SDK, ensuring that users have the resources they need to effectively validate their implementations.

Overall, the Prowler Test SDK is an invaluable tool for developers looking to implement robust unit testing for their cloud security checks, particularly in environments leveraging AWS, Azure, and GCP.

When to use it

Use this skill when developing and testing components of the Prowler SDK, especially when dealing with AWS, Azure, or GCP services.

When not to use it

This skill is not suitable for testing non-Prowler SDK components or when working with cloud providers outside of AWS, Azure, and GCP.

What you can build with it

Testing AWS Checks

Developers can use the Prowler Test SDK to implement unit tests for AWS checks using `moto` for accurate service mocking.

Validating Azure Services

The SDK allows for effective testing of Azure services by utilizing `MagicMock` to simulate Azure service responses.

Ensuring GCP Compliance

Use the Prowler Test SDK to create unit tests for GCP checks, ensuring compliance and functionality across cloud environments.

How to install Prowler Test SDK

View source

1. Install with the skills CLI

npx skills add prowler-cloud/prowler/prowler-test-sdk --agent claude-code

2. Or install it manually

Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.

Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs

Inside SKILL.md

Written by prowler-cloud

Generic Patterns: For base pytest patterns (fixtures, mocking, parametrize, markers), see the pytest skill. This skill covers Prowler-specific conventions only.

Full Documentation: docs/developer-guide/unit-testing.mdx

CRITICAL: Provider-Specific Testing

ProviderMocking ApproachDecorator
AWSmoto library@mock_aws
Azure, GCP, K8s, othersMagicMockNone

NEVER use moto for non-AWS providers. NEVER use MagicMock for AWS.


AWS Check Test Pattern

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"

Critical: Always import the check INSIDE the mock.patch context to ensure proper client mocking.


Azure Check Test Pattern

NO moto decorator. Use MagicMock to mock the service client directly.

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/Other Providers

Follow the same MagicMock pattern as Azure:

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

Key difference: Each provider has its own fixtures file with set_mocked_{provider}_provider.


Provider Fixtures Reference

ProviderFixtures FileKey Constants
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-

Test File Structure

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

NOTE: Do not create a __init__.py file in the test folder.


Required Test Scenarios

Every check MUST test:

ScenarioExpected
Resource compliantstatus == "PASS"
Resource non-compliantstatus == "FAIL"
No resourceslen(results) == 0

Assertions to Include

# 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

Commands

# 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/

Resources

  • Templates: See assets/ for complete test templates (AWS with moto, Azure/GCP with MagicMock)
  • Documentation: See references/testing-docs.md for official Prowler Developer Guide links

Frequently asked questions about Prowler Test SDK

Similar skills