By Peter Bell

If it isn't worth testing, it isn't worth coding . . .

One of the common arguments against Test Driven Development is that a lot of the code we write (simple getters and setters, dumb parameterized calls against a proven API, etc.) has behavior that is too simple to bother testing.

I won't necessarily disagree that there is some code that is too simple to be worthy of writing tests for. However, I will argue that you should almost never be writing such code . . .

If your code is simple enough that it isn't worth testing, why are you writing it in a 3gl where you could have syntax errors, you can't introspect it's meaning easily and you can't apply programmatic transformations to evolve your code? If it's that darn simple, turn your code into data. Use a database, a csv, XML or a custom external DSL with a parser, but stop writing code. If it's too simple to require a test, it's too simple to require code in a 3gl (*almost* all the time).

Thoughts?!

Comments
I think that could be true in many situations, but I can think of situations where its not.

One obvious one is that I'll write a test first, say test_isValid?().

isValid?() just returns true at first.

Then I might make _isValid? a property and have it return that.

But in the end, isValid?() actually calculates a value.

I had a test first, and didn't know whether or not the method would be so easy as to require a test when I wrote it.

Another example: suppose I'm using a framework that by default outputs a list where every column in the DB is a column in the table. It lets me change that behavior with some statement, say:

combineColumns(col1="address", col2="city", separator="<br/>", newname="Address")
combineColumns(col1="Address", col2="state", separator=", ")

And so on...

That code is probably too simple to write a test for, so should I never have written it? The backend framework we can assume is tested, but my code isn't.

These sort of situations are abundant in my daily programming life.

Great string of posts lately, BTW. Would like to have commented on almost all of them, but I've been incredibly busy!
# Posted By Sammy Larbi | 7/11/08 9:46 AM
Yes, there is a concept called a 'prototype'. Obviously testing a prototype is border lunatic. :)

Therefore, here is something worth coding, that is fundamentally crazy to 'test'. Prototypes are often coded, but the bigger issue is testing the components that make up the prototype tools.
# Posted By John Farrar | 7/11/08 9:54 AM
let's see it in action, brutha! examples, etc. this concept is one i'm getting into... and more examples will help me get there.
# Posted By marc esher | 7/11/08 9:59 AM
Ok, so maybe I'm just a n00b technologist, but what is a 3GL? That has to do with the abstraction of language constructs, right? Third generation? But, what does that mean? Is ColdFusion a 3GL?

Let's say I wanted to create a site called Raffle-A-Winner.com that takes the number of people in a room (ex. CFUG room) and returns a random number between 1 and the number of people in the room.

Really simple, right? Simply some HTML and RandRange()... are you saying that this should be defined in XML, rather than ColdFusion? I think I would understand better if you explained 3GL a bit more?
# Posted By Ben Nadel | 7/11/08 10:24 AM
@Sam, that's why you generate a basic isValid() method, describe most validations declaratively and then only code a custom isValid() if you need one! It's not like iisValid() is an unusual requirement - so why not generate it to start with and only code if it needs to do something outside of the bounds of your validation DSL (you DO have a validation DSL - right?!).

@John, But why would you EVER code a prototype by hand? That's what code generation is for. Now to be fair, I don't include HTML/CSS in coding as you tend not to write unit tests for that at all. I don't think a prototype is worth coding at all. Prototyping is one of the quickest and easiest wins for generators. Of course, you may need to write your own as a "one size fits all" prototyping tool is pretty unlikely to solve your problems in the way you want.

@Marc, Well, we'd talked about doing something offline, so we can set that up. In fact I'm doing a really nice set of upgrades now so in a week or two there will be even more to play with!
# Posted By Peter Bell | 7/11/08 10:27 AM
@Ben,

Sorry - 3gl is a third generation language - distinguishing from the 4gl or fourth generation case tools (which died an inglorious death a few years back). Examples of 3gl's (although the term is pretty vague) would be ColdFusion, Java, PHP, Ruby, Python, C#, VisualBasic.NET and Perl.

