From 26930a09f77551bdae771715873b8ae90de70dce Mon Sep 17 00:00:00 2001 From: Artyom Date: Fri, 1 Aug 2025 13:07:07 +0300 Subject: [PATCH 1/4] feat (docs): updated manual run with broker examples --- docs/docs/en/getting-started/index.md | 30 ++++++++++++++----- .../getting_started/manual_run/__init__.py | 0 .../manual_run/confluent_base_run.py | 13 ++++++++ .../manual_run/kafka_base_run.py | 13 ++++++++ .../manual_run/nats_base_run.py | 13 ++++++++ .../manual_run/rabbit_base_run.py | 13 ++++++++ .../manual_run/redis_base_run.py | 13 ++++++++ 7 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 docs/docs_src/getting_started/manual_run/__init__.py create mode 100644 docs/docs_src/getting_started/manual_run/confluent_base_run.py create mode 100644 docs/docs_src/getting_started/manual_run/kafka_base_run.py create mode 100644 docs/docs_src/getting_started/manual_run/nats_base_run.py create mode 100644 docs/docs_src/getting_started/manual_run/rabbit_base_run.py create mode 100644 docs/docs_src/getting_started/manual_run/redis_base_run.py diff --git a/docs/docs/en/getting-started/index.md b/docs/docs/en/getting-started/index.md index 9d152a64fb..1bd6a59a3c 100644 --- a/docs/docs/en/getting-started/index.md +++ b/docs/docs/en/getting-started/index.md @@ -149,16 +149,30 @@ Enjoy your new development experience! Also, you can run the `FastStream` application manually, as a regular async function: -```python -import asyncio +=== "AIOKafka" + ```python linenums="1" + {!> docs_src/getting_started/manual_run/kafka_base_run.py!} + ``` -async def main(): - app = FastStream(...) - await app.run() # blocking method +=== "Confluent" + ```python linenums="1" + {!> docs_src/getting_started/manual_run/confluent_base_run.py!} + ``` -if __name__ == "__main__": - asyncio.run(main()) -``` +=== "RabbitMQ" + ```python linenums="1" + {!> docs_src/getting_started/manual_run/rabbit_base_run.py!} + ``` + +=== "NATS" + ```python linenums="1" + {!> docs_src/getting_started/manual_run/nats_base_run.py!} + ``` + +=== "Redis" + ```python linenums="1" + {!> docs_src/getting_started/manual_run/redis_base_run.py!} + ``` ### Other tools integrations diff --git a/docs/docs_src/getting_started/manual_run/__init__.py b/docs/docs_src/getting_started/manual_run/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/docs_src/getting_started/manual_run/confluent_base_run.py b/docs/docs_src/getting_started/manual_run/confluent_base_run.py new file mode 100644 index 0000000000..07bb1dfa82 --- /dev/null +++ b/docs/docs_src/getting_started/manual_run/confluent_base_run.py @@ -0,0 +1,13 @@ +import asyncio + +from faststream import FastStream +from faststream.confluent import KafkaBroker + + +async def main(): + broker = KafkaBroker("localhost:9092") + app = FastStream(broker) + await app.run() # blocking method + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/docs/docs_src/getting_started/manual_run/kafka_base_run.py b/docs/docs_src/getting_started/manual_run/kafka_base_run.py new file mode 100644 index 0000000000..b3c834a616 --- /dev/null +++ b/docs/docs_src/getting_started/manual_run/kafka_base_run.py @@ -0,0 +1,13 @@ +import asyncio + +from faststream import FastStream +from faststream.kafka import KafkaBroker + + +async def main(): + broker = KafkaBroker("localhost:9092") + app = FastStream(broker) + await app.run() # blocking method + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/docs/docs_src/getting_started/manual_run/nats_base_run.py b/docs/docs_src/getting_started/manual_run/nats_base_run.py new file mode 100644 index 0000000000..bb350957f5 --- /dev/null +++ b/docs/docs_src/getting_started/manual_run/nats_base_run.py @@ -0,0 +1,13 @@ +import asyncio + +from faststream import FastStream +from faststream.nats import NatsBroker + + +async def main(): + broker = NatsBroker("nats://localhost:4222") + app = FastStream(broker) + await app.run() # blocking method + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/docs/docs_src/getting_started/manual_run/rabbit_base_run.py b/docs/docs_src/getting_started/manual_run/rabbit_base_run.py new file mode 100644 index 0000000000..a93297376e --- /dev/null +++ b/docs/docs_src/getting_started/manual_run/rabbit_base_run.py @@ -0,0 +1,13 @@ +import asyncio + +from faststream import FastStream +from faststream.rabbit import RabbitBroker + + +async def main(): + broker = RabbitBroker("amqp://guest:guest@localhost:5672/") + app = FastStream(broker) + await app.run() # blocking method + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/docs/docs_src/getting_started/manual_run/redis_base_run.py b/docs/docs_src/getting_started/manual_run/redis_base_run.py new file mode 100644 index 0000000000..8500331cea --- /dev/null +++ b/docs/docs_src/getting_started/manual_run/redis_base_run.py @@ -0,0 +1,13 @@ +import asyncio + +from faststream import FastStream +from faststream.redis import RedisBroker + + +async def main(): + broker = RedisBroker("redis://localhost:6379") + app = FastStream(broker) + await app.run() # blocking method + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file From d57494cc2c94e0020c27d5dbdd6fa95346947666 Mon Sep 17 00:00:00 2001 From: "faststream-actions[bot]" Date: Fri, 1 Aug 2025 10:33:50 +0000 Subject: [PATCH 2/4] chore: apply autofixes --- docs/docs_src/getting_started/manual_run/confluent_base_run.py | 2 +- docs/docs_src/getting_started/manual_run/kafka_base_run.py | 2 +- docs/docs_src/getting_started/manual_run/nats_base_run.py | 2 +- docs/docs_src/getting_started/manual_run/rabbit_base_run.py | 2 +- docs/docs_src/getting_started/manual_run/redis_base_run.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/docs_src/getting_started/manual_run/confluent_base_run.py b/docs/docs_src/getting_started/manual_run/confluent_base_run.py index 07bb1dfa82..a66c586a53 100644 --- a/docs/docs_src/getting_started/manual_run/confluent_base_run.py +++ b/docs/docs_src/getting_started/manual_run/confluent_base_run.py @@ -10,4 +10,4 @@ async def main(): await app.run() # blocking method if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) diff --git a/docs/docs_src/getting_started/manual_run/kafka_base_run.py b/docs/docs_src/getting_started/manual_run/kafka_base_run.py index b3c834a616..f22c41517f 100644 --- a/docs/docs_src/getting_started/manual_run/kafka_base_run.py +++ b/docs/docs_src/getting_started/manual_run/kafka_base_run.py @@ -10,4 +10,4 @@ async def main(): await app.run() # blocking method if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) diff --git a/docs/docs_src/getting_started/manual_run/nats_base_run.py b/docs/docs_src/getting_started/manual_run/nats_base_run.py index bb350957f5..8354bc69f8 100644 --- a/docs/docs_src/getting_started/manual_run/nats_base_run.py +++ b/docs/docs_src/getting_started/manual_run/nats_base_run.py @@ -10,4 +10,4 @@ async def main(): await app.run() # blocking method if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) diff --git a/docs/docs_src/getting_started/manual_run/rabbit_base_run.py b/docs/docs_src/getting_started/manual_run/rabbit_base_run.py index a93297376e..b821b790a1 100644 --- a/docs/docs_src/getting_started/manual_run/rabbit_base_run.py +++ b/docs/docs_src/getting_started/manual_run/rabbit_base_run.py @@ -10,4 +10,4 @@ async def main(): await app.run() # blocking method if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) diff --git a/docs/docs_src/getting_started/manual_run/redis_base_run.py b/docs/docs_src/getting_started/manual_run/redis_base_run.py index 8500331cea..5c1c7e45de 100644 --- a/docs/docs_src/getting_started/manual_run/redis_base_run.py +++ b/docs/docs_src/getting_started/manual_run/redis_base_run.py @@ -10,4 +10,4 @@ async def main(): await app.run() # blocking method if __name__ == "__main__": - asyncio.run(main()) \ No newline at end of file + asyncio.run(main()) From 21198c6851b66aec0599100f820c661035d85571 Mon Sep 17 00:00:00 2001 From: Artyom Date: Wed, 22 Oct 2025 16:54:03 +0300 Subject: [PATCH 3/4] docs: added testing section in getting-started --- docs/docs/en/getting-started/index.md | 29 +++++++++++++++++++ docs/docs/en/release.md | 2 +- .../getting_started/testing/__init__.py | 0 .../testing/confluent_test_service.py | 19 ++++++++++++ .../testing/kafka_test_service.py | 19 ++++++++++++ .../testing/nats_test_service.py | 19 ++++++++++++ .../testing/rabbit_test_service.py | 19 ++++++++++++ .../testing/redis_test_service.py | 19 ++++++++++++ 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 docs/docs_src/getting_started/testing/__init__.py create mode 100644 docs/docs_src/getting_started/testing/confluent_test_service.py create mode 100644 docs/docs_src/getting_started/testing/kafka_test_service.py create mode 100644 docs/docs_src/getting_started/testing/nats_test_service.py create mode 100644 docs/docs_src/getting_started/testing/rabbit_test_service.py create mode 100644 docs/docs_src/getting_started/testing/redis_test_service.py diff --git a/docs/docs/en/getting-started/index.md b/docs/docs/en/getting-started/index.md index b695e12aaa..44da18dce7 100644 --- a/docs/docs/en/getting-started/index.md +++ b/docs/docs/en/getting-started/index.md @@ -176,6 +176,35 @@ Also, you can run the `FastStream` application manually, as a regular async func {!> docs_src/getting_started/manual_run/redis_base_run.py!} ``` +### Testing + +The service can be tested using the `TestBroker` context managers, which, by default, puts the Broker into "testing mode". + +=== "AIOKafka" + ```python linenums="1" + {!> docs_src/getting_started/testing/kafka_test_service.py!} + ``` + +=== "Confluent" + ```python linenums="1" + {!> docs_src/getting_started/testing/confluent_test_service.py!} + ``` + +=== "RabbitMQ" + ```python linenums="1" + {!> docs_src/getting_started/testing/rabbit_test_service.py!} + ``` + +=== "NATS" + ```python linenums="1" + {!> docs_src/getting_started/testing/nats_test_service.py!} + ``` + +=== "Redis" + ```python linenums="1" + {!> docs_src/getting_started/testing/redis_test_service.py!} + ``` + ### Other tools integrations If you want to use **FastStream** as part of another framework service, you probably don't need to utilize the `FastStream` object at all, as it is primarily intended as a **CLI** tool target. Instead, you can start and stop your broker as part of another framework's lifespan. You can find such examples in the [integrations section](./integrations/frameworks/index.md){.internal-link}. diff --git a/docs/docs/en/release.md b/docs/docs/en/release.md index b3e2721560..0cfa3aa486 100644 --- a/docs/docs/en/release.md +++ b/docs/docs/en/release.md @@ -3220,7 +3220,7 @@ pip install faststream==0.3.0rc0 && pip install "faststream[redis]" #### Misc * chore: polishing by [@davorrunje](https://github.com/davorrunje){.external-link target="_blank"} in [https://github.com/ag2ai/faststream/pull/946](https://github.com/ag2ai/faststream/pull/946){.external-link target="_blank"} -* сhore: add manual publish btn to CI by [@Lancetnik](https://github.com/Lancetnik){.external-link target="_blank"} in [https://github.com/ag2ai/faststream/pull/950](https://github.com/ag2ai/faststream/pull/950){.external-link target="_blank"} +* chore: add manual publish btn to CI by [@Lancetnik](https://github.com/Lancetnik){.external-link target="_blank"} in [https://github.com/ag2ai/faststream/pull/950](https://github.com/ag2ai/faststream/pull/950){.external-link target="_blank"} * chore: limit open dev dependency versions by [@kumaranvpl](https://github.com/kumaranvpl){.external-link target="_blank"} in [https://github.com/ag2ai/faststream/pull/953](https://github.com/ag2ai/faststream/pull/953){.external-link target="_blank"} diff --git a/docs/docs_src/getting_started/testing/__init__.py b/docs/docs_src/getting_started/testing/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/docs_src/getting_started/testing/confluent_test_service.py b/docs/docs_src/getting_started/testing/confluent_test_service.py new file mode 100644 index 0000000000..a192de4c83 --- /dev/null +++ b/docs/docs_src/getting_started/testing/confluent_test_service.py @@ -0,0 +1,19 @@ +import pytest +from pydantic import ValidationError +from faststream import FastStream +from faststream.confluent import KafkaBroker, TestKafkaBroker + + +broker = KafkaBroker("localhost:9092") +app = FastStream(broker) + + +@pytest.mark.asyncio +async def test_correct() -> None: + async with TestKafkaBroker(broker) as br: + await br.publish(...) + +@pytest.mark.asyncio +async def test_invalid() -> None: + async with TestKafkaBroker(broker) as br: + with pytest.raises(ValidationError): ... \ No newline at end of file diff --git a/docs/docs_src/getting_started/testing/kafka_test_service.py b/docs/docs_src/getting_started/testing/kafka_test_service.py new file mode 100644 index 0000000000..ee15f65f31 --- /dev/null +++ b/docs/docs_src/getting_started/testing/kafka_test_service.py @@ -0,0 +1,19 @@ +import pytest +from pydantic import ValidationError +from faststream import FastStream +from faststream.kafka import KafkaBroker, TestKafkaBroker + + +broker = KafkaBroker("localhost:9092") +app = FastStream(broker) + + +@pytest.mark.asyncio +async def test_correct() -> None: + async with TestKafkaBroker(broker) as br: + await br.publish(...) + +@pytest.mark.asyncio +async def test_invalid() -> None: + async with TestKafkaBroker(broker) as br: + with pytest.raises(ValidationError): ... \ No newline at end of file diff --git a/docs/docs_src/getting_started/testing/nats_test_service.py b/docs/docs_src/getting_started/testing/nats_test_service.py new file mode 100644 index 0000000000..c3ea243a10 --- /dev/null +++ b/docs/docs_src/getting_started/testing/nats_test_service.py @@ -0,0 +1,19 @@ +import pytest +from pydantic import ValidationError +from faststream import FastStream +from faststream.nats import NatsBroker, TestNatsBroker + + +broker = NatsBroker("nats://localhost:4222") +app = FastStream(broker) + + +@pytest.mark.asyncio +async def test_correct() -> None: + async with TestNatsBroker(broker) as br: + await br.publish(...) + +@pytest.mark.asyncio +async def test_invalid() -> None: + async with TestNatsBroker(broker) as br: + with pytest.raises(ValidationError): ... \ No newline at end of file diff --git a/docs/docs_src/getting_started/testing/rabbit_test_service.py b/docs/docs_src/getting_started/testing/rabbit_test_service.py new file mode 100644 index 0000000000..8a703988df --- /dev/null +++ b/docs/docs_src/getting_started/testing/rabbit_test_service.py @@ -0,0 +1,19 @@ +import pytest +from pydantic import ValidationError +from faststream import FastStream +from faststream.rabbit import RabbitBroker, TestRabbitBroker + + +broker = RabbitBroker("amqp://guest:guest@localhost:5672/") +app = FastStream(broker) + + +@pytest.mark.asyncio +async def test_correct() -> None: + async with TestRabbitBroker(broker) as br: + await br.publish(...) + +@pytest.mark.asyncio +async def test_invalid() -> None: + async with TestRabbitBroker(broker) as br: + with pytest.raises(ValidationError): ... \ No newline at end of file diff --git a/docs/docs_src/getting_started/testing/redis_test_service.py b/docs/docs_src/getting_started/testing/redis_test_service.py new file mode 100644 index 0000000000..0a13b58e78 --- /dev/null +++ b/docs/docs_src/getting_started/testing/redis_test_service.py @@ -0,0 +1,19 @@ +import pytest +from pydantic import ValidationError +from faststream import FastStream +from faststream.redis import RedisBroker, TestRedisBroker + + +broker = RedisBroker("redis://localhost:6379") +app = FastStream(broker) + + +@pytest.mark.asyncio +async def test_correct() -> None: + async with TestRedisBroker(broker) as br: + await br.publish(...) + +@pytest.mark.asyncio +async def test_invalid() -> None: + async with TestRedisBroker(broker) as br: + with pytest.raises(ValidationError): ... \ No newline at end of file From 4f72ced9d8e7c7e2c567171f538253b42007a222 Mon Sep 17 00:00:00 2001 From: Artyom Date: Wed, 22 Oct 2025 17:07:03 +0300 Subject: [PATCH 4/4] style: format code --- docs/docs_src/getting_started/testing/confluent_test_service.py | 2 +- docs/docs_src/getting_started/testing/kafka_test_service.py | 2 +- docs/docs_src/getting_started/testing/nats_test_service.py | 2 +- docs/docs_src/getting_started/testing/rabbit_test_service.py | 2 +- docs/docs_src/getting_started/testing/redis_test_service.py | 2 +- uv.lock | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/docs_src/getting_started/testing/confluent_test_service.py b/docs/docs_src/getting_started/testing/confluent_test_service.py index a192de4c83..5aa2c93084 100644 --- a/docs/docs_src/getting_started/testing/confluent_test_service.py +++ b/docs/docs_src/getting_started/testing/confluent_test_service.py @@ -16,4 +16,4 @@ async def test_correct() -> None: @pytest.mark.asyncio async def test_invalid() -> None: async with TestKafkaBroker(broker) as br: - with pytest.raises(ValidationError): ... \ No newline at end of file + with pytest.raises(ValidationError): ... diff --git a/docs/docs_src/getting_started/testing/kafka_test_service.py b/docs/docs_src/getting_started/testing/kafka_test_service.py index ee15f65f31..120c178b89 100644 --- a/docs/docs_src/getting_started/testing/kafka_test_service.py +++ b/docs/docs_src/getting_started/testing/kafka_test_service.py @@ -16,4 +16,4 @@ async def test_correct() -> None: @pytest.mark.asyncio async def test_invalid() -> None: async with TestKafkaBroker(broker) as br: - with pytest.raises(ValidationError): ... \ No newline at end of file + with pytest.raises(ValidationError): ... diff --git a/docs/docs_src/getting_started/testing/nats_test_service.py b/docs/docs_src/getting_started/testing/nats_test_service.py index c3ea243a10..eea9a60dd0 100644 --- a/docs/docs_src/getting_started/testing/nats_test_service.py +++ b/docs/docs_src/getting_started/testing/nats_test_service.py @@ -16,4 +16,4 @@ async def test_correct() -> None: @pytest.mark.asyncio async def test_invalid() -> None: async with TestNatsBroker(broker) as br: - with pytest.raises(ValidationError): ... \ No newline at end of file + with pytest.raises(ValidationError): ... diff --git a/docs/docs_src/getting_started/testing/rabbit_test_service.py b/docs/docs_src/getting_started/testing/rabbit_test_service.py index 8a703988df..9bff4a7100 100644 --- a/docs/docs_src/getting_started/testing/rabbit_test_service.py +++ b/docs/docs_src/getting_started/testing/rabbit_test_service.py @@ -16,4 +16,4 @@ async def test_correct() -> None: @pytest.mark.asyncio async def test_invalid() -> None: async with TestRabbitBroker(broker) as br: - with pytest.raises(ValidationError): ... \ No newline at end of file + with pytest.raises(ValidationError): ... diff --git a/docs/docs_src/getting_started/testing/redis_test_service.py b/docs/docs_src/getting_started/testing/redis_test_service.py index 0a13b58e78..41aa6cc666 100644 --- a/docs/docs_src/getting_started/testing/redis_test_service.py +++ b/docs/docs_src/getting_started/testing/redis_test_service.py @@ -16,4 +16,4 @@ async def test_correct() -> None: @pytest.mark.asyncio async def test_invalid() -> None: async with TestRedisBroker(broker) as br: - with pytest.raises(ValidationError): ... \ No newline at end of file + with pytest.raises(ValidationError): ... diff --git a/uv.lock b/uv.lock index 69dc15d257..e955353a98 100644 --- a/uv.lock +++ b/uv.lock @@ -732,7 +732,7 @@ wheels = [ [[package]] name = "faststream" -version = "0.6.1" +version = "0.6.2" source = { editable = "." } dependencies = [ { name = "anyio" },