

How to write untestable code - bigsassy
http://googletesting.blogspot.com/2008/07/how-to-write-3v1l-untestable-code.html

======
psnj
Could someone explain: "Be Defensive - They're out to Get Your Code! -
Defensively assert about the state of parameters passed in methods,
constructors, and mid-method."?

which, desarcastified, I take to mean:

"Don't defensively assert about the state of parameters passed in methods,
constructors, and mid-method."

Specifically:

"You see, there are testing freaks out there that like to instantiate your
object, or call a method under test and pass in nulls"

Isn't it the case that a calling a method with (say) null parameters where
they are supposed to be non-null should raise an exception? Isn't an assertion
failure reasonable in this case?

I understood and agreed with a lot of the other stuff (although it struck me
as a bit dogmatic) but this one I don't get.

~~~
japherwocky
I think what the author is getting at is testing a particular method on an
object without having to mock up all the data required by the entire object. I
guess?

Agreed that the whole article would be more useful without the sarcasm.

~~~
viraptor
So that's basically allowing operations on a half-broken object, just so that
you can test it without creating all the dependencies?... I see how it might
be useful, but I just can't agree with that.

The tests are not the goal - a working product is. That's just making a trade-
off between less lines in a test -vs- code that doesn't explode mid-
transaction when that null suddenly occurs in a real-world scenario. If I'm
supposed to write my code properly, testies should not be _too_ lazy while
writing the tests.

~~~
omouse
It's no longer a unit-test once you're putting the object into the living
system. It becomes a system test and then you might as well test the whole
system instead of faking things with mockups.

------
viraptor
Could someone explain this one?

> Be Defensive [...] Defensively assert about the state of parameters passed
> in methods, constructors, and mid-method. If someone can pass in a null,
> you've left your guard down. You see, there are testing freaks out there
> that like to instantiate your object, or call a method under test and pass
> in nulls!

I'm not sure what he wants to change. Surely if the code would crash when I
pass a null as an argument, it's better to make it throw the exception as
early as possible. You can test that by asserting an exception when you call
that_func(null);.

Why is that a bad thing? (Or did I misunderstand him?)

~~~
req2
In the comments he admits that public APIs should be defensive, but internal
APIs should be 'known good' via testing.

------
jriddycuz
I'm pretty sure this was copied word for word from the employee guide of the
firm that originally wrote the software I now trudge through every day. Except
it wasn't sarcastic. And I think there was some other rule in there about
avoiding spacing in the source code at all costs.

------
DannoHung
Some pretty darn good advice in here. This might be slightly embarrassing, but
it actually makes me appreciate the value of Factories; something I always
thought was a little overkill for anything but GUI code.

~~~
viraptor
They are overkill. They're java man's substitute for lambdas. But if all you
have is java, everything looks like an object.

~~~
_sh
I don't understand this. Are you using closures as types? If so, what can they
offer that factories can't? Trying to understand, genuinely curious.

~~~
viraptor
They offer the same functionality (more or less)... Factory objects just feel
like overkill - usually they carry no state of their own, so why are they
objects? If you could pass around functions, you could just use them instead.

    
    
        x_factory_proto :: GlobalParams -> InitParams -> X
        ...
        x_factory = x_factory_proto some_params

------
yread
What's wrong with

 _Create Utility Classes and Functions/Methods - For instance, you have a
String which is a URL you're passing around (obeying "Use Primitives Wherever
Possible"). Create another class with static methods such as isValidUrl(String
url)_

if the function is a deterministic function (I guess it could be implemented
as a simple test against regex) why is is difficult to test? I get that its
better to use the system one or your own URL class, but thats really about OO
and not testing!

~~~
roam
The keyword is "static". You'll often want to use a mock implementation rather
than connecting to a remote server, checking for a 404 error and returning
true or false - every time you run your tests.

Loosely coupled objects will allow you to do that, but how would you redefine
the behavior of something static?

------
ardit33
Jesus, basically don't worry about the product, just worry about having
testable code.

I thought "having testable" code, is never the end, maybe the means perhaps,
but not necessary,

If you have done mobile development, you know you have to break most of these
rules at some point. Sorry, I'd rather have a shipping/peformant product, than
one that is a hog, but makes OO purists happy, and is easy to test.

At the end of the day, keeping your customer happy, that is the end game.

------
txxxxd
It's too bad Java/C++ were designed after unit testing became commonplace.
Some of the advice here will actually improve your production code but a lot
of this is just a case of the programmer having to work around the language.

For example, the advice to not "instantiate objects using new in the middle of
methods" wouldn't be a big deal if if your test code could easily instruct the
compiler to replace the concrete object with a mock when the test is run.

~~~
ori_b
Nothing prevents that being implemented in existing compilers. In fact, you
can already do that in Java with class paths.

------
arohner
Should be "How to write untestable code in Java".

Makes me glad I'm not writing Java, fewer than half of these are problems for
me.

------
JoeAltmaier
A little too vague - don't use if? switch? Surely they are useful. Better to
advise against putting application logic into the wrong object - which is what
I THINK they are arguing against.

------
rincewind
_Greenlight if-branches and switch statements

OO cowboys will want to have a whole polymorphic soup of collaborating
objects_

Of Course! When I implement, say, Bubble Sort, I do not implement the classes
BubbleList with the methods sort and addObject: anObject and BubbleObject with
the method bubbleMaybe: aBubbleList, just to see my tests for BubbleObject
fail when I switch to Quicksort.

------
adamc
Mostly assumes object-oriented programming, of course.

~~~
Deestan
With a smug smile on my face, I notice that most of this list is impossible to
do in Haskell.

------
flyingbertman
How about a million lines of code in VB6?

