Blog Web App

Level: Intermediate 30–60 min

Concepts: Business LogicMockingBoundariesValidation

Solutions: C# | TypeScript | Python


Build the backend logic for a simple blogging application. No UI — focus on the domain rules, authorization, and using test doubles to fake persistence.

Requirements

Posts

  • A user can create a blog post with a title and body
  • A user can edit their own posts
  • A user can delete their own posts
  • A user cannot edit or delete another user’s posts
  • Attempting to modify another user’s post returns an error

Comments

  • Any user can comment on any post
  • Comments belong to the post and the commenting user
  • A user can delete their own comments

Tags

  • A post author can add tags to their own posts
  • A user cannot add tags to another user’s posts
  • Tags are visible to all users

Queries

  • Recent posts — retrieve the N most recent posts across all users
  • Posts by tag — retrieve all posts with a given tag
  • All tags — list all tags used in a specific user’s blog

Test Cases

ScenarioExpected
Create postPost exists with title, body, author
Edit own postPost updated
Edit other’s postError: unauthorized
Delete own postPost removed
Delete other’s postError: unauthorized
Comment on postComment added to post
Add tag to own postTag added
Add tag to other’s postError: unauthorized
Recent posts (5)Returns 5 most recent
Recent posts, only 3 existReturns 3
Posts by tag “TDD”Returns matching posts
Posts by tag, no matchesReturns empty list
All tags for userReturns unique tag list

Bonus

  • Add post publishing — posts start as drafts, only published posts appear in queries
  • Add pagination to recent posts and tag queries
  • Add a “like” system — users can like posts (once per user per post)
  • Add full-text search across post titles and bodies

Hint

Use test doubles (mocks, fakes, or stubs) for the data layer. Define a repository interface (e.g. PostRepository) and fake it in tests. This keeps tests fast and focused on business rules. Start with create and read, then add authorization checks, then tags and comments as separate concerns.

Reference Walkthrough

Full C#, TypeScript, and Python implementations live at tddbuddy-reference-katas/blog-web-app with twenty-five scenarios across all three languages, a fluent BlogBuilder, domain-specific UnauthorizedOperationException for authorization boundaries, and a Clock collaborator so tests control timestamps deterministically.

The Blog aggregate root owns all mutations. Authorization checks (EnsureAuthorOfPost) guard edit, delete, and tag operations with byte-identical error messages across all three languages. The builder seeds posts, comments, and tags by post index so test setup reads like a scenario description.


  • Examples Pin Intent. Properties Pin the Invariants.
    Example-based tests anchor scenarios in the team's vocabulary. Property-based tests anchor invariants across the input space. The agent needs both axes, and most suites only carry one.
  • The Test Pyramid Was an Economic Argument
    The test pyramid was not a quality law. It was a cost structure: unit tests were cheap, integration tests were expensive, so you wrote many of the first and few of the second. Agents collapsed the cost of writing tests at every level, and the cheapest test that still tells the truth is the one that pins a seam the agent cannot fake.
  • Agents Amplify Whatever Vocabulary They Find
    Agents do not bring vocabulary to your codebase. They mirror what's already there. Strong vocabulary gets agent contributions that read like the team. Weak vocabulary gets faster mediocrity. The work you did for craft reasons just became leverage.