Skip to content

Commit

Permalink
Update Testing-RESTful-APIs.md
Browse files Browse the repository at this point in the history
  • Loading branch information
abhiverse01 authored Oct 13, 2024
1 parent 9f35142 commit 03b1dda
Showing 1 changed file with 262 additions and 0 deletions.
262 changes: 262 additions & 0 deletions Restful APIs/Testing-RESTful-APIs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# **Testing RESTful APIs**

Testing is an essential part of API development. It ensures that the endpoints behave as expected and helps catch bugs early in the development process. In this section, we’ll cover automated testing using **`pytest`** for **Flask** and **`unittest`** or **`pytest-django`** for **Django**. We’ll also provide a mini-tutorial on how to manually test APIs using **Postman**.

## **1. Automated Testing in Flask with pytest**

Testing APIs in Flask is straightforward using **`pytest`**. We’ll start by setting up basic test cases for CRUD operations, and then move on to testing authenticated routes.

### **Step 1: Install pytest**
```bash
pipenv install pytest pytest-flask
```

### **Step 2: Setting Up Test Configuration**
In **`tests/conftest.py`**, create a test configuration to set up a test environment for your Flask app.

```python
import pytest
from app import create_app, db

@pytest.fixture
def app():
app = create_app()
app.config.update({
"TESTING": True,
"SQLALCHEMY_DATABASE_URI": "sqlite:///:memory:", # Use in-memory database for testing
})

with app.app_context():
db.create_all() # Create the database for tests
yield app # Provide the app to the tests
db.session.remove()
db.drop_all()

@pytest.fixture
def client(app):
return app.test_client() # Provide a test client
```
- **`TESTING`**: Enables testing mode in Flask.
- **`SQLALCHEMY_DATABASE_URI`**: Uses an in-memory SQLite database for testing purposes.
- **`client`**: Provides a test client for making requests to the Flask application.

### **Step 3: Writing Test Cases**
Now, let’s write test cases for CRUD operations and authentication. In **`tests/test_api.py`**, we create tests using pytest.

```python
def test_create_user(client):
response = client.post('/users', json={
"name": "John Doe",
"email": "[email protected]",
"age": 30
})
assert response.status_code == 201
data = response.get_json()
assert data['name'] == "John Doe"

def test_get_users(client):
response = client.get('/users')
assert response.status_code == 200
data = response.get_json()
assert len(data) > 0 # Ensure we get a list of users

def test_get_single_user(client):
response = client.get('/users/1')
assert response.status_code == 200
data = response.get_json()
assert data['id'] == 1

def test_update_user(client):
response = client.put('/users/1', json={"name": "Jane Doe"})
assert response.status_code == 200
data = response.get_json()
assert data['name'] == "Jane Doe"

def test_delete_user(client):
response = client.delete('/users/1')
assert response.status_code == 200
```
- **Test Case Breakdown**:
- **`test_create_user`**: Tests the creation of a new user via the POST method.
- **`test_get_users`**: Tests retrieving a list of users via the GET method.
- **`test_get_single_user`**: Tests retrieving a specific user by ID.
- **`test_update_user`**: Tests updating a user’s information.
- **`test_delete_user`**: Tests deleting a user.

### **Step 4: Running the Tests**
To run the tests, simply execute:
```bash
pytest
```
This will discover and execute all tests within the **`tests/`** directory.

---

## **2. Automated Testing in Django with pytest-django**

For Django, we can use either the built-in **`unittest`** module or **`pytest-django`** for testing. We’ll cover both approaches, but we recommend using **`pytest-django`** for better flexibility and features.

### **Option 1: Using pytest-django**

### **Step 1: Install pytest-django**
```bash
pipenv install pytest pytest-django
```

### **Step 2: Configure pytest-django**
In your **`pytest.ini`** or **`conftest.py`** file, configure the test environment:

```ini
[pytest]
DJANGO_SETTINGS_MODULE = django_crud_api.settings
```

### **Step 3: Writing Test Cases**
Create a test file in **`users/tests/test_views.py`**:

