Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I was asked this question in an interview and it has been bugging me ever since.

You have two projects, both with the same specification but only one of these projects was developed using Test Driven Development. You are given the source for both but with the tests removed from the TDD project. How can you tell which was developed using TDD?

All I was able to muster up was something about the classes being more “broken up” into smaller chunks and having more visible APIs, not my proudest moment. I would be very interested to hear a good answer to this question.

share|improve this question
4  
Are you able to follow up on your interview with an email? I'm curious if they were looking for a specific answer or were just looking to test your communication skills (is the answer a stream-of-consciousness or a testable hypothesis, clearly stated?). –  ccoakley Mar 21 '12 at 1:12
    
I agree with ccoakley - why not invite them to provide the answer on SO? –  JW01 Mar 27 '12 at 18:40
    
There will be no difference at all between both except the fact that the developpers on the TDD project will be more confidents about maintaining their code. (check slide 35 slideshare.net/rowan_m/tdd-and-getting-paid) it gets the heart of the idea –  JF Dion Mar 28 '12 at 19:18
add comment

14 Answers 14

up vote 47 down vote accepted

The people in the interview have assumed that someone developing code does not know how to properly abstract out things like separation of concerns, dependency injection, single responsibility, etc. unless they are using TDD. This is a horrible interview question, and you should think nothing less of yourself for not being able to provide a reasonable answer. The only real answer is "you can't".

I've seen much code that has had improper tests written for it, and as such has forced the code into a form that is not conducive to maintenance. I have also seen exceptionally easy to maintain code written without a single test.

share|improve this answer
9  
I agree. IMO the real answer "if you can tell the difference then someone didn't know what they were doing." In particular, a project developed using TDD and a project designed to be unit tested later should look nearly identical. –  Michael Edenfield Mar 21 '12 at 2:30
13  
I don't know that it's a "horrible question." It sounds to me like a roundabout way of seeing whether a candidate has experience with the benefits (or simply effects) that a TDD approach has on a code base. Of course it's theoretically possible to develop the same code with two different approaches, but it's not very likely. On average, there are likely to be differences in the TDD and non-TDD codebase and, on average, these differences are likely to take on similar forms. This might also be true of, say, developing with IDE 1 vs IDE 2. –  Erik Dietrich Mar 21 '12 at 5:03
1  
In an ideal world this would be true, but here in the real world code developed using TDD looks drastically different from code that wasn't. –  BlueRaja - Danny Pflughoeft Mar 21 '12 at 18:07
2  
I think that @BlueRaja-DannyPflughoeft gave an answer that would have been better in my interview. On reflection I may have indicated a lack of knowledge of TDD and this Q was given as an opportunity for me to talk about some attributes of TDD code. So for me, I think this was not a bad interview question. However, alone and with no other context I think I would agree with the answer to this Q. That and the community seems to have deemed this the best answer. –  Andy Smith Mar 30 '12 at 9:48
2  
I disagree. If you've done a reasonable amount of TDD, you'll have an idea of how to answer this question. And that's what the question really aims to find out: Have you really done TDD, or have you just read about it in a book? –  Kyralessa Apr 11 '12 at 19:09
show 5 more comments

Actually, a lot of sacrifices must be made to make code testable. Because of this, code written using TDD tends to look very distinct from non-TDD code:

  • Almost every class will have its own interface. This is because, in C#, it's not possible to mock concrete classes. In Java, it is possible, but most of the major mock-object frameworks discourage it anyways.
  • Dependency Injection. The cost of Dependency Injection can often outweigh the benefits, so even in non-TDD projects that do use DI, it won't be used everywhere. However, once you call new MyClass() in a method, that method can no longer be tested in isolation from MyClass. Thus, in a TDD project, almost every class will either be injected or have a factory-class injected. Which leads us to...
  • Most classes not instantiated at startup will have a separate factory class for the reasons stated above.
  • All classes are public. This is because non-public classes can't be accessed (and thus tested) from a separate project. Yes, this defeats the purpose of having access specifiers on classes at all, but thus is the world we live in.
  • Much fewer methods are private, because private methods can't be tested. What often happens in TDD-code instead is that we pull the private methods into a separate class, or we make the methods public, but not include them in the interface.
  • Modularity. Projects utilizing TDD tend to be more modular, simply because the more modular something is, the easier it tends to be to test.
