fixture-foundry


Namefixture-foundry JSON
Version 0.2.2 PyPI version JSON
download
home_pageNone
SummaryFixtures and helpers to create AWS infrastructure (via LocalStack) and containerized databases locally for fast, reproducible integration testing.
upload_time2025-10-08 14:37:16
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords fixtures python test-data testing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Fixture Foundry

Pytest fixtures and context managers for ephemeral integration testing infrastructure: LocalStack (AWS services), PostgreSQL containers, and Pulumi deployment automation.

## Features

- **Session-scoped fixtures**: `localstack`, `postgres`, `container_network`
- **Context managers**: Standalone infrastructure orchestration for dev scripts
- **Pulumi Automation**: `deploy()` helper targets LocalStack automatically
- **Database seeding**: `exec_sql_file()` loads SQL schemas with transaction support
- **URL translation**: `to_localstack_url()` converts AWS Gateway URLs to LocalStack endpoints
- **Auto-cleanup**: Health checks, retries, and teardown on test completion

## Installation

```bash
pip install fixture-foundry docker requests pytest psycopg2-binary
# Optional for Pulumi deployment:
pip install pulumi pulumi-aws
```

**Requirements**: Python 3.8–3.12, Docker

## Quick Start

### Setup pytest fixtures in conftest.py

```python
import pytest
from fixture_foundry import localstack, postgres, container_network  # noqa: F401

def pytest_addoption(parser):
    g = parser.getgroup("localstack")
    g.addoption("--teardown", default="true")
    g.addoption("--localstack-port", type=int, default=0)  # 0 = random port
    g.addoption("--database-image", default="postgres:16")
```

### Database with Schema Loading

```python
from pathlib import Path
import psycopg2
from fixture_foundry import postgres, exec_sql_file

@pytest.fixture(scope="session")
def test_db(postgres):
    # Load schema from SQL file
    schema_file = Path(__file__).parent / "schema.sql"
    
    conn = psycopg2.connect(postgres["dsn"])
    conn.autocommit = True  # Required for multi-statement scripts
    exec_sql_file(conn, schema_file)
    conn.close()
    
    yield postgres
```

### Pulumi Deployment to LocalStack

```python
import json
from fixture_foundry import deploy, to_localstack_url

def my_pulumi_program():
    # Your Pulumi resources here
    pulumi.export("api_url", "https://example.execute-api.us-east-1.amazonaws.com")

@pytest.fixture(scope="module") 
def api_stack(test_db, localstack):
    with deploy("my-project", "test", my_pulumi_program, localstack=localstack) as outputs:
        yield outputs

@pytest.fixture(scope="module")
def api_endpoint(api_stack, localstack):
    # Convert AWS Gateway URL to LocalStack endpoint
    aws_url = api_stack["api_url"]
    yield to_localstack_url(aws_url, localstack["port"])

def test_api_call(api_endpoint):
    import requests
    response = requests.get(f"{api_endpoint}/health")
    assert response.status_code == 200
```

### Context Managers (for dev scripts)

```python
from pathlib import Path
import psycopg2
from fixture_foundry import postgres_context, localstack_context, deploy, exec_sql_file

# Standalone usage outside pytest
with postgres_context(database="mydb") as pg:
    # Seed database with schema
    conn = psycopg2.connect(pg["dsn"])
    conn.autocommit = True
    exec_sql_file(conn, Path("schema.sql"))
    conn.close()
    
    with localstack_context() as ls:
        with deploy("proj", "stack", program, localstack=ls) as outputs:
            # Infrastructure is now running - execute your dev workflow
            api_url = outputs['endpoint']
            print(f"API deployed at: {api_url}")
            
            # Start frontend dev server, run manual tests, etc.
            # subprocess.run(["npm", "run", "dev"], env={"VITE_API_URL": api_url})
            # Or keep running for interactive development...
```

## API Reference

### Fixtures (session-scoped)

| Fixture | Yields | Description |
|---------|--------|-------------|
| `container_network` | `str` | Docker bridge network name (default: "ls-dev") |
| `postgres` | `dict` | PostgreSQL container with `dsn`, `host_port`, `container_name`, credentials |
| `localstack` | `dict` | LocalStack container with `endpoint_url`, `port`, `region`, `services` |

### Functions

| Function | Purpose |
|----------|---------|
| `deploy(project, stack, program, localstack=None, teardown=True)` | Pulumi Automation API context manager |
| `exec_sql_file(conn, path)` | Execute SQL file (supports multi-statement, `DO $$` blocks) |
| `to_localstack_url(aws_url, edge_port=4566)` | Convert AWS Gateway URL to LocalStack endpoint |

### Connection Patterns

