Page 1 of 1

TDD: were to start

Posted: Mon Dec 18, 2006 2:31 pm
by matthijs
After having started a bit with writing my first tests for a model class in an MVC app I started to think a bit further and have some questions about the next step.

We know that in a TDD approach you start with the simplest thing. You write a test testFetchUserId() or something and then write the minimal code needed to do that. Ok, that's clear. In this case, i started working on one of the "deeper" classes of the system in the data layer.

But we all know that a medium sized project is more then just a few classes which pass a test. At the front end we need pages which show some kind of combination of data, coming from different db tables and thus using different model classes. Somewhere between that single front page view and all those backend (data) classes a lot is happening. User authentication, validation, session handling, data mapping, etc etc

So how do I get to that?

To give an example. You have a CRUD like app with categories and articles (which can be in different categories) and users (who write articles in different categories), etc. With my approach you would start to test/write a few model classes for categories, articles and users. Fine. You have some model classes for adding, deleting and editing cats, articles, and users. That will probably look like a couple of active record classes.

Ok. Then what? Should you then just start testing the front-end views? Like, test a class with methods like showAllArticlesBy AuthorId(), showCategories(), showArticlesInLastMonth() etc? If I would do that it would be difficult to use the model classes as I designed earlier, because I need to combine the data from several tables somehow.

Or should I have started with the front end anyway?

Well, I hope my issue is clear and some people could enlighten me on this.

Posted: Mon Dec 18, 2006 3:58 pm
by Ambush Commander
To a certain extent, TDD can test overarching segments of functionality, using mocks if necessary to reduce the amount of lower level components each unit test depends on (and testing more specifically that component and how it integrates several classes together).

TDD doesn't catch everything though, so you'll want to set up a bunch of smoketests, where a live human steps through various procedures in the application and makes sure everything is working properly. Tools like Selenium can automate this process.

Posted: Mon Dec 18, 2006 6:09 pm
by phait
hi,
In addition to what the commander mentioned above, if you use Simpletest, you can also produce the user acceptance tests / smoke tests / (insert other name here). So you can have your unit tests and then test them in situ on a test server prior to making them live, or perhaps just on your local dev box.

http://www.lastcraft.com/web_tester_documentation.php

I think ST V.2 might also have some changes with this aswell, Marcus has certainly suggested that on posts elsewhere. I think there is also a plugin available that generates Selenium scripts for integration with ST 1.

Google is your friend.

Cheers,
phait

Posted: Tue Dec 19, 2006 12:49 am
by matthijs
Thanks for the replies and suggestions.

I'll look into the user acceptance tests. I did read the web tester docs. (still getting many errors using it, but that's another question). I'll also look at Selenium as Ambush suggested.

I would like to go a bit further into the general approach of using TDD though. The thing what bothers me, at the moment, is that there's such a wide gap between the idea of TDD as I understand it now and the reality of how mid- or larger sized applications might look like. What I mean is as follows. In the TDD/agile way you start writing one test on one class. On success, do the second. Etc. Once the classes get bigger you will see that you start repeating certain parts of code, or you spot certain areas with code smells. So you refactor the code. However, at this point you will still have a fairly "flat" layer of classes. At most a few helper classes which you got with refactoring. For example, a db class.

However, if you look at an average MVC -diagram, there are many layers. In Sweatje's book you have Controller, ActionFactory, ShowViewAcction, ViewFactory, View, Model, TemplateEngine. I do understand the purpose of all those layers. What I find hard to see is how you get from that first "flat" layer of classes after writing those first tests to such a deeper layered application.

Do you get there only with refactoring? Do you do that each time you write a new application, rewriting the code again and again until you end up with all those layers?

Or do you start with a general idea of how the design might look like (in this case MVC) and write your tests/classes accordingly?

Posted: Tue Dec 19, 2006 3:00 am
by Maugrim_The_Reaper
However, if you look at an average MVC -diagram, there are many layers. In Sweatje's book you have Controller, ActionFactory, ShowViewAcction, ViewFactory, View, Model, TemplateEngine. I do understand the purpose of all those layers. What I find hard to see is how you get from that first "flat" layer of classes after writing those first tests to such a deeper layered application.

Do you get there only with refactoring? Do you do that each time you write a new application, rewriting the code again and again until you end up with all those layers?
There are only three layers - Model, View, Controller. You can add Database as a fourth, but often it's not a Unit Testing concern. Within those three layers are various competing Patterns you can implement, mix and match. For example, you could have single Controller classes OR multiple Action classes OR ...

TDD and Unit Testing will push you towards what you call "flat" class families. This is considered a major benefit for many people (assuming I'm interpreting you right). Something that's flat has little depth, it's easier to pull out and reuse elsewhere without having to cart half the whole library with you because there a dozen dependencies are all deeply buried and hard to extract. I think most of your issues lies within the Controller layer. If you have unit tested Models, and a set of unit tested component classes (authentication for example) then you are well on your way.

It all starts boiling towards the Controller - since the Controller manages workflow a great deal and determines a lot of how you use the classes you have assembled. As in all things like this, an example would be easier to dissect and discuss...

Posted: Tue Dec 19, 2006 4:16 am
by matthijs
Thanks for your explanation Maugrim.
TDD and Unit Testing will push you towards what you call "flat" class families. This is considered a major benefit for many people (assuming I'm interpreting you right). Something that's flat has little depth, it's easier to pull out and reuse elsewhere without having to cart half the whole library with you because there a dozen dependencies are all deeply buried and hard to extract.
This makes sense. And gives me some hope :)
It all starts boiling towards the Controller - since the Controller manages workflow a great deal and determines a lot of how you use the classes you have assembled. As in all things like this, an example would be easier to dissect and discuss...
You're right. Once I rethought this a bit and when I have my first classes figured out I'll post a concrete example.