Some people ask me how Test Driven Development fits in MVC Frameworks like Django, Ruby on Rails, and all this kind of frameworks that use convention over configuration, and offer powerful tools for CRUD (Create-Read-Update-Delete) operations.
Well, the solution always depends on the kind of problem you face. If all your application needs to do is CRUD, then, the framework is perfect. You don’t need TDD at all. You just write some entities (known as models) and let the framework create all kinds of scaffolding to let the user create and retrieve data. Everything is created for you automatically.
You even don’t need system tests because the framework has already been tested.

However, none of my applications are so simple. They go beyond CRUD. They got business logic which I need to test drive.

The big mistake in my opinion is to clutter the controller with the business logic. In the development of MavenCharts.com, we never have business logic within a controller. The mission of the controller, is to get the input from the user, call the application core, get the response, render a view and send it back to the user. The controller should not even manage entities (models if you want). It just gets inputs and send outputs.

Web MVC and TDD

Web MVC and TDD

If you test drive your code, you manage the dependencies using injection. Creating a business class might not be easy. For that reason we use factories. The factory might use an IoC container in order to get instances. In the case of languages like Python or Ruby, I believe that IoC container is not necessary, so we just use static factory methods (functions defined in the global namespace of a module).

The code of an action in the controller should be something as simple as this:

@render_error_if_method_is_not("POST")
@login_required()
def save_new_profession(request):
    logging.info(str(request))
    profs = request.POST.getlist(dom_constants.PROFESSION)
    info = __get_basic_info(request)
    user = info['user']
    factory.get_user_updater().add_professions(
                                    user, profs)
    return HttpResponseRedirect(reverse(my_professions))

The “add_professions” method is implemented regardless the MVC framework. It can run in the console. We test drive it with the xUnit framework as easy as always.
The common mistake people make is to implement that method in the controller itself, making it hard to reuse, develop and test.

The controller might still contain defects. For that reason we write one test for every action (controller method), using WebDriver. But we don’t test all the cases through the controller, just one case. Other cases were designed with TDD even before writing the controller.

MVC frameworks are great but they are dangerous when we want them to solve all our problems. Their mission is to help with plumbing, help avoid writing same tools once again.

For those starting with Django, it is worth noting that names are confusing. They call Views what should be named Controllers, and they call Templates, what really are Views. Eventually, they call Models, what should be entities, but that is something everybody does.