```python
import pytest
from django.urls import reverse
from rest_framework.test import APIClient
from users.models import User

@pytest.fixture
def api_client():
return APIClient()

@pytest.fixture
def create_user():
return User.objects.create(name="John Doe", email="[email protected]", age=30)

def test_create_user(api_client):
url = reverse('user-list') # Use Django’s reverse function for the URL
response = api_client.post(url, {"name": "Jane Doe", "email": "[email protected]", "age": 25}, format='json')
assert response.status_code == 201
assert response.data['name'] == "Jane Doe"

def test_get_users(api_client, create_user):
url = reverse('user-list')
response = api_client.get(url)
assert response.status_code == 200
assert len(response.data) > 0

def test_update_user(api_client, create_user):
url = reverse('user-detail', args=[create_user.id])
response = api_client.put(url, {"name": "John Smith", "email": "[email protected]"}, format='json')
assert response.status_code == 200
assert response.data['name'] == "John Smith"

def test_delete_user(api_client, create_user):
url = reverse('user-detail', args=[create_user.id])
response = api_client.delete(url)
assert response.status_code == 204
```
- **`reverse()`**: Generates the URL for API endpoints.
- **APIClient**: DRF’s test client for making API requests.

### **Step 4: Running Tests**
To run the tests:
```bash
pytest
```

---

### **Option 2: Using Django's Unittest Framework**

If you prefer **`unittest`**, you can write test cases similarly. In **`users/tests.py`**, add:

```python
from django.test import TestCase
from django.urls import reverse
from users.models import User

class UserTests(TestCase):
def setUp(self):
self.user = User.objects.create(name="John Doe", email="[email protected]", age=30)

def test_create_user(self):
response = self.client.post(reverse('user-list'), {
"name": "Jane Doe", "email": "[email protected]", "age": 25
})
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data['name'], "Jane Doe")

def test_get_users(self):
response = self.client.get(reverse('user-list'))
self.assertEqual(response.status_code, 200)
self.assertGreater(len(response.data), 0)

def test_update_user(self):
response = self.client.put(reverse('user-detail', args=[self.user.id]), {
"name": "John Smith", "email": "[email protected]"
})
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['name'], "John Smith")

def test_delete_user(self):
response = self.client.delete(reverse('user-detail', args=[self.user.id]))
self.assertEqual(response.status_code, 204)
```

Run these tests with:
```bash
python manage.py test
```

---

## **3. Manual Testing Using Postman**

**Postman** is a powerful tool that allows you to manually test your RESTful APIs by sending HTTP requests to your server.

### **Step 1: Setting Up Postman**

1. **Install Postman**: Download and install Postman from the [official website](https://www.postman.com/downloads/).
2. **Create a New Collection**: Organize your API requests in a collection. A collection helps you manage different endpoints, including GET, POST, PUT, and DELETE requests.

### **Step 2: Sending Requests**

Here’s a mini-tutorial to test each CRUD operation manually:

1. **POST (Create a User)**:
- In Postman, select **POST** and enter the URL: `http://127.0.0.1:5000/users` (or your Django API URL).
- In the **Body** tab, select **raw** and **JSON** format, then enter the following JSON:
```json
{
"name": "Jane Doe",
"email": "[email protected]",
"age": 25
}
```
- Click **Send** to create the user. You should receive a **201 Created** response with the new user’s details.

2. **GET (Retrieve All Users)**:
- Select **GET** and enter `http://127.0.0.1:5000/users`.
- Click **Send**. You should receive a **200 OK** response with a list of users.

3. **GET (Retrieve a Single User)**:
- Select **GET** and enter `http://127.0.0.1:5000/users/1` (replace `1` with the correct user ID).
- Click **Send**. You

should receive a **200 OK** response with the user’s details.

4. **PUT (Update a User)**:
- Select **PUT** and enter `http://127.0.0.1:5000/users/1`.
- In the **Body** tab, enter the updated user details:
```json
{
"name": "Jane Smith",
"email": "[email protected]"
}
```
- Click **Send** to update the user. You should receive a **200 OK** response with the updated details.

5. **DELETE (Delete a User)**:
- Select **DELETE** and enter `http://127.0.0.1:5000/users/1`.
- Click **Send**. You should receive a **200 OK** response with a confirmation of the deletion.

## **4. Conclusion**

- Testing RESTful APIs is critical for ensuring their correctness and reliability. With automated testing in Flask and Django using **`pytest`**, **`unittest`**, or **`pytest-django`**, you can cover a wide range of test cases for your endpoints. Postman provides a manual way to test your APIs and verify responses.

0 comments on commit 03b1dda

Please sign in to comment.