I personally find that the applications that I build are more complex than a raffle-a-winner.cfm as described. If I could hack a site in an hour, I'd just put it in a single cfm and be done. Most of the apps I build are more complex and need object models, controllers, layout templates and the like. I describe all of that declaratively and then just code the stuff that I can't generate. If I needed a method to return a random value, that would probably be one of the few cases where I might not write a test (unless it was random within a range, it was more than just a simple function call and I wanted to write some tests to make sure it didn't seem to go outside the range) and would probably choose to hand code as I don't need it very often. But that said, I usually find if I'm writing code that it too simple to test it's a code smell that I should really be writing a framework, generator or other tooling to raise the level of abstraction to get rid of the boilerplate. Kind of like comments being a code smell. It isn't a rule, but it isn't a bad rule of thumb!
# Posted By Peter Bell | 7/11/08 10:35 AM
@Sam, As for the framework call example, that is exactly the problem with internal DSLs/framework calls. It's why I think the Ruby world is heading into a wall with all of their internal DSL groovyness. The problem is you end up with simple code that could still have syntax errors and could do with being tested but is too simple to test. Move that out into an external DSL. Use an XML or little language to configure a given screen or transformation or whatever and then you can use constraints and custom semantic validations to look over your external code and confirm that it is valid. It's why I prefer external declarative DSLs to internal ones most of the time. Especially now that tooling like oAW is making writing parsers and custom editors for your DSLs including syntax highlighting and an OCL like constraint language extremely easy (in a tutorial we wrote a DSL and created an editor for it in under five minutes using oAW for the tooling and E-BNF to describe the meta-grammar).

Glad you're enjoying the postings!
# Posted By Peter Bell | 7/11/08 10:39 AM
@Peter, because prototypes should roll into the the next phase without reworking them. Part of "DRY" development and a working flow where the designer and the developer are able to continue to work and change things is having stuff in a domain that makes them safe. (After all, safe is the reason we are doing testing to start with.)

With that said, if someone wrote a WSYWIG tool like 'Thermo' for Flex then it would not require hand coding. (As much, even DW and the other tools still provide for hand coding. And it is not uncommon to find designers spending blocks of time in code with no complaints. HTML, CSS, etc code that is.)

In the end it is about removing redundant workflow, reducing errors and keeping the pieces round trip to be edited without breaking the other pieces. The way we prototype things historically won't support this. COOP does support this. Perhaps I am getting spoiled. LOL
# Posted By John Farrar | 7/11/08 12:14 PM
@John, We just describe our apps declaratively and it generates a "prototype" which is really the actual application with relatively low fidelity. The client comes back with changes some of which we can describe in our DSLs, some of which require a smattering of custom coding. Once we're done with revisions the prototype/site is ready to launch. No rework or redundancy!
# Posted By Peter Bell | 7/11/08 12:28 PM
@Peter, that is another way of doing it. The value of it remains to be comparable at this time for me since it's not an open market technology. I can see plus and minus concepts comparing your method and ours. Perhaps my general opinion at this time is they are both best for different types of projects and teams.
# Posted By John Farrar | 7/11/08 1:01 PM
It's interesting that you mention getters and setters... because I tend to agree... in the CF community recently it's become really popular (I presume as an arbitrary dredge-over from java - as opposed to a hold-over) to build anemic domain models with beans that are written via code generators... blech... bad idea... You're taking a system with lots of busy-work or leg-work for yourself, and you're solving the busy-work problem by creating an automated system for creating more busy-work! Because the amount of busy-work you could create on your own apparently wasn't enough.

My own code never includes the standard getters and setters, it always uses getValue() and setValue() which has a HORDE of advantages over the more traditional solution, which I mentioned at great length in an article on my own blog titled "Ducks Are Loosely Coupled". I've recently added onMissingMethod() for folks who insist on doing things the hard way and made that just execute the getValue and setValue methods if applicable. But in my case, I wouldn't be testing just a typical "getter or setter", I would be testing a dynamic get/set architecture (albeit fairly small) that includes other related features as well.
# Posted By ike | 7/11/08 10:36 PM
Somebody slotted ColdFusion into the 4GL page on Wikipedia under "web".

http://en.wikipedia.org/wiki/Fourth-generation_pro...
# Posted By ike | 7/11/08 10:52 PM
@Ike, Sounds like you've got a similar solution to the one I use (and a number of other people seem to do this as well). As you said, a set of unit tests for the generic setter/getter infrastructure is necessary, but not for specific getters/setters as they don't exist.
# Posted By Peter Bell | 7/13/08 4:45 PM
Actually after having looked briefly at lightwire (for the first time no less) it seems to bear some similarity to the way DataFaucet handles ORM... I'm making a cross-comparison analogy here... Lightwire is to ColdSpring as DataFaucet is to Transfer. :) I actually just added a lightwireadapter.cfc to the onTap framework core components over the weekend as a part of the IoC Manager in the upcoming release.
# Posted By ike | 7/14/08 10:14 PM
I hadn't thought about it in quite this way before, but I agree completely. Although perhaps not perfect, I think that is a great "code smell"!
# Posted By Steve Bryant | 7/16/08 10:38 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.005.