{"id":46365339,"url":"https://github.com/axiomantic/bigfoot","last_synced_at":"2026-04-01T19:31:17.026Z","repository":{"id":342023151,"uuid":"1172483420","full_name":"axiomantic/bigfoot","owner":"axiomantic","description":"Full-certainty test mocking: every call recorded and verified","archived":false,"fork":false,"pushed_at":"2026-03-26T19:17:01.000Z","size":5638,"stargazers_count":0,"open_issues_count":18,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T23:40:54.577Z","etag":null,"topics":["full-certainty-testing","http-testing","integration-testing","interaction-testing","mocking","pytest","pytest-plugin","python","test-automation","test-doubles","test-framework","testing"],"latest_commit_sha":null,"homepage":"https://axiomantic.github.io/bigfoot/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axiomantic.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["axiomantic"]}},"created_at":"2026-03-04T11:08:20.000Z","updated_at":"2026-03-26T19:16:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/axiomantic/bigfoot","commit_stats":null,"previous_names":["axiomantic/bigfoot"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/axiomantic/bigfoot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomantic%2Fbigfoot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomantic%2Fbigfoot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomantic%2Fbigfoot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomantic%2Fbigfoot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axiomantic","download_url":"https://codeload.github.com/axiomantic/bigfoot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axiomantic%2Fbigfoot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291146,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["full-certainty-testing","http-testing","integration-testing","interaction-testing","mocking","pytest","pytest-plugin","python","test-automation","test-doubles","test-framework","testing"],"created_at":"2026-03-05T02:14:28.743Z","updated_at":"2026-04-01T19:31:17.009Z","avatar_url":"https://github.com/axiomantic.png","language":"Python","funding_links":["https://github.com/sponsors/axiomantic"],"categories":[],"sub_categories":[],"readme":"# bigfoot\n\n[![CI](https://github.com/axiomantic/bigfoot/actions/workflows/ci.yml/badge.svg)](https://github.com/axiomantic/bigfoot/actions/workflows/ci.yml)\n[![PyPI](https://img.shields.io/pypi/v/bigfoot)](https://pypi.org/project/bigfoot/)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\n\u003c!-- CHANGED: New opening description repositioned as unittest.mock replacement --\u003e\n\n**bigfoot replaces `unittest.mock` with full-certainty test mocking for Python.**\n\nDrop-in mocking that catches the bugs `unittest.mock` silently ignores. bigfoot intercepts every external call your code makes and forces your tests to account for all of them. It ships with plugins for HTTP, subprocess, database, socket, Redis, SMTP, WebSocket, logging, and more. It enforces three guarantees that `unittest.mock` and most mocking libraries leave silent:\n\n\u003c!-- END CHANGED --\u003e\n\n1. **Every call must be pre-authorized.** Code makes a call with no registered mock? `UnmockedInteractionError`, immediately.\n2. **Every recorded interaction must be explicitly asserted.** Forget to assert an interaction? `UnassertedInteractionsError` at teardown.\n3. **Every registered mock must actually be triggered.** Register a mock that never fires? `UnusedMocksError` at teardown.\n\n\u003c!-- NEW SECTION: Why Not unittest.mock? --\u003e\n\n## Why Not unittest.mock?\n\n`unittest.mock` is designed for flexibility. bigfoot is designed for correctness. Here is what `unittest.mock` silently allows that bigfoot catches:\n\n| Scenario | unittest.mock | bigfoot |\n|----------|---------------|---------|\n| Mocked function is never called | Test passes silently | `UnusedMocksError` at teardown |\n| Mocked function called with wrong args | `assert_called_with` only if you remember to add it | Recorded and required to be asserted with exact args |\n| Real HTTP/DB/Redis call leaks through | Nothing happens (call goes to production) | `UnmockedInteractionError` immediately |\n| You forget to assert a call happened | Test passes silently | `UnassertedInteractionsError` at teardown |\n| Mock returns wrong type, caller doesn't notice | `MagicMock` auto-generates attributes forever | Not applicable; you declare explicit return values |\n| Production code adds a new external call | Existing tests still pass, new call is untested | `UnmockedInteractionError` forces you to handle it |\n\n**The core problem:** `unittest.mock` makes it your responsibility to remember what to assert. bigfoot makes it impossible to forget.\n\n```python\n# unittest.mock -- this test passes, but proves nothing\nfrom unittest.mock import patch\n\n@patch(\"myapp.payments.httpx.post\")\ndef test_payment(mock_post):\n    mock_post.return_value.json.return_value = {\"id\": \"ch_123\"}\n    create_charge(5000)\n    # Forgot assert_called_with? Test passes.\n    # Called with wrong amount? Test passes.\n    # Added a second HTTP call? Test passes.\n\n# bigfoot -- every interaction is accounted for\ndef test_payment():\n    bigfoot.http.mock_response(\"POST\", \"https://api.stripe.com/v1/charges\",\n                               json={\"id\": \"ch_123\"}, status=200)\n\n    with bigfoot:\n        result = create_charge(5000)\n\n    # MUST assert this or test fails at teardown\n    bigfoot.http.assert_request(\n        \"POST\", \"https://api.stripe.com/v1/charges\",\n        headers=IsInstance(dict), body='{\"amount\": 5000}',\n    ).assert_response(200, IsInstance(dict), '{\"id\": \"ch_123\"}')\n    assert result[\"id\"] == \"ch_123\"\n```\n\n\u003c!-- END NEW SECTION --\u003e\n\n**Firewall mode** (enabled by default) goes further: bigfoot installs interceptors at test session startup, catching any real I/O call that happens outside a sandbox. In the default `\"warn\"` level, accidental calls emit a `GuardedCallWarning` and proceed normally, so existing test suites keep working while you see exactly which calls are unguarded. Set `guard = \"error\"` in `[tool.bigfoot]` for strict enforcement that raises `GuardedCallError` on every unguarded call. Use `bigfoot.allow(\"dns\", \"socket\")` or `@pytest.mark.allow(...)` to selectively permit real calls. Use `M()` pattern objects for granular matching (e.g., `M(protocol=\"http\", host=\"*.example.com\")`). Use `bigfoot.restrict(...)` to set a ceiling that inner blocks cannot widen. Configure project-wide rules in `[tool.bigfoot.firewall]` TOML sections.\n\nA plugin system makes it straightforward to intercept any service and enforce all three guarantees.\n\n```bash\npip install bigfoot[all]\n```\n\n## Quick Start\n\n```python\nimport bigfoot\nfrom dirty_equals import IsInstance\n\ndef create_charge(amount):\n    \"\"\"Production code -- calls Stripe via httpx internally.\"\"\"\n    import httpx\n    response = httpx.post(\"https://api.stripe.com/v1/charges\",\n                          json={\"amount\": amount})\n    return response.json()\n\ndef test_payment_flow():\n    bigfoot.http.mock_response(\"POST\", \"https://api.stripe.com/v1/charges\",\n                               json={\"id\": \"ch_123\"}, status=200)\n\n    with bigfoot:\n        result = create_charge(5000)\n\n    bigfoot.http.assert_request(\n        \"POST\", \"https://api.stripe.com/v1/charges\",\n        headers=IsInstance(dict), body='{\"amount\": 5000}',\n    ).assert_response(200, IsInstance(dict), '{\"id\": \"ch_123\"}')\n    assert result[\"id\"] == \"ch_123\"\n```\n\nIf you forget the `assert_request()` call, bigfoot fails the test at teardown:\n\n```\nE   bigfoot._errors.UnassertedInteractionsError: 1 interaction was not asserted.\nE\nE       http.assert_request(\nE           \"POST\",\nE           \"https://api.stripe.com/v1/charges\",\nE           headers={'host': 'api.stripe.com', ...},\nE           body='{\"amount\":5000}',\nE           require_response=True,\nE       ).assert_response(\nE           status=200,\nE           headers={'content-type': 'application/json'},\nE           body='{\"id\": \"ch_123\"}',\nE       )\nE       # ^ [sequence=0] [HttpPlugin] POST https://api.stripe.com/v1/charges (status=200)\n```\n\nEvery field is shown. Every value is real. Copy, paste, done.\n\n## How It Works\n\n1. **Register mocks** before the sandbox (`mock_response`, `mock_run`, `returns`, etc.)\n2. **Open the sandbox** with `with bigfoot:` (or `async with bigfoot:`)\n3. **Code runs normally** inside the sandbox, but external calls are intercepted and recorded\n4. **Assert interactions** after the sandbox closes, in order\n5. **`verify_all()`** runs automatically at test teardown via the pytest plugin\n\nNo fixture injection required. Install bigfoot, `import bigfoot`, and go.\n\n\u003c!-- NEW SECTION: Coming from unittest.mock --\u003e\n\n## Coming from unittest.mock\n\n### Concepts mapping\n\n| unittest.mock | bigfoot equivalent | Notes |\n|---------------|-------------------|-------|\n| `@patch(\"module.Class\")` | `bigfoot.mock(\"module:Class\")` | Colon-separated import path |\n| `@patch.object(obj, \"attr\")` | `bigfoot.mock.object(obj, \"attr\")` | Same idea, stricter enforcement |\n| `MagicMock()` | Plugin-specific mocks | `mock_response`, `mock_run`, `mock_command`, etc. |\n| `mock.return_value = X` | `.returns(X)` | Explicit, typed return values |\n| `mock.side_effect = Exception` | `mock_error(..., raises=Exception)` | Explicit error mocking |\n| `mock.assert_called_with(...)` | `plugin.assert_request(...)` / `spy.assert_call(...)` | Required, not optional |\n| `mock.assert_not_called()` | Not needed | If it was not registered, it cannot be called |\n| `call_args_list` | Interaction log | Automatic, exhaustive, shown on failure |\n\n### Migration by example\n\n**Patching an HTTP call**\n\n```python\n# BEFORE: unittest.mock\nfrom unittest.mock import patch, MagicMock\n\n@patch(\"myapp.client.requests.get\")\ndef test_fetch_user(mock_get):\n    mock_get.return_value = MagicMock(\n        status_code=200,\n        json=MagicMock(return_value={\"name\": \"Alice\"}),\n    )\n    user = fetch_user(42)\n    mock_get.assert_called_once_with(\"https://api.example.com/users/42\")\n    assert user[\"name\"] == \"Alice\"\n\n# AFTER: bigfoot\nfrom dirty_equals import IsInstance\n\ndef test_fetch_user():\n    bigfoot.http.mock_response(\n        \"GET\", \"https://api.example.com/users/42\",\n        json={\"name\": \"Alice\"}, status=200,\n    )\n    with bigfoot:\n        user = fetch_user(42)\n\n    bigfoot.http.assert_request(\n        \"GET\", \"https://api.example.com/users/42\",\n        headers=IsInstance(dict), body=None,\n    ).assert_response(200, IsInstance(dict), '{\"name\": \"Alice\"}')\n    assert user[\"name\"] == \"Alice\"\n```\n\n**Patching a subprocess call**\n\n```python\n# BEFORE: unittest.mock\nfrom unittest.mock import patch\n\n@patch(\"myapp.deploy.subprocess.run\")\ndef test_deploy(mock_run):\n    mock_run.return_value.returncode = 0\n    mock_run.return_value.stdout = \"deployed\"\n    result = deploy(\"prod\")\n    mock_run.assert_called_once()\n\n# AFTER: bigfoot\ndef test_deploy():\n    bigfoot.subprocess_mock.mock_run(\n        [\"kubectl\", \"apply\", \"-f\", \"prod.yaml\"],\n        returncode=0, stdout=\"deployed\",\n    )\n    with bigfoot:\n        result = deploy(\"prod\")\n\n    bigfoot.subprocess_mock.assert_run(\n        [\"kubectl\", \"apply\", \"-f\", \"prod.yaml\"],\n        returncode=0, stdout=\"deployed\",\n    )\n```\n\n**Patching an arbitrary object**\n\n```python\n# BEFORE: unittest.mock\nfrom unittest.mock import patch\n\n@patch(\"myapp.services.cache\")\ndef test_cached_lookup(mock_cache):\n    mock_cache.get.return_value = \"cached_value\"\n    result = lookup(\"key\")\n    mock_cache.get.assert_called_once_with(\"key\")\n\n# AFTER: bigfoot\ndef test_cached_lookup():\n    cache_mock = bigfoot.mock(\"myapp.services:cache\")\n    cache_mock.get.returns(\"cached_value\")\n\n    with bigfoot:\n        result = lookup(\"key\")\n\n    cache_mock.get.assert_call(args=(\"key\",), kwargs={}, returned=\"cached_value\")\n```\n\n### Incremental adoption\n\nYou do not have to migrate your entire test suite at once. bigfoot and `unittest.mock` can coexist in the same project:\n\n1. **Start with guard mode.** Install bigfoot and run your suite. Guard mode (default `\"warn\"`) will show you every real I/O call across all tests without breaking anything.\n2. **Migrate test by test.** Pick tests that touch HTTP, subprocess, or database calls first -- these benefit most from bigfoot's strict enforcement.\n3. **Escalate to strict guard mode.** Once coverage is high, set `guard = \"error\"` in `pyproject.toml` to catch any remaining leaks.\n\n\u003c!-- END NEW SECTION --\u003e\n\n## Plugins\n\nbigfoot ships with 27 plugins covering the most common external dependencies:\n\n| Category | Plugins | Intercepts |\n|----------|---------|------------|\n| **General** | [MockPlugin](https://axiomantic.github.io/bigfoot/guides/mock-plugin/), [LoggingPlugin](https://axiomantic.github.io/bigfoot/guides/logging-plugin/) | Named mock proxies, `logging` module |\n| **HTTP** | [HttpPlugin](https://axiomantic.github.io/bigfoot/guides/http-plugin/) | `httpx`, `requests`, `urllib`, `aiohttp` |\n| **Subprocess** | [SubprocessPlugin](https://axiomantic.github.io/bigfoot/guides/subprocess-plugin/), [PopenPlugin](https://axiomantic.github.io/bigfoot/guides/popen-plugin/), [AsyncSubprocessPlugin](https://axiomantic.github.io/bigfoot/guides/async-subprocess-plugin/) | `subprocess.run`, `shutil.which`, `Popen`, `asyncio.create_subprocess_*` |\n| **Database** | [DatabasePlugin](https://axiomantic.github.io/bigfoot/guides/database-plugin/), [Psycopg2Plugin](https://axiomantic.github.io/bigfoot/guides/psycopg2-plugin/), [AsyncpgPlugin](https://axiomantic.github.io/bigfoot/guides/asyncpg-plugin/), [MongoPlugin](https://axiomantic.github.io/bigfoot/guides/mongo-plugin/), [ElasticsearchPlugin](https://axiomantic.github.io/bigfoot/guides/elasticsearch-plugin/) | `sqlite3`, `psycopg2`, `asyncpg`, `pymongo`, `elasticsearch` |\n| **Cache** | [RedisPlugin](https://axiomantic.github.io/bigfoot/guides/redis-plugin/), [MemcachePlugin](https://axiomantic.github.io/bigfoot/guides/memcache-plugin/) | `redis`, `pymemcache` |\n| **Network** | [SmtpPlugin](https://axiomantic.github.io/bigfoot/guides/smtp-plugin/), [SocketPlugin](https://axiomantic.github.io/bigfoot/guides/socket-plugin/), [WebSocket](https://axiomantic.github.io/bigfoot/guides/websocket-plugin/), [DnsPlugin](https://axiomantic.github.io/bigfoot/guides/dns-plugin/), [SshPlugin](https://axiomantic.github.io/bigfoot/guides/ssh-plugin/), [GrpcPlugin](https://axiomantic.github.io/bigfoot/guides/grpc-plugin/) | `smtplib`, `socket`, `websockets`, `websocket-client`, DNS resolution, `paramiko`, `grpcio` |\n| **Cloud \u0026 Messaging** | [Boto3Plugin](https://axiomantic.github.io/bigfoot/guides/boto3-plugin/), [CeleryPlugin](https://axiomantic.github.io/bigfoot/guides/celery-plugin/), [PikaPlugin](https://axiomantic.github.io/bigfoot/guides/pika-plugin/) | `boto3` (AWS), `celery` tasks, `pika` (RabbitMQ) |\n| **Crypto \u0026 Auth** | [JwtPlugin](https://axiomantic.github.io/bigfoot/guides/jwt-plugin/), [CryptoPlugin](https://axiomantic.github.io/bigfoot/guides/crypto-plugin/) | `PyJWT`, `cryptography` |\n| **System** | [FileIoPlugin](https://axiomantic.github.io/bigfoot/guides/file-io-plugin/), [NativePlugin](https://axiomantic.github.io/bigfoot/guides/native-plugin/) | `open`, `pathlib`, `os`; `ctypes`, `cffi` |\n\n\u003cdetails\u003e\n\u003csummary\u003ePlugin examples\u003c/summary\u003e\n\n**Subprocess**\n```python\nbigfoot.subprocess_mock.mock_run([\"git\", \"pull\"], returncode=0, stdout=\"Up to date.\\n\")\n```\n\n**Database (sqlite3)**\n```python\nbigfoot.db_mock.new_session() \\\n    .expect(\"connect\", returns=None) \\\n    .expect(\"execute\", returns=[]) \\\n    .expect(\"commit\", returns=None) \\\n    .expect(\"close\", returns=None)\n```\n\n**Redis**\n```python\nbigfoot.redis_mock.mock_command(\"GET\", returns=b\"cached_value\")\n```\n\n**MongoDB**\n```python\nbigfoot.mongo_mock.mock_operation(\"find_one\", returns={\"_id\": \"abc\", \"name\": \"Alice\"})\n```\n\n**AWS (boto3)**\n```python\nbigfoot.boto3_mock.mock_api_call(\"s3\", \"GetObject\", returns={\"Body\": b\"file contents\"})\n```\n\n**RabbitMQ (pika)**\n```python\nbigfoot.pika_mock.new_session() \\\n    .expect(\"connect\", returns=None) \\\n    .expect(\"channel\", returns=None) \\\n    .expect(\"publish\", returns=None) \\\n    .expect(\"close\", returns=None)\n```\n\n**SSH (paramiko)**\n```python\nbigfoot.ssh_mock.new_session() \\\n    .expect(\"connect\", returns=None) \\\n    .expect(\"exec_command\", returns=(b\"\", b\"output\\n\", b\"\")) \\\n    .expect(\"close\", returns=None)\n```\n\n**SMTP**\n```python\nbigfoot.smtp_mock.new_session() \\\n    .expect(\"connect\", returns=(220, b\"OK\")) \\\n    .expect(\"ehlo\", returns=(250, b\"OK\")) \\\n    .expect(\"sendmail\", returns={}) \\\n    .expect(\"quit\", returns=(221, b\"Bye\"))\n```\n\n**Logging**\n```python\nbigfoot.log_mock.assert_info(\"User logged in\", \"myapp\")\n```\n\n**Mock (general)**\n```python\nsvc = bigfoot.mock(\"myapp.payments:PaymentService\")\nsvc.charge.returns({\"status\": \"ok\"})\n```\n\n\u003c/details\u003e\n\n## Advanced Features\n\n**Concurrent assertions** -- relax FIFO ordering for parallel requests:\n\n```python\nwith bigfoot.in_any_order():\n    bigfoot.http.assert_request(method=\"GET\", url=\".../a\", headers=IsInstance(dict), body=None,\n                                require_response=False)\n    bigfoot.http.assert_request(method=\"GET\", url=\".../b\", headers=IsInstance(dict), body=None,\n                                require_response=False)\n```\n\n**Mock / spy** -- composable mocks with import-site patching:\n\n```python\n# Mock a module-level attribute\ncache_mock = bigfoot.mock(\"myapp.services:cache\")\ncache_mock.get.returns(\"cached_value\")\n\n# Mock an attribute on a specific object\nmock = bigfoot.mock.object(my_module, \"service\")\n\n# Spy on real implementation\nspy = bigfoot.spy(\"myapp.services:cache\")\n```\n\n**Context managers** -- sandbox activates all mocks and enforces assertions:\n\n```python\n# Sandbox activates all mocks, enforces assertions\nwith bigfoot.sandbox():\n    result = code_under_test()\n\n# Individual activation (no assertion enforcement)\nwith cache_mock:\n    setup_code()\n```\n\n**Error mocking** -- mock exceptions and assert error interactions:\n\n```python\n# Mock errors\nbigfoot.http.mock_error(\"GET\", url, raises=httpx.ConnectError(\"refused\"))\n\n# Assert errors\nbigfoot.http.assert_request(\"GET\", url, headers=..., body=\"\",\n                            raised=IsInstance(httpx.ConnectError))\n```\n\n**Spy observability** -- assert return values and raised exceptions:\n\n```python\nspy.assert_call(args=(\"key\",), kwargs={}, returned=\"value\")\nspy.assert_call(args=(\"bad\",), kwargs={}, raised=IsInstance(KeyError))\n```\n\n**Pass-through** -- delegate to the real service, still record and require assertion:\n\n```python\nbigfoot.http.pass_through(\"GET\", url)\n```\n\n**Configuration** via `pyproject.toml`:\n\n```toml\n[tool.bigfoot.http]\nrequire_response = true  # This is the default; set to false to opt out\n```\n\nPer-call arguments override project-level settings. See the [configuration guide](https://axiomantic.github.io/bigfoot/guides/configuration/).\n\n## Selective Installation\n\n`bigfoot[all]` installs everything. For a smaller footprint, pick only what you need:\n\n```bash\npip install bigfoot                       # Core plugins (no optional deps)\npip install bigfoot[http]                 # + httpx, requests, urllib\npip install bigfoot[aiohttp]              # + aiohttp\npip install bigfoot[redis]                # + Redis\npip install bigfoot[pymemcache]           # + Memcached\npip install bigfoot[pymongo]              # + MongoDB\npip install bigfoot[elasticsearch]        # + Elasticsearch/OpenSearch\npip install bigfoot[psycopg2]             # + PostgreSQL (psycopg2)\npip install bigfoot[asyncpg]              # + PostgreSQL (asyncpg)\npip install bigfoot[boto3]                # + AWS SDK\npip install bigfoot[pika]                 # + RabbitMQ\npip install bigfoot[celery]               # + Celery tasks\npip install bigfoot[grpc]                 # + gRPC\npip install bigfoot[paramiko]             # + SSH\npip install bigfoot[jwt]                  # + PyJWT\npip install bigfoot[crypto]               # + cryptography\npip install bigfoot[cffi]                 # + cffi (C FFI)\npip install bigfoot[websockets]           # + async WebSocket\npip install bigfoot[websocket-client]     # + sync WebSocket\npip install bigfoot[matchers]             # + dirty-equals matchers\n```\n\n## Documentation\n\nFull API reference, plugin guides, and advanced usage: **[axiomantic.github.io/bigfoot](https://axiomantic.github.io/bigfoot/)**\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxiomantic%2Fbigfoot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxiomantic%2Fbigfoot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxiomantic%2Fbigfoot/lists"}