Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.20.0] - 2026-04-20

### Changed

- **Plugin proxy attributes renamed to drop the `_mock` suffix:** All 26 `_mock`-suffixed plugin proxy attributes on the `bigfoot` module have been renamed to their un-suffixed forms. The un-suffixed names are now canonical: `bigfoot.subprocess`, `bigfoot.popen`, `bigfoot.smtp`, `bigfoot.socket`, `bigfoot.db`, `bigfoot.async_websocket`, `bigfoot.sync_websocket`, `bigfoot.redis`, `bigfoot.mongo`, `bigfoot.dns`, `bigfoot.memcache`, `bigfoot.celery`, `bigfoot.log`, `bigfoot.async_subprocess`, `bigfoot.psycopg2`, `bigfoot.asyncpg`, `bigfoot.boto3`, `bigfoot.elasticsearch`, `bigfoot.jwt`, `bigfoot.crypto`, `bigfoot.file_io`, `bigfoot.pika`, `bigfoot.ssh`, `bigfoot.grpc`, `bigfoot.mcp`, and `bigfoot.native`. `bigfoot.http` was already un-suffixed and is unchanged.

### Deprecated

- **Old `_mock`-suffixed proxy names:** The previous attribute names (`bigfoot.subprocess_mock`, `bigfoot.db_mock`, `bigfoot.redis_mock`, and the rest of the 26) are retained as backward-compatibility aliases. Accessing any one of them emits a `DeprecationWarning` on first access per name, pointing at the new un-suffixed attribute. The aliases will be removed in a future release. Migration is mechanical: find-and-replace `_mock` where it appears immediately after a `bigfoot.` proxy access (e.g., `bigfoot.redis_mock.mock_command(...)` becomes `bigfoot.redis.mock_command(...)`). Local variables, plugin class names, and method names like `mock_response` / `mock_run` are not affected.

## [0.19.2] - 2026-04-08

### Changed
Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,14 @@ def test_deploy(mock_run):

