Skip to content

Commit 261b696

Browse files
authored
Merge pull request #188 from digital-land/update_testing_guidance
Adding about testclient, testcontainers, conftest and coverage etc
2 parents 4d0bb3f + 1398ec6 commit 261b696

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

docs/development/testing-guidance.md

+114
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,60 @@ tests
7575
- test_user_story_1.py
7676
- test_user_story_2.py
7777
```
78+
### Adding `conftest.py` File
7879

80+
The `conftest.py` file in a Python project is a centralized location for defining shared fixtures and configuration for your tests. It provides:
81+
82+
- **Shared Resources**: Setting up shared resources like database connections, mock clients, or application instances.
83+
- **Code Reusability**: Reducing code duplication by providing reusable fixtures.
84+
- **Clarity**: Maintaining test clarity by isolating setup logic from test cases.
85+
86+
##### Best Practices for `conftest.py`
87+
88+
1. **Keep It Focused**
89+
- Only include shared configurations and fixtures. Avoid adding test cases or unrelated code.
90+
91+
2. **Name Fixtures Clearly**
92+
- Use descriptive names to indicate their purpose (e.g., `temp_file`, `mock_service`).
93+
94+
3. **Use Appropriate Scopes**
95+
- Choose the right fixture scope (`function`, `class`, `module`, `session`) based on how long the fixture should persist.
96+
97+
4. **Minimize Side Effects**
98+
- Ensure fixtures clean up resources after execution to prevent interference between tests.
99+
100+
101+
---
102+
103+
### Code Coverage, Linting, and Formatting
104+
105+
To ensure code quality, maintain consistency, and measure testing effectiveness, we can try including steps for **coverage**, **linting**, and **formatting** as part of the testing workflow.
106+
107+
For example, we can add this in a `Makefile` or CI pipeline:
108+
109+
```makefile
110+
test: lint test-coverage
111+
112+
test-coverage:: coverage-unit coverage-integration
113+
114+
coverage-unit:
115+
pytest --cov=src tests/unit/
116+
117+
coverage-integration:
118+
pytest --cov=src --cov-append --cov-fail-under=90 tests/integration/
119+
120+
lint:: black-check flake8
121+
122+
black-check:
123+
black --check .
124+
125+
black:
126+
black .
127+
128+
flake8:
129+
flake8 .
130+
131+
```
79132

80133
## Testing Information By Language
81134

@@ -134,3 +187,64 @@ class TestClassTwo:
134187
def test_process_test_something_else(self):
135188
.....
136189
```
190+
191+
192+
## Testing FastAPI Applications
193+
194+
FastAPI provides built-in tools and conventions that simplify testing APIs.
195+
### `TestClient`
196+
197+
FastAPI includes a `TestClient` utility (via Starlette) to simulate HTTP requests.
198+
199+
```python
200+
from fastapi.testclient import TestClient
201+
202+
# Create a test client for the FastAPI app
203+
client = TestClient(app)
204+
205+
def test_endpoint():
206+
response = client.get("/endpoint_api")
207+
assert response.status_code == 200
208+
assert response.json() == {"key": "value"} # Replace with your expected response
209+
```
210+
211+
212+
### `Testcontainers`
213+
214+
215+
**Testcontainers** is a library that helps you create lightweight, disposable containers for testing. It is particularly useful for testing services like databases without mocking, ensuring your tests run in a real-world environment.
216+
217+
### Prerequisites
218+
219+
* **Docker Desktop** (or any Docker runtime)
220+
* **Python >= 3.8**
221+
222+
### Why Testcontainers?
223+
224+
1. **Real Services**: Test against actual instances of databases, queues, etc.
225+
2. **Isolation**: Each test runs in its own container, avoiding conflicts.
226+
3. **Consistency**: Ensures the test environment matches production as closely as possible.
227+
228+
### Example Usage with LocalStack Container. You can use Testcontainers to spin up a LocalStack container, which emulates AWS services
229+
230+
```python
231+
from testcontainers.localstack import LocalStackContainer
232+
import boto3
233+
234+
def localstack_container():
235+
# Start LocalStack container
236+
with LocalStackContainer() as localstack:
237+
yield localstack
238+
239+
def s3_client(localstack_container):
240+
# Create an S3 client using the LocalStack endpoint
241+
s3 = boto3.client(
242+
"s3",
243+
endpoint_url=localstack_container.get_url(),
244+
region_name=os.environ["AWS_DEFAULT_REGION"],
245+
aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"],
246+
aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"],
247+
)
248+
return s3
249+
250+

0 commit comments

Comments
 (0)