This topic comes up here all the time and I'm always shocked to see that this is even considered as a hiring practice and I'm surprised it's not outright illegal.

This problem exists in every field and for every kind of job. Nobody takes seriously the notion that a book-keeper candidate should do your accounting for a day to see if they should be hired, or have a contract manager negotiate a contract for a day for free, or a designer design for you for a day. So why are developers freed from this?

Because it's feasible for a developer to sit down in front of a terminal for a few hours and start hacking away?

Here's part of the problem from the candidate PoV

1) It's slave labor (obvious) and opens you up for a never ending series of small, but annoying lawsuits if you don't hire the candidates.

2) Candidate doesn't know if you're serious about hiring, or just doing a cattle call. There's a lot of reasons companies do this, but it's a practice used by some very well funded startups that wastes unbelievable amounts of people's time and is like a cancer in the industry.

3) Candidate likely has plenty of other irons in the fire, and your company isn't a special snowflake. If they're currently employed it's even worse as they have to figure out how to take time off of work to waste doing free work for somebody else. Now let's say they have to do this for the 20 companies they applied to, that's a month off of work!

4) Development on complex codebases is hard, most engineering companies don't really expect a new hire to be very productive on their codebase for a few months at best. It doesn't actually test them on their day-to-day as much as anybody might think, because their day-to-day job function will rapidly change over their first six months as they start to wrap their brains around the work.

What is appropriate?

1) Ask for a portfolio, open source projects, other work they've done, etc. Hopefully they have some kind of work history they can show off.

2) Irritating, but ask them to complete basic development tasks -- fizzbuzz is a good example. Surprisingly, most bad engineers will be stumped by surprisingly simple questions like "write a for loop" or "write a basic SQL query". If they pass that, ask more and more complex questions until they're at the level you need. You can usually figure out a candidate's skillset within 10 questions. But please, don't waste anybody's time with brain teasers and puzzles and other nonsense. Keep it focused and keep it real.

3) Actually have a conversation with the candidate. Plumb their knowledge. Ask them about various frameworks they've used, or languages they've experimented with or whatever. People who know their stuff can usually talk endlessly about their past experiences, people who don't can't and you end up with "well....C++ is nice, but Lisp is a great language!". Too many hiring processes forget this part of interviewing because it takes practice to get good at "interrogating". But it gets you so much soft information about a person as well.

4) With questionable candidates that you're 50-50 on, be open to offering probationary employment. 30-days, or 90-days or something. It must be well structured (weekly check-points, options to leave after the first 30 days, etc.), and you have to take it seriously. It's up-to the candidate if they want to take this or move on to other opportunities. If they move on, nobody's time was wasted. If they really need something right now and they take it, you have some exit valves if they stink, and if they're promising you can adjust final employment one-way or the other.

5) Something I hated at first, but have come around to a bit is the idea of a take-home problem they can work on at their leisure. Perhaps a problem that wouldn't take more than 2-4 hours to work on. Why is this different then having them hack on your code? Because you can make it not-your actual code, and can use it to concisely test exactly what you're looking for. Plus they're not taking time off of work to do this. They can spit-shine and polish their response as much as possible and really show off if they want.