- **Container-to-container**: Use `postgres["container_name"]:5432` (Docker network)
- **Host-to-container**: Use `localhost:{postgres["host_port"]}` (port mapping)
- **Lambda-to-DB**: Requires shared Docker network (automatic with LocalStack)

### Environment Variables

- `AWS_REGION` / `AWS_DEFAULT_REGION`: AWS region (default: us-east-1)
- `DOCKER_TEST_NETWORK`: Override network name (default: ls-dev)
- `LAMBDA_DOCKER_NETWORK`: Set by LocalStack for container connectivity

### CLI Options

Add to your `conftest.py` via `pytest_addoption()`:

- `--teardown=true|false`: Control resource cleanup
- `--localstack-port=0`: LocalStack port (0 = random)
- `--database-image=postgres:16`: PostgreSQL Docker image
- `--localstack-image=localstack/localstack:latest`: LocalStack image


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fixture-foundry",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "fixtures, python, test-data, testing",
    "author": null,
    "author_email": "Dan Repik <dan.repik@example.com>",
    "download_url": "https://files.pythonhosted.org/packages/f1/1b/18d43eec02cd5a16802ed7db044718558ab0487a41abb292150548022b62/fixture_foundry-0.2.2.tar.gz",
    "platform": null,
    "description": "# Fixture Foundry\n\nPytest fixtures and context managers for ephemeral integration testing infrastructure: LocalStack (AWS services), PostgreSQL containers, and Pulumi deployment automation.\n\n## Features\n\n- **Session-scoped fixtures**: `localstack`, `postgres`, `container_network`\n- **Context managers**: Standalone infrastructure orchestration for dev scripts\n- **Pulumi Automation**: `deploy()` helper targets LocalStack automatically\n- **Database seeding**: `exec_sql_file()` loads SQL schemas with transaction support\n- **URL translation**: `to_localstack_url()` converts AWS Gateway URLs to LocalStack endpoints\n- **Auto-cleanup**: Health checks, retries, and teardown on test completion\n\n## Installation\n\n```bash\npip install fixture-foundry docker requests pytest psycopg2-binary\n# Optional for Pulumi deployment:\npip install pulumi pulumi-aws\n```\n\n**Requirements**: Python 3.8\u20133.12, Docker\n\n## Quick Start\n\n### Setup pytest fixtures in conftest.py\n\n```python\nimport pytest\nfrom fixture_foundry import localstack, postgres, container_network  # noqa: F401\n\ndef pytest_addoption(parser):\n    g = parser.getgroup(\"localstack\")\n    g.addoption(\"--teardown\", default=\"true\")\n    g.addoption(\"--localstack-port\", type=int, default=0)  # 0 = random port\n    g.addoption(\"--database-image\", default=\"postgres:16\")\n```\n\n### Database with Schema Loading\n\n```python\nfrom pathlib import Path\nimport psycopg2\nfrom fixture_foundry import postgres, exec_sql_file\n\n@pytest.fixture(scope=\"session\")\ndef test_db(postgres):\n    # Load schema from SQL file\n    schema_file = Path(__file__).parent / \"schema.sql\"\n    \n    conn = psycopg2.connect(postgres[\"dsn\"])\n    conn.autocommit = True  # Required for multi-statement scripts\n    exec_sql_file(conn, schema_file)\n    conn.close()\n    \n    yield postgres\n```\n\n### Pulumi Deployment to LocalStack\n\n```python\nimport json\nfrom fixture_foundry import deploy, to_localstack_url\n\ndef my_pulumi_program():\n    # Your Pulumi resources here\n    pulumi.export(\"api_url\", \"https://example.execute-api.us-east-1.amazonaws.com\")\n\n@pytest.fixture(scope=\"module\") \ndef api_stack(test_db, localstack):\n    with deploy(\"my-project\", \"test\", my_pulumi_program, localstack=localstack) as outputs:\n        yield outputs\n\n@pytest.fixture(scope=\"module\")\ndef api_endpoint(api_stack, localstack):\n    # Convert AWS Gateway URL to LocalStack endpoint\n    aws_url = api_stack[\"api_url\"]\n    yield to_localstack_url(aws_url, localstack[\"port\"])\n\ndef test_api_call(api_endpoint):\n    import requests\n    response = requests.get(f\"{api_endpoint}/health\")\n    assert response.status_code == 200\n```\n\n### Context Managers (for dev scripts)\n\n```python\nfrom pathlib import Path\nimport psycopg2\nfrom fixture_foundry import postgres_context, localstack_context, deploy, exec_sql_file\n\n# Standalone usage outside pytest\nwith postgres_context(database=\"mydb\") as pg:\n    # Seed database with schema\n    conn = psycopg2.connect(pg[\"dsn\"])\n    conn.autocommit = True\n    exec_sql_file(conn, Path(\"schema.sql\"))\n    conn.close()\n    \n    with localstack_context() as ls:\n        with deploy(\"proj\", \"stack\", program, localstack=ls) as outputs:\n            # Infrastructure is now running - execute your dev workflow\n            api_url = outputs['endpoint']\n            print(f\"API deployed at: {api_url}\")\n            \n            # Start frontend dev server, run manual tests, etc.\n            # subprocess.run([\"npm\", \"run\", \"dev\"], env={\"VITE_API_URL\": api_url})\n            # Or keep running for interactive development...\n```\n\n## API Reference\n\n### Fixtures (session-scoped)\n\n| Fixture | Yields | Description |\n|---------|--------|-------------|\n| `container_network` | `str` | Docker bridge network name (default: \"ls-dev\") |\n| `postgres` | `dict` | PostgreSQL container with `dsn`, `host_port`, `container_name`, credentials |\n| `localstack` | `dict` | LocalStack container with `endpoint_url`, `port`, `region`, `services` |\n\n### Functions\n\n| Function | Purpose |\n|----------|---------|\n| `deploy(project, stack, program, localstack=None, teardown=True)` | Pulumi Automation API context manager |\n| `exec_sql_file(conn, path)` | Execute SQL file (supports multi-statement, `DO $$` blocks) |\n| `to_localstack_url(aws_url, edge_port=4566)` | Convert AWS Gateway URL to LocalStack endpoint |\n\n### Connection Patterns\n\n- **Container-to-container**: Use `postgres[\"container_name\"]:5432` (Docker network)\n- **Host-to-container**: Use `localhost:{postgres[\"host_port\"]}` (port mapping)\n- **Lambda-to-DB**: Requires shared Docker network (automatic with LocalStack)\n\n### Environment Variables\n\n- `AWS_REGION` / `AWS_DEFAULT_REGION`: AWS region (default: us-east-1)\n- `DOCKER_TEST_NETWORK`: Override network name (default: ls-dev)\n- `LAMBDA_DOCKER_NETWORK`: Set by LocalStack for container connectivity\n\n### CLI Options\n\nAdd to your `conftest.py` via `pytest_addoption()`:\n\n- `--teardown=true|false`: Control resource cleanup\n- `--localstack-port=0`: LocalStack port (0 = random)\n- `--database-image=postgres:16`: PostgreSQL Docker image\n- `--localstack-image=localstack/localstack:latest`: LocalStack image\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Fixtures and helpers to create AWS infrastructure (via LocalStack) and containerized databases locally for fast, reproducible integration testing.",
    "version": "0.2.2",
    "project_urls": {
        "Homepage": "https://github.com/DanRepik/fixture_foundry",
        "Issues": "https://github.com/DanRepik/fixture_foundry/issues",
        "Repository": "https://github.com/DanRepik/fixture_foundry"
    },
    "split_keywords": [
        "fixtures",
        " python",
        " test-data",
        " testing"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "98bb110f790989f82237c595e8fd1f1558690bc0c337080451a04a336e313fef",
                "md5": "1e711a983d1f35e297fc4b4e117fd4d2",
                "sha256": "623a875a85b476f5d7e94fcb7cf51e585c673463970bea1d0f19c711a9d62c04"
            },
            "downloads": -1,
            "filename": "fixture_foundry-0.2.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1e711a983d1f35e297fc4b4e117fd4d2",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 14249,
            "upload_time": "2025-10-08T14:37:17",
            "upload_time_iso_8601": "2025-10-08T14:37:17.083846Z",
            "url": "https://files.pythonhosted.org/packages/98/bb/110f790989f82237c595e8fd1f1558690bc0c337080451a04a336e313fef/fixture_foundry-0.2.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f11b18d43eec02cd5a16802ed7db044718558ab0487a41abb292150548022b62",
                "md5": "c707d33be7b306a5b3dbdfd2a1fc19ab",
                "sha256": "d710476b3376585195adbec46b19ad40fc4ea5235d24efabc802dd7730a78c62"
            },
            "downloads": -1,
            "filename": "fixture_foundry-0.2.2.tar.gz",
            "has_sig": false,
            "md5_digest": "c707d33be7b306a5b3dbdfd2a1fc19ab",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 25002,
            "upload_time": "2025-10-08T14:37:16",
            "upload_time_iso_8601": "2025-10-08T14:37:16.147538Z",
            "url": "https://files.pythonhosted.org/packages/f1/1b/18d43eec02cd5a16802ed7db044718558ab0487a41abb292150548022b62/fixture_foundry-0.2.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-08 14:37:16",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "DanRepik",
    "github_project": "fixture_foundry",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "fixture-foundry"
}
        
Elapsed time: 3.50118s