XpdWiki

FrontPage
RecentChanges
XtC
FindPage
PageIndex
XpApprentices

Set your name in
UserPreferences

Edit this page

Referenced by
PairProgramming
LisaVanGelder
DoingIt




JSPWiki v2.0.52


DoingTests


Worried about IntroducingTestUpFront to an existing team or code base?

The testing experience is that you write your test upfront, and then run it. It should immediately fail because you haven't written the code to implement the test yet.

It is hard to make sure you have the discipline to write tests upfront (which is why DoingPairProgramming is important); however the benefit is huge.

There are examples of DoingTests where we have been working on RealCode.

In one of our examples, you can see that a simple text compare is done to check the output from a Servlet. We think this is the simplest thing until you start using more HTML in your output. You know you've reached this point when you have to change these tests often. The tests have become dependent on your presentation, at this point you can move on to the next level. -- OliBye

You might find it useful to consider the NatureofTesting.


Okay, I'm not sure if this exactly the right place to ask about this, but I'm sure there must be a few people around here who have a greater understanding of this than me, and maybe you can show me where I should be putting this question if it's in the wrong bit of the wiki...

I'm trying to train myself to work test first. Sometimes it fits fine and is great, but when I work with a database (as I often do) I really struggle to see how it isn't just a nonsense: basically my tests are just a mirror of the real code, so how am I really testing anything useful at all?

e.g. I have a method to add a widget record into my database table. I write my test:

// assuming tables are cleared down... \\
DataLayer.AddWidget(WidgetSize); \\
Assert.IsEqual(GetCountOfWidgets(), 1); \\

Now I need to write a function (GetCountOfWidgets?) as part of my test harness to count the number of widgets in the table: this needs to open the database, make a call to the table, and count the number of rows.

But maybe I already have a method like that on my DataLayer?... so maybe I should just call that?... but then I would be assuming that it works which seems wrong... but otherwise I am going to pretty much copy and paste the code from DataLayer?.GetCountOfWidgets? into my test harness - and that can't be right can it??!

I do hope this strikes a chord with someone - it's driving me bananas!

(...and very sorry if it's in the wrong place, or a dumb FAQ!) -- MattWynne?


Great question, one that IMHO goes right to the heart of test first. TimMackinnon and I also ran into this same problem when first learning to do test first. We too discovered that we seemed to be writing implementation code in our tests.

Trust your instincts. You've correctly identified that GetCountOfWidgets? it only needed for the test, yet it has real functional code in it. This instinct is essential for good test first design.

The fact that the test goes back to the database makes it more obvious, but in general if you have to write function just for your tests then that's a CodeSmell?. Usually it means you'e trying either:

  1. Test too much
  2. Test a unit that does too much

In this case I think you're trying to test too much.

Ask yourself "what are we testing". Do you need to test that:

 insert into Widgets (WidgetSize) values (42)

inserts 42 into a new row in table Widgets. Ofcourse you don't need to test that. You'd be a fool to use a database that didn't implement SQL properly and this is the key. SQL is an interface. Go ahead, write 4 functional tests for select, insert, update and delete on one table if you really don't trust your database, but how many tables and column names do you need to test before you are sure your database is a database. Trust the implementation of the interface (unit tests test one thing and the database isn't it, in this case).

Rephrase the question "what could break".

  • Wrong table name
  • Wrong column name
  • Wrong type for parameter e.g. calling insert into Widgets (WidgetSize?) values ("42")

You simply want to test that when you call DataLayer?.AddWidget(42) that the string insert into Widgets (WidgetSize?) values (42) is squirted down the connection.

In Java you're expecting that Statement.executeQuery("insert into Widgets (WidgetSize?) values (42)") gets called. However you can only get a Statement from the Connection. Formally you also want to check the the result set is correctly emptied of potential results.

The mock JDBC interfaces from the MockObjects library can help you here. There is an example that Tim wrote for a workshop in there that does this very thing. If not call back here and I'll carry on the story.

-- OliBye


Edit this page   More info...   Attach file...
This page last changed on 18-Nov-2004 22:57:00 GMT by OliBye.