share|improve this answer
12  
For C# making the classes public would be a mistake. They should be marked internal, and made visible to the test assembly using System.Runtime.CompilerServices.InternalsVisibleToAttribute, which is exactly the approach used for unit testing the Framework's Class librasries. Alternatively, one can use private reflection to test a private class, potentially using dynamic to avoid explictly using reflection except to instantiate the class. –  Kevin Cathcart Mar 21 '12 at 16:25
1  
I've tested a lot of concrete classes in my day. You definitely need to hide external dependencies behind interfaces but most POCOish stuff is quite testable without resorting to tricks like that. –  Wyatt Barnett Mar 21 '12 at 17:56
3  
The first five illustrate that the developer doesn't know what they are doing if they have to do all that boilerplate indirection and extra work to simply write a few tests. None of those first five things are indicative of anything but a massive dependency on frameworks to do your job for you and lack of comprehension of how to actually test what matters without throwing out all the features that make an OO language powerful in the first place. No private methods, really? If that was the answer I got, that would end the interview in a negative way pretty quickly. –  Jarrod Roberson Mar 28 '12 at 18:03
2  
@BlueRaja-DannyPflughoeft your predication that TDD is required for large programs is flawed and incorrect. I have been doing development of all scales for 20+ years, and there have been millions lines of code applications written that were safe, secure, robust, maintainable and bug free before TDD was the buzz word of the day. Your opinion about dependencies is flawed, properly designed systems don't need all these compromises to be tested in a meaningful way, all these compromises tend to make tests less valuable and meaningful. Integration tests are way more valuable than useless mocks. –  Jarrod Roberson Mar 28 '12 at 19:06
3  
@Jarrod: I think you misread. I never said large programs need TDD - I said large programs that use TDD need the sacrifices I listed (workarounds to deficiencies in languages that were not designed with TDD in mind) to have meaningful unit-tests. And I agree that integration tests are useful, but these are a completely separate thing from unit-tests and TDD, which are also useful, for different reasons. I think you are confusing "has tests" with "developed using TDD." –  BlueRaja - Danny Pflughoeft Mar 28 '12 at 19:12
show 5 more comments

I would generally say that you're going to have better "seams" for decoupling in the TDD code base. It's not just about being smaller or more "broken up", but rather about being more modular.

A TDD code base often makes me think of Legos in a vague way. That is, you have a bunch of small, independent (with help from interfaces) components that can be assembled or mixed and matched at runtime, largely in whatever fashion you please. Contrast this with a non-TDD code base, where this outcome is much less likely. TDD forces me to have ways to set an object's dependencies, and so I do. Non-TDD allows me to build Iceberg Classes that monolithically hide all decision making about collaborators and object creation.

Edit: In addition, you'll tend to see much less use of static methods and state in TDD code-bases, in my experience.

share|improve this answer
4  
+1 I would also add that non-TDD code tends to utilize more defensive programming techniques and null checking. –  bcarlso Mar 21 '12 at 3:38
    
@bcarlso That's a good point. There tends to be more "future-proofing" and "idiot-proofing" that is really just guessing at usage scenarios and paths through the code. A TDD API already has a thorough 'client', so you see less of this. –  Erik Dietrich Mar 21 '12 at 5:00
add comment

This seems like an odd question to ask for an interview, but here you go:

The cyclomatic complexity of subroutines follows a power-law distribution. So, if you graph a cumulative histogram of the cyclomatic complexity of the individual subroutines on a log-log scale, you will get a straight line. The magnitude of the slope of the line tells you wether the project was developed using TDD or not: anything above 2 is with TDD, below 2 is without.

Note: nobody knows why that is so. Nobody knows what the slope of the line means. Nobody knows if the slope even means anything. But, AFAIK, nobody has yet been able to find a counterexample. Also, people generally find that code that they are happy with always has a steeper slope than code they are unhappy with. And they find that refactorings which subjectively improve code quality always lead to a steeper slope.

  • Author interprets this measure as

    A steeper distribution [larger magnitude of the slope] suggests a preference for less complex methods

Source: Measure for Measure – Keith Braithwaite.

share|improve this answer
    
Regarding your comment... so I can just run measure against (a directory containing?) my codebase and get a number (for the slope of the line in log-log space)? Is this difficult to set up and run? If you are sincerely curious, and my employer is amicable to the idea (a bigger question), I will attempt to do this. –  ccoakley Mar 21 '12 at 0:41
    
