In Part 1, we configured pytest, created a test database, and set up fixtures.
Now we focus on real test cases using the following models:
WriterCategoryBlog-
SocialMediaMeta(auto-created via signal when a blog is published)
1. Example Models
Writer
class Writer(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
Category
class Category(models.Model):
title = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
SocialMediaMeta
class SocialMediaMeta(models.Model):
blog = models.OneToOneField("Blog", on_delete=models.CASCADE, related_name="social")
twitter_title = models.CharField(max_length=255)
facebook_description = models.TextField()
Blog
class Blog(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
writer = models.ForeignKey(Writer, on_delete=models.PROTECT)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
published = models.BooleanField(default=False)
2. Signal That Auto-Creates Metadata
@receiver(post_save, sender=Blog)
def create_social_media_meta(sender, instance, created, **kwargs):
if created and instance.published:
SocialMediaMeta.objects.create(
blog=instance,
twitter_title=instance.title[:70],
facebook_description=instance.content[:200],
)
We will test whether this works.
3. Test Case 1 — Create Blog (Basic FK Handling)
@pytest.mark.django_db
def test_blog_creation(api_client, writer, category):
payload = {
"title": "Deep Dive into Django Testing",
"content": "This article explains...",
"writer": writer.id,
"category": category.id,
"published": False
}
response = api_client.post("/api/blogs/", payload, format="json")
assert response.status_code == 201, response.json()
assert response.json()["title"] == payload["title"]
4. Test Case 2 — Test Signal Execution
@pytest.mark.django_db
def test_published_blog_creates_social_meta(api_client, writer, category):
payload = {
"title": "Signal Test Blog",
"content": "Testing signal logic...",
"writer": writer.id,
"category": category.id,
"published": True,
}
response = api_client.post("/api/blogs/", payload, format="json")
assert response.status_code == 201
blog_id = response.json()["id"]
detail = api_client.get(f"/api/blogs/{blog_id}/").json()
assert "social" in detail
assert detail["social"]["twitter_title"] == payload["title"][:70]
5. Test Case 3 — Listing Blogs with Filter
@pytest.mark.django_db
def test_blog_list_filter_by_category(api_client, writer, category):
api_client.post("/api/blogs/", {
"title": "A",
"content": "AAA",
"writer": writer.id,
"category": category.id,
"published": False
}, format="json")
api_client.post("/api/blogs/", {
"title": "B",
"content": "BBB",
"writer": writer.id,
"category": category.id,
"published": False
}, format="json")
response = api_client.get("/api/blogs/?category=tech")
assert response.status_code == 200
assert len(response.json()) == 2
6. Test Case 4 — Nested JSON Response
@pytest.mark.django_db
def test_blog_detail_nested(api_client, writer, category):
blog = api_client.post("/api/blogs/", {
"title": "Nested Blog",
"content": "Testing nested serializer logic.",
"writer": writer.id,
"category": category.id,
"published": True
}, format="json").json()
detail = api_client.get(f"/api/blogs/{blog['id']}/").json()
assert detail["writer"]["name"] == writer.name
assert detail["category"]["title"] == category.title
assert "social" in detail
7. Test Case 5 — Update Blog
@pytest.mark.django_db
def test_blog_update(api_client, writer, category):
blog = api_client.post("/api/blogs/", {
"title": "Old Title",
"content": "Old content",
"writer": writer.id,
"category": category.id,
"published": False
}, format="json").json()
response = api_client.patch(
f"/api/blogs/{blog['id']}/",
{"title": "Updated Title"},
format="json"
)
assert response.status_code == 200
assert response.json()["title"] == "Updated Title"
8. Test Case 6 — Validation Error (Invalid FK)
@pytest.mark.django_db
def test_blog_invalid_writer(api_client, category):
payload = {
"title": "Invalid Blog",
"content": "Fails",
"writer": 999999,
"category": category.id,
"published": False,
}
response = api_client.post("/api/blogs/", payload, format="json")
assert response.status_code == 400
assert "writer" in response.json()["errors"]
9. Test Case 7 — Reverse FK Test
@pytest.mark.django_db
def test_writer_blog_count(api_client, writer, category):
api_client.post("/api/blogs/", {
"title": "Blog1",
"content": "AAA",
"writer": writer.id,
"category": category.id,
"published": False
}, format="json")
api_client.post("/api/blogs/", {
"title": "Blog2",
"content": "BBB",
"writer": writer.id,
"category": category.id,
"published": False
}, format="json")
response = api_client.get(f"/api/writers/{writer.id}/blogs/")
assert len(response.json()) == 2
Final Checklist (Both Parts in One Summary)
Setup (Part 1)
✓ Install pytest and plugins
✓ Create pytest.ini
✓ Create settings/test.py
✓ Set up PostgreSQL test_db
✓ Add fixtures (user, API client, writer, category)
✓ Handle custom users
✓ Ensure DRF authentication bypasses login
Use Cases (Part 2)
✓ Test FK creation (Writer, Category → Blog)
✓ Test signals creating related metadata
✓ Test nested JSON responses
✓ Test list endpoints and filters
✓ Test validation errors
✓ Test patch/update flows
✓ Test reverse FK relationships
✓ Use authenticated API requests
Top comments (0)