DEV Community

Cover image for Building My Own Technical Interview Practice Repository
Johann Gaviria
Johann Gaviria

Posted on

Building My Own Technical Interview Practice Repository

Preparing for technical interviews has made me realize something:

solving more exercises doesn't necessarily mean practicing better.

I've spent quite a bit of time solving programming problems, reviewing Python concepts, working on backend projects, and preparing for technical interviews.

But there was always something missing.

I didn't have a consistent way to practice.

Sometimes I'd solve an algorithmic problem. Other times I'd work on some business logic. Then I'd look at a random interview question online.

It worked, but it felt disconnected.

So I decided to build something for myself.

The project is called Technical Tests.

It's a repository designed to help me practice technical interviews for Junior Backend Developer, Junior Python Developer, and Software Engineering Intern roles.


Why Build Another Exercise Repository?

There are already plenty of platforms for coding challenges.

LeetCode, HackerRank, CodeSignal, and many others are great resources.

But I wasn't trying to replace them.

I wanted something slightly different.

I wanted exercises that felt closer to the kind of problem I might actually encounter during a junior backend interview.

Not necessarily:

"Implement this famous algorithm."

But rather:

"Here's a small system with some business rules. Figure out how to process this data correctly."

That difference is important to me.

Backend development isn't only about algorithms.

You also need to understand requirements, translate them into logic, handle edge cases, choose appropriate data structures, write maintainable code, and think about complexity.

So the exercises are designed around those skills.


What Kind of Exercises?

Each exercise is intended to take roughly 30–60 minutes.

The difficulty stays within:

  • Easy
  • Easy/Medium
  • Medium

And each exercise focuses on one coherent problem.

For example, an exercise might involve an inventory system where you need to process stock events and determine which products need to be reordered.

Or a room allocation problem where you need to process booking requests according to availability and business rules.

These problems can combine several concepts without becoming artificially complex.

Some of the things I want to practice are:

  • Lists and dictionaries
  • Sets
  • Sorting
  • Searching
  • Frequency counting
  • Two pointers
  • Sliding windows
  • Stacks and queues
  • Basic greedy strategies
  • Data transformations
  • Business rules
  • Validation
  • State management
  • Resource limits
  • Edge cases
  • Time and space complexity

The important part is that these concepts appear inside a problem, rather than as isolated exercises.


The AI Part

One of the more interesting parts of this project is that I'm using AI coding agents to help generate and evaluate the exercises.

But I don't want the AI to simply generate a problem and a complete solution and call it a day.

That wouldn't really help me practice.

So I created repository-level rules that define how exercises should be generated.

The agent has to follow constraints such as:

  • Generate exactly one exercise at a time.
  • Keep the problem suitable for junior developers.
  • Avoid trivial programming exercises.
  • Avoid simply copying well-known platform problems.
  • Keep exercises self-contained.
  • Prefer the Python standard library.
  • Include public and hidden tests.
  • Include evaluation criteria.
  • Keep the candidate-facing starter code minimal.

That last point became particularly important.


The Starter Code Problem

Initially, I was tempted to provide more structure in the starter code.

For example, an exercise might start with predefined:

  • constants
  • enums
  • dataclasses
  • error types
  • helper functions
  • domain models
  • result structures

It looked organized.

But there was a problem.

It was also giving away too much of the solution.

If the exercise tells me that I need a BookingStatus enum, a BookingResult dataclass, three helper functions, and a particular domain model, then I'm already being guided toward a specific implementation.

That's not what I wanted.

So I changed the philosophy.

The starter code should answer:

"Where do I implement my solution?"

Not:

"How should I implement the solution?"

Minimal starter code philosophy

For example, a starter might simply look like:

def process_bookings(rooms: list, requests: list) -> dict:
    """Process booking requests and return the allocation report."""
    raise NotImplementedError
Enter fullscreen mode Exit fullscreen mode

That's it.

The README explains the requirements.

The starter tells me where to start.

I decide how to solve it.

That means I have to make the design decisions myself:

  • What data structures should I use?
  • Do I need helper functions?
  • Should I create classes?
  • How should validation work?
  • How should errors be represented?
  • Can I solve it in one pass?
  • Do I need sorting?
  • What's the complexity?

That's much closer to an actual interview.


README → Starter → Candidate

This led to a simple principle for the repository:

README
  ↓
What needs to be solved?

Starter
  ↓
Where do I implement it?

Candidate
  ↓
How do I solve it?

Tests
  ↓
Did the solution actually work?
Enter fullscreen mode Exit fullscreen mode

The tests shouldn't care whether I used three functions or one.

They shouldn't care whether I created a class.

They shouldn't care whether I used a dictionary, a list, or another appropriate data structure.

They should care about the documented behavior.

This also makes the evaluation more fair.

For example, if two candidates solve the same exercise using completely different internal designs, both should be accepted if their implementations satisfy the contract.


Testing

Each exercise has public and hidden tests.