# AFTER: bigfoot
def test_deploy():
bigfoot.subprocess_mock.mock_run(
bigfoot.subprocess.mock_run(
["kubectl", "apply", "-f", "prod.yaml"],
returncode=0, stdout="deployed",
)
with bigfoot:
result = deploy("prod")

bigfoot.subprocess_mock.assert_run(
bigfoot.subprocess.assert_run(
["kubectl", "apply", "-f", "prod.yaml"],
returncode=0, stdout="deployed",
)
Expand Down Expand Up @@ -281,12 +281,12 @@ bigfoot ships with 27 plugins covering the most common external dependencies:

**Subprocess**
```python
bigfoot.subprocess_mock.mock_run(["git", "pull"], returncode=0, stdout="Up to date.\n")
bigfoot.subprocess.mock_run(["git", "pull"], returncode=0, stdout="Up to date.\n")
```

**Database (sqlite3)**
```python
bigfoot.db_mock.new_session() \
bigfoot.db.new_session() \
.expect("connect", returns=None) \
.expect("execute", returns=[]) \
.expect("commit", returns=None) \
Expand All @@ -295,22 +295,22 @@ bigfoot.db_mock.new_session() \

**Redis**
```python
bigfoot.redis_mock.mock_command("GET", returns=b"cached_value")
bigfoot.redis.mock_command("GET", returns=b"cached_value")
```

**MongoDB**
```python
bigfoot.mongo_mock.mock_operation("find_one", returns={"_id": "abc", "name": "Alice"})
bigfoot.mongo.mock_operation("find_one", returns={"_id": "abc", "name": "Alice"})
```

**AWS (boto3)**
```python
bigfoot.boto3_mock.mock_api_call("s3", "GetObject", returns={"Body": b"file contents"})
bigfoot.boto3.mock_api_call("s3", "GetObject", returns={"Body": b"file contents"})
```

**RabbitMQ (pika)**
```python
bigfoot.pika_mock.new_session() \
bigfoot.pika.new_session() \
.expect("connect", returns=None) \
.expect("channel", returns=None) \
.expect("publish", returns=None) \
Expand All @@ -319,15 +319,15 @@ bigfoot.pika_mock.new_session() \

**SSH (paramiko)**
```python
bigfoot.ssh_mock.new_session() \
bigfoot.ssh.new_session() \
.expect("connect", returns=None) \
.expect("exec_command", returns=(b"", b"output\n", b"")) \
.expect("close", returns=None)
```

**SMTP**
```python
bigfoot.smtp_mock.new_session() \
bigfoot.smtp.new_session() \
.expect("connect", returns=(220, b"OK")) \
.expect("ehlo", returns=(250, b"OK")) \
.expect("sendmail", returns={}) \
Expand All @@ -336,7 +336,7 @@ bigfoot.smtp_mock.new_session() \

**Logging**
```python
bigfoot.log_mock.assert_info("User logged in", "myapp")
bigfoot.log.assert_info("User logged in", "myapp")
```

**Mock (general)**
Expand Down
20 changes: 10 additions & 10 deletions docs/guides/async-subprocess-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

## Setup

In pytest, access `AsyncSubprocessPlugin` through the `bigfoot.async_subprocess_mock` proxy. It auto-creates the plugin for the current test on first use:
In pytest, access `AsyncSubprocessPlugin` through the `bigfoot.async_subprocess` proxy. It auto-creates the plugin for the current test on first use:

```python
import asyncio
import bigfoot

async def test_run_command():
(bigfoot.async_subprocess_mock
(bigfoot.async_subprocess
.new_session()
.expect("spawn", returns=None)
.expect("communicate", returns=(b"hello\n", b"", 0)))
Expand All @@ -27,8 +27,8 @@ async def test_run_command():
assert stdout == b"hello\n"
assert proc.returncode == 0

bigfoot.async_subprocess_mock.assert_spawn(command=["echo", "hello"], stdin=None)
bigfoot.async_subprocess_mock.assert_communicate(input=None)
bigfoot.async_subprocess.assert_spawn(command=["echo", "hello"], stdin=None)
bigfoot.async_subprocess.assert_communicate(input=None)
```

For manual use outside pytest, construct `AsyncSubprocessPlugin` explicitly:
Expand Down Expand Up @@ -60,7 +60,7 @@ The `spawn` step fires automatically during `asyncio.create_subprocess_exec(...)
Use `new_session()` to create a `SessionHandle` and chain `.expect()` calls to build the script:

```python
(bigfoot.async_subprocess_mock
(bigfoot.async_subprocess
.new_session()
.expect("spawn", returns=None)
.expect("communicate", returns=(b"output", b"errors", 0)))
Expand All @@ -85,34 +85,34 @@ Use `new_session()` to create a `SessionHandle` and chain `.expect()` calls to b

## Asserting interactions

Each step records an interaction on the timeline. Use the typed assertion helpers on `bigfoot.async_subprocess_mock`:
Each step records an interaction on the timeline. Use the typed assertion helpers on `bigfoot.async_subprocess`:

### `assert_spawn(*, command, stdin)`

Asserts the next spawn interaction. Both `command` and `stdin` are required fields.

```python
# For exec:
bigfoot.async_subprocess_mock.assert_spawn(command=["git", "status"], stdin=None)
bigfoot.async_subprocess.assert_spawn(command=["git", "status"], stdin=None)

# For shell:
bigfoot.async_subprocess_mock.assert_spawn(command="ls -la | grep foo", stdin=None)
bigfoot.async_subprocess.assert_spawn(command="ls -la | grep foo", stdin=None)
```

### `assert_communicate(*, input)`

Asserts the next communicate interaction. The `input` field is required.

```python
bigfoot.async_subprocess_mock.assert_communicate(input=None)
bigfoot.async_subprocess.assert_communicate(input=None)
```

### `assert_wait()`

Asserts the next wait interaction. No fields are required.

```python
bigfoot.async_subprocess_mock.assert_wait()
bigfoot.async_subprocess.assert_wait()
```

## Full example
Expand Down
30 changes: 15 additions & 15 deletions docs/guides/asyncpg-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ pip install bigfoot[asyncpg]

## Setup

In pytest, access `AsyncpgPlugin` through the `bigfoot.asyncpg_mock` proxy. It auto-creates the plugin for the current test on first use:
In pytest, access `AsyncpgPlugin` through the `bigfoot.asyncpg` proxy. It auto-creates the plugin for the current test on first use:

```python
import bigfoot

async def test_fetch_users():
(bigfoot.asyncpg_mock
(bigfoot.asyncpg
.new_session()
.expect("connect", returns=None)
.expect("fetch", returns=[{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}])
Expand All @@ -30,9 +30,9 @@ async def test_fetch_users():

assert rows == [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]

bigfoot.asyncpg_mock.assert_connect(host="localhost", database="myapp", user="admin")
bigfoot.asyncpg_mock.assert_fetch(query="SELECT id, name FROM users", args=[])
bigfoot.asyncpg_mock.assert_close()
bigfoot.asyncpg.assert_connect(host="localhost", database="myapp", user="admin")
bigfoot.asyncpg.assert_fetch(query="SELECT id, name FROM users", args=[])
bigfoot.asyncpg.assert_close()
```

For manual use outside pytest, construct `AsyncpgPlugin` explicitly:
Expand Down Expand Up @@ -65,7 +65,7 @@ Unlike psycopg2/sqlite3, asyncpg does not have an explicit transaction state for
Use `new_session()` to create a `SessionHandle` and chain `.expect()` calls:

```python
(bigfoot.asyncpg_mock
(bigfoot.asyncpg
.new_session()
.expect("connect", returns=None)
.expect("fetch", returns=[{"id": 1}])
Expand Down Expand Up @@ -109,30 +109,30 @@ The `assert_connect()` helper accepts whichever parameters were used:

```python
# For DSN connections
bigfoot.asyncpg_mock.assert_connect(dsn="postgresql://admin@localhost/myapp")
bigfoot.asyncpg.assert_connect(dsn="postgresql://admin@localhost/myapp")

# For keyword connections
bigfoot.asyncpg_mock.assert_connect(host="localhost", port=5432, database="myapp", user="admin")
bigfoot.asyncpg.assert_connect(host="localhost", port=5432, database="myapp", user="admin")
```

## Asserting interactions

Each step records an interaction on the timeline. Use the typed assertion helpers on `bigfoot.asyncpg_mock`:
Each step records an interaction on the timeline. Use the typed assertion helpers on `bigfoot.asyncpg`:

### `assert_connect(**kwargs)`

Asserts the next connect interaction. Pass whichever connection fields were used.

```python
bigfoot.asyncpg_mock.assert_connect(host="localhost", database="myapp", user="admin")
bigfoot.asyncpg.assert_connect(host="localhost", database="myapp", user="admin")
```

### `assert_execute(*, query, args)`

Asserts the next execute interaction. Both `query` and `args` are required.

```python
bigfoot.asyncpg_mock.assert_execute(
bigfoot.asyncpg.assert_execute(
query="INSERT INTO users (name) VALUES ($1)",
args=["Alice"],
)
Expand All @@ -143,15 +143,15 @@ bigfoot.asyncpg_mock.assert_execute(
Asserts the next fetch interaction. Both `query` and `args` are required.

```python
bigfoot.asyncpg_mock.assert_fetch(query="SELECT id, name FROM users", args=[])
bigfoot.asyncpg.assert_fetch(query="SELECT id, name FROM users", args=[])
```

### `assert_fetchrow(*, query, args)`

Asserts the next fetchrow interaction. Both `query` and `args` are required.

```python
bigfoot.asyncpg_mock.assert_fetchrow(
bigfoot.asyncpg.assert_fetchrow(
query="SELECT id, name FROM users WHERE id = $1",
args=[1],
)
Expand All @@ -162,15 +162,15 @@ bigfoot.asyncpg_mock.assert_fetchrow(
Asserts the next fetchval interaction. Both `query` and `args` are required.

```python
bigfoot.asyncpg_mock.assert_fetchval(query="SELECT count(*) FROM users", args=[])
bigfoot.asyncpg.assert_fetchval(query="SELECT count(*) FROM users", args=[])
```

### `assert_close()`

Asserts the next close interaction. No fields are required.

```python
bigfoot.asyncpg_mock.assert_close()
bigfoot.asyncpg.assert_close()
```

## Full example
Expand Down
Loading
Loading