In this thread, Brian (the only answerer) says \"Your code should be written in such a fashion that it is testing-agnostic\"
The single comment says \"Your code shou
I read all these answers quite closely and they are all helpful. But perhaps I should reclassify myself: I appear to be becoming a low-intermediate TDD practitioner, rather than a newb. A lot of these points and rules of thumb I have already assimilated, either by reading or by sometimes baffling, occasionally bitter but always instructive experience over the past 6 months or so.
Carl Manaster's analogy with the Volkswagen scandal is seductive but slightly inapplicable, perhaps: I am not suggesting that the app code should "detect" that a test is happening and alter its behaviour as a result.
What I am suggesting is that there are one or two knotty, bothersome low-level problems where you might want to use this tool in a way that does not interfere in any way with the cast-iron rules and "philosophy" of TDD.
Two examples:
I have a few cases in my code where exceptions are thrown, and tests where I want to check they are thrown. Fine: I go doThrow( ... )
and @Test( expected = ... )
and everything works fine. But during a production run I want an error message to be printed out with a stack trace. During a test run I just want the error message. I don't want the logback-test.xml
to suppress error-level logging completely. But apparently there is no way to configure a logger to prevent printing out the stack trace.
So what I can do is to have a method like this in the app code, contrived solely for testing:
boolean suppressStacktrace(){ return false; };
... and then I use that as a test for a given LOGGER.error( ...
situation, and then mock that method to return true
when I want to provoke that exception during testing.
Secondly, the rather specific case of console input: BufferedReader.readLine()
. Substituting another InputStream
for System.in
and feeding it with a List
of different Strings
which will be served up once per readLine
is a right pain in the provberbial. What I have done is to have a private
field in the app class:
Deque inputLinesDeque;
... and a package-private
method to set this with an List
of input lines, which can then be pop
ped until the Deque
is empty. During an app run this Deque
is null
, so an if
branches to br.readline()
instead.
These are just 2 examples. No doubt there are other situations where the ultra-purist approach comes at too high a price, and arguably procures no real benefit.
However, I appreciate davidxxx's superior definition of one of the TDD 10 commandments: "thou shalt not create methods to suit your tests and that open the API of the application in an undesirable way". Very helpful: food for thought.
later
Since writing this a month ago I've realised it's far from impossible to extend and modify logback
classes... I assume it wouldn't be too difficult to make your own logback
class that would indeed accept a configuration flag in logback-test.xml
to "supress stack traces". And of course this bespoke logback
class wouldn't have to be exported when you make an executable jar of your app ... but again, to me this comes in the category of "jumping through hoops". How "pure" does app code really need to be?