The public tests are there to make the expected behavior clearer and allow the candidate to verify their implementation.

The hidden tests are intended to catch cases such as:

  • Empty input
  • Single-element input
  • Duplicate values
  • Boundary conditions
  • Conflicting business rules
  • Invalid states
  • Large inputs
  • Incomplete implementations
  • Cases where an apparently correct solution breaks under less obvious conditions

The tests interact only with the documented public interface.

They don't depend on the internal structure of the candidate's solution.

For example, if two candidates solve the same exercise using completely different internal designs, both should be accepted if their implementations satisfy the contract.


Evaluation

After solving an exercise, the repository can also evaluate the implementation.

The default scoring model is:

Category Points
Functional correctness 50
Edge cases 15
Code quality 15
Complexity 10
Python usage 10
Total 100

The score is then converted into a grade from 1 to 10.

The evaluation also produces feedback about:

  • What was done well
  • Problems found
  • Potential improvements
  • Complexity
  • Code quality
  • Interview-oriented feedback

The goal isn't to pretend that an automated score is equivalent to a real interviewer.

It's simply another way to get structured feedback after solving the exercise.


Keeping the Architecture Simple

Another decision I made was to avoid unnecessary infrastructure.

These aren't backend applications.

I don't need:

  • FastAPI
  • Django
  • PostgreSQL
  • Redis
  • Docker
  • External APIs
  • Authentication
  • Cloud infrastructure

The goal is to practice problem solving and Python, not spend an hour configuring infrastructure before getting to the actual problem.

That doesn't mean those technologies aren't useful.

They are.

But they belong in other projects and exercises.

For this repository, the Python standard library and pytest are enough for most problems.


Repository Structure

The repository is intentionally simple:

technical-tests/
├── AGENTS.md
├── README.md
├── docs/
│   ├── EXERCISE_RULES.md
│   └── EVALUATION_RULES.md
│
└── exercises/
    └── YYYY-MM-DD-test-name/
        ├── README.md
        ├── EVALUATION.md
        ├── 
        ├── docs/
        │   ├── README.es.md
        │   └── EVALUATION.es.md
        ├── pyproject.toml
        │
        ├── solution/
        │   └── solution.py
        │
        └── tests/
            ├── test_solution.py
            └── test_solution_hidden.py
Enter fullscreen mode Exit fullscreen mode

Each exercise is self-contained.

The root README acts mostly as an index.

The detailed rules live separately so that the project documentation doesn't become unnecessarily large.


The Workflow

The workflow I'm aiming for is simple:

Technical interview practice workflow

The interesting part is that the repository itself becomes part of the learning loop.

Instead of just solving a problem and moving on, I can look back at:

  • How I approached the problem.
  • Where I made mistakes.
  • Which edge cases I missed.
  • Whether my solution was unnecessarily complex.
  • How I could improve the implementation.

Over time, that should give me a better picture of where I actually need to improve.


What I'm Learning From Building It

Ironically, building a repository for practicing interviews has already taught me a few things.

1. Designing a good exercise is harder than it looks

It's surprisingly easy to create a problem that is either:

  • too trivial,
  • too ambiguous,
  • too difficult,
  • too long,
  • or accidentally gives away the solution.

Finding the middle ground is harder.

2. More structure isn't always better

I like clean architecture and well-defined abstractions.

But an interview exercise doesn't necessarily benefit from having every possible abstraction predefined.

Sometimes giving less structure creates a better problem.

3. Tests are part of the specification

Writing tests forced me to think about what the actual contract of an exercise is.

If a test depends on an internal implementation detail, that's probably a bad test.

4. AI needs constraints

AI can generate code and problems extremely quickly.

But "generate something" isn't the same as "generate something useful."

The repository rules are there to constrain the agent and keep the exercises consistent.


What's Next?

For now, the project is intentionally small.

My plan is to gradually build a collection of exercises covering different areas of backend-oriented problem solving.

I'd like to eventually have exercises around:

  • Inventory management
  • Orders
  • Reservations
  • Loans
  • Scheduling
  • Permissions
  • Billing
  • Resource allocation
  • Data processing
  • Algorithms and data structures

But I don't want to turn it into a giant collection just for the sake of having hundreds of exercises.

I'd rather have fewer, well-designed problems that actually make me think.


Final Thoughts

I'm building this mainly for myself.

I'm currently preparing for professional practice and junior backend opportunities, and I wanted a more structured way to work on the part of software development that is difficult to practice through personal projects alone:

solving problems under constraints.

Maybe it will eventually be useful to someone else too.

But for now, the goal is pretty simple:

practice consistently, understand my mistakes, and get a little better with every exercise.

And what do I know, I'm just a junior dev.


Repository

The project is available on GitHub: Technical Tests

If you're also preparing for technical interviews, feel free to take an exercise and solve it without looking at the reference solution.

That's kind of the point.


Created with ♥️ by JohannGaviria; And what do I know, I'm just a junior dev.

Top comments (0)