Its not a particularly odd question if one assumes (!) that its one that's designed to highlight the interviewee's practical knowledge off TDD and also to make the interviewee think and provide reasoned explanation/discussion - whether its a good question or one that has an answer as an absolute is a separate issue. –  Murph Mar 21 '12 at 12:10
    
Well, I ran measure: regression: |alpha| = 2.15. I guess we are TDD after all (according to measure, not our dev practices). Incidentally, the graph takes a huge dive when the Cyclomatic Complexity hits 30 on the output graph. It's not very straight there. That's good, right? –  ccoakley Mar 21 '12 at 16:49
    
I note that the original research just looks at code with and without tests, not specifically highlighting TDD. Without a follow-up on each project analyzed, it is quite a leap to say that tests=TDD (your comment reaches the same conclusion. Now you have empirical support). –  ccoakley Mar 21 '12 at 17:24
1  
I found this description confusing: talking about a slope greater than 2 made me think that TDD corresponded to greater complexity. After reading the article, I see that the slope is actually -2, which makes more sense. I wonder why the author left out the negative sign in the descriptive text. –  AShelly Mar 21 '12 at 17:49
add comment

The TDD project makes heavy use of the dependency injection pattern. The non-TDD project uses it sparingly, if at all.

share|improve this answer
7  
Interesting. I am working on a project that makes heavy use of DI, but is not a TDD project. Though we have nearly 100% test coverage, we violate several other tenets of TDD. I'm not sure you could distinguish our project from a TDD project by looking at the code. –  ccoakley Mar 20 '12 at 21:50
1  
@ccoakley: It would be very interesting to see whether Keith Braithwaite's metrics work on your project. He says that he can reliably distinguish between open source Java projects which have been published with automated unit tests and those that have been published without. Then he makes the leap that projects that don't publish automated unit tests probably don't have them (a reasonable assumption) and that projects which do publish them probably use them (an even more reasonable assumption). From there, he makes the next leap: projects which don't have tests don't use TDD (obvious), … –  Jörg W Mittag Mar 20 '12 at 23:45
1  
… while projects which do have a large number of automated unit tests probably used some form of TDD. It's this last assumption that is the most shaky one. I have yet to see a counterexample, but maybe yours is one? –  Jörg W Mittag Mar 20 '12 at 23:47
    
@JörgWMittag well, there's a caveat there, isn't there? "Some form of TDD." While the project (which is for a financial services firm, so not exactly open source) uses automated testing, has high test coverage, and tries not to overgeneralize implementation, I would argue that not putting "test first" makes us not TDD. Braithwaite may still argue that we fall under "some form of TDD". Conversely, when using Braithwaite's "measure" or some other automated system, you might find some sort of fingerprint to distinguish us. Whether you'd be able to do so by manual code inspection is less certain. –  ccoakley Mar 21 '12 at 0:29
    
Just to clarify, I put quotes around "measure" because it is the name of a piece of software by Braithwaite. It wasn't an awkward emphasis of the word "measure" or a misquote of metric. –  ccoakley Mar 21 '12 at 0:32
add comment

Presumably, any feature implemented to spec in TDD would have a test written for it (first). The TDD project will have a subset of functionality but will implement each feature with simple objective tests correctly.

The idea is that the other project will implement a feature first, then fix bugs found.

The assumption here is that both projects are not yet complete. For the TDD project, not all features have been implemented. For the non-TDD project, not all bugs have been ironed out.

In the interview, this is explained by a hand-wavy explanation that both projects asymptotically approach the ideal project state of feature-complete and bug-free. The TDD project approaches it from the bug-free direction and the non-TDD project approaches it from first hitting the features.

This would quickly be followed with the ol' "Does this rag smell like chloroform to you?" and some sub-conscious (unconscious) hypnosis technique. If you have the flashy-thing from Men In Black, you can use that instead of chloroform.

Edit: after reading the other responses, I think I have a better one:

There's a TDD principle: Write just enough code to pass the test

Look for code above and beyond the spec (i.e. anticipating future expansion of scope), in any method. Similar features like generalizing cases with only one concrete implementation are also signs. TDD shouldn't have such things.

share|improve this answer
add comment

Look at the interfaces in the system

The easiest way to test something is to provide dummy implementations on the things needed that are not under test.

If you have interfaces describing larger chunks of the system then it is a very good indication that those interfaces were used in a test.

Then have a look at the methods in these interfaces describing larger chunks, and evaluate how well thought out they appear to be. It usually shows very clearly if they were written before or after the main code hiding behind the interface. If most or all of them were written before the main code implementing them, then it is a very good indication that TDD was used.

share|improve this answer
add comment

Seems like an unanswerable question. As I see it, the interviewer expected either:

  1. A "clever", but concrete answer. Something like, "feature language X is not used in a TDD project because such code cannot be tested."

  2. A bunch of vague points about how the TDD project should have less redundant code, easily used APIs, fewer bugs, more modules/classes, in other words things that are not necessarily true, but somehow prove that the candidate "knows" what TDD is (or has read all the hype about it).

In either case the question could have been better phrased. (To clarify, I think TDD is a great idea, and I try to use it when I can, but I'm also perfectly aware that some people can produce amazing code without writing tests.)

Why don't you ask the interviewer what he had in mind, if that's possible?

share|improve this answer
1  
Think about the interview process - its seems to me that this is a way of exploring both knowledge and communication skills –  Murph Mar 21 '12 at 12:11
add comment

As evidenced by this article analyzing a study of TDD in relation to code quality, the TDD code will be of worse quality than the non TDD code. Though this study only had 2 groups, one that tests first (TDD) and one that wrote code first, but did use unit tests. So this would only be true if both samples had unit tests.

share|improve this answer
add comment

How can you tell which was developed using TDD?

If it is done properly, then there are no ways to tell which process is used to create an application. Not even if you can take a look into the unit tests.

Of course, if there are no unit tests, or low unit test code coverage, then it's easy :)

share|improve this answer
add comment

Check for excess parenthesis.

There are two ways to try and reduce the bugs in your code. You can test things or you can try to write your code very carefully. A common form of trying to be careful is not trusting the precedence rules of the programming language. Instead, programmers tend to explicitly parenthesize everything to make sure that there are no surprises. In contrast the TDD developer doesn't put in the parenthesis because he trusts that any silly errors he makes will get caught by his tests.

It comes down the question of what the developers trust to deal with bugs. Do they trust in their coding style or in their tests? I think that'll give a very good indication of whether they are TDD or not.

share|improve this answer
1  
Sounds more like being familiar with the language or not, rather than test-dependent. –  user1249 Mar 21 '12 at 0:37
    
@ThorbjørnRavnAndersen, agreed and I'm not entirely serious. But I think there's a small amount of truth to it. –  Winston Ewert Mar 21 '12 at 2:03
2  
I sometimes write parentheses to make the code more readable, even though I know that they are not necessary. For example, instead of a and b and c or d and e and f, I write (a and b and c) or (d and e and f) just for readability. –  user281377 Mar 22 '12 at 8:59
1  
@ammoQ, certainly in some cases its sensible to have more then strictly neccessary. Its the poeple who do it everywhere that I find suspicious. –  Winston Ewert Mar 23 '12 at 14:47
add comment

It very largely depends on the code written.

While some languages will show a heavy usage of interfaces in a TDD project, this isn't a very specific criteria that would guarantee you could tell either way. You can develop TDD in non-OO and non-interface-supporting languages also. I found it odd that none of the other answers (at the time I write this) seem to have addressed this, though I suspect that this could be because of the Java tag on the question.

If both projects are well factored, contain no duplication, and can be said to meet all of the requirements, then it really should be impossible to tell which project was specifically TDD. If not, then you might in a very general sense be looking for the program that may contain duplication, and may be more likely to exhibit a number of methods that do more than they strictly should. Even so, the quality of the code will largely come down to the experience of the team members working on it, and just how fussy those developers are about sticking to the SRP and DRY principals.

share|improve this answer
add comment

Are you sure this wasn't intended as a trick question? I could imagine many answers being of the form where someone either rants or raves about how TDD would produce X, Y and Z in the code and thus they would figure it out that way.

Could you come back with a, "Why would you want to know such an answer?" just to see what the main point is of asking such a question. Course an interviewer may reply, "This is just a hypothetical to see how well do you know TDD," or something like that.

share|improve this answer
add comment

I would sum it up something like this. The TDD code will have:

  1. Smaller classes and shorter methods
  2. Public properties and methods that make sense (in other words, they look like they were created before the code was written, because they were)
  3. Lots of dependency injection
  4. Objects created using factories and/or factory methods rather than using the "new" keyword
  5. Higher use of interfaces (not required, but TDD code will tend to have more interfaces)
  6. Fewer calls to static methods
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.