URL Shortener

Level: Intermediate 30–60 min

Concepts: Strings

Solutions: C# | TypeScript | Python


Write a library that takes a long URL and converts it to a shortened URL similar to https://goo.gl/.

  • The library should have a method that accepts the long URL and returns the shortened URL.
    • The library should generate a short URL like https://short.url/abc1234 and store the short URL and the long URL together in an in-memory data store. E.g. A dictionary.
  • The library should have a method called translate which takes in a long or short URL and returns the shortened URL.
  • The library should track the number of times the short URL is visited.
  • The library should have a statistics method for the shortened URLs. Calling the method with the long or short URL should show the short URL, the long URL, and the number of times the short URL was accessed.

Hint

Don’t worry about invalid URLs, focus on functionality. Use only an in-memory data store.

Bonus

  • Throw an error if an invalid URL is provided.
  • Detect duplicate URLs and return the existing short URL instead of creating a duplicate.
  • Record the date and time each short URL was accessed via the translate method.
    • Create a method log which is similar to the statistics method. It should print the short and long URL with the number of times access as well as a complete history of all accesses.

Reference Walkthrough

Reference implementations in C#, TypeScript, and Python live at tddbuddy-reference-katas/url-shortener. Fourteen shared scenarios cover shorten / translate / statistics across both directions of the URL ↔ short-code mapping, including deduplication, visit counting on short-URL translates only, and byte-identical unknown-URL errors — satisfied identically across all three languages.

This kata ships in Agent Full-Bake mode at high gear (F1 tier): a small stateful Shortener class with no builders. The short-code scheme is base36 sequential — the first URL shortens to https://short.url/0, the eleventh to .../a, the thirty-seventh to .../10. This makes the scenarios spec-able in plain prose rather than forcing every test to pre-compute a hash digest; collision handling disappears by construction. A bonus track (invalid-URL rejection, access-time history, log method) is left as an extension — the core spec is what the three implementations satisfy. See the repo’s Gears section for when high gear is the right call.


  • Katas Are Rehearsal, Not Performance
    You don't practice TDD on production code. You practice on katas and bring the muscle memory to production. The gap between knowing TDD and doing TDD is reps.
  • Test Deletion Is a Privileged Operation
    The cheapest way for an agent to make a failing test pass is to delete it. That is logical for the agent and catastrophic for the codebase. Tests are append-only by default. Deletion needs a human author, a separate commit, and a separate review.
  • Refactor Was Always Where Compounding Lived
    Red and green were the visible two thirds of TDD. Refactor was the optional polish. Codebases that compound did the refactor pass; codebases that accrete did not. Agents skip refactor by default because it has no green-bar reward, and a year of skipped refactors is how a codebase loses its shape.