In a traditional ASP.NET Application, a page (WebForm) contains controls (WebControls and UserControls) that display application domain data. A user can modify the data and submit the changes, via Postbacks. The page retrieves the domain data, handles user events, alters other controls on the page in response to the events, and submits the changed domain data to the Business Layer.

Including the code that performs these functions in the Web page makes the class complex, difficult to maintain, and hard to test. In addition, it is difficult to share code between Web pages that require the same behavior.

Recently there has been much more emphasis on the use of automated Unit tests in the development cycle.  The benefit of automating Unit Tests, which can then be run whenever a change is made to the code is that it has the potential to free the QA resources to focus on the Usability of an application and on the exceptions (edge cases), as the application has been well tested before it gets to the QA team. 

Of course, this all depends on how well the tests have been written and how much of the Application the tests cover (code coverage).

Unit Tests

A unit is the smallest testable part of an application. Typically, the smallest unit is a method, which may belong to a base/super class, abstract class or derived/child class.

Ideally, each unit test is independent from the others, and double objects like stubs, mock or fake objects as well as test harnesses can be used to assist testing a module in isolation.

The goal of unit testing is to isolate each section of the program and show that the individual sections are correct. A unit test provides a strict, written contract that the piece of code must satisfy. As a result, it affords several benefits, as unit tests find problems early in the development cycle.

Test Driven Development

Test-Driven Development is a style of software development that takes this use of testing to the extreme.  In Test-Driven Development (TDD) the Unit Test is written first, and then the minimum amount of code is written to get the test to pass.  Most testing frameworks use the red light/green light approach – red light, the test fails – green light, the test passes.  The complete cycle of Test Driven Development is as follows (from Test-Driven Development, By Example – Kent Beck)

  1. Write a test
  2. Run all tests – and see the new test fail
  3. Make a little change – to make the test pass
  4. Run all tests and see them all succeed
  5. Refactor to remove duplication
  6. Repeat

The important steps are (3) and (5).  The initial coding to make the test pass should be as small as possible. 

For instance if you are creating a math function to multiply two numbers together and your test invloves calling the function with the two numbers 2 and 5, and checking that the answer is 10, a TDD purist would say that the initial implementation of the function should just return the literal constant integer 10, as this is the simplest code that satisfies the test. 

It is in step (5) when the duplication is removed that causes the code to be refactored to return param1 * param2.

Loosely Coupled Systems

In order to test one component, independently from another, the components should be loosely coupled.  This is not always the case with software.  Often a business layer class will have a dependency on the database.  In this scenario, a method in the business layer cannot be executed without affecting the database.  The data layer can probably be independently unit tested, but the business layer is said to be tightly couple to the data layer, as it cannot exist in isolation.

Testable DotNetNuke Modules

The conventional methodology for building DotNetNuke modules does not lend itself to support Unit Testing (or by extension Test-Driven Development) for a number of reasons.

  1. While the Data Layer is quite loosely coupled from the Business Layer (through the DataProvider model) the providers are configured through the web.config file, and there is no way (prior to version 5.0) to independently create a MockDataProvider to enable us to test the Controller classes in isolation from the database.
  2. Web Forms (and User Controls) do not provide a way to independently Unit Test the Presentation Layer – there are browser-automation frameworks like Watin and WebAii, which can automate user interaction with the Page – but these are not Unit Tests.

In this series of blog posts I will discus ways we can modify our normal module development process to create Testable Modules.  While I will discus Test-Driven Development, the real goal in this series of blogs is to build testable modules, regardless of the development process you decide to use.


Posted in: DotNetNuke  Tags: , ,

Comments


Netherlands Paco
August 14. 2008 12:57
Paco
I have been working on a lot of DNN modules. I like TDD and use it a lot outside of DNN. A lot of objects in DotNetNuke are very hard to test. Par example simple objects as TabInfo, PortalInfo, filesystem methods are impossible to mock. How do you solve these problems?

I'm also curious on how you apply "loose coupling" in DNN module development. It's impossible to bootstrap an IoC on application start-up. I use a singleton object that boots itself for my IoC in DNN at the moment, but singletons are not loose coupling.

It's also impossible to create a module with a non default constructor to inject dependencies.
no site


August 14. 2008 14:29
Charles Nurse
@Paco - Good questions - as I am working my way through this I will have to indulge your patience.  

Partly because I haven't solved the problems completely, but also because I want to develop the concepts before we dive into actually dealing with DNN specific items.

But there is a concept that we do need to remember when developing DNN modules - "We don't need to test the Framework"


Netherlands Paco
August 14. 2008 15:09
Paco
OK, I'll wait a few posts in this series before going into detail.

A little correction on my comment above: I wrote: "A lot of objects in DotNetNuke are very hard to test" and you correctly reacted with "A lot of objects in DotNetNuke are very hard to test", but I actually meant to say that's its hard to isolate dependencies from dnn in your tests. You don't want to make your unit tests integration tests.

I tried out a lot with test-driven dnn modules. I also have some ideas to improve the dnn core with looser coupling and isolation. Feel free to ask when your stuck.
no site


August 16. 2008 06:03
Don Worthley
Hey Paco,

I'm interested to know more about your research into TDD with DotNetNuke.  Are you using an MVP pattern for the development of your DNN modules?  While the layer between DNN and module creation is fairly tightly coupled, it seems that the MVP pattern can help create a layer between your module and the real logic you've added to your module.  Although it would be nice to have green lights on the world as we step out the door each morning, using interfaces to separate your View from your Presenter should allow you to stay disconnected enough to write tests for your own stuff.  With your View and Presenter separated by the use of an interface, you have control of the Model, so you can choose your own TDD friendly framework to handle the  BLL (Or facade or service layer, if you have one) down to the database.  I used SubSonic, which isn't the best from a TDD perspective, but I like the simplicity of the design and the SubSonic team is working to make the framework more TDD friendly.

I've used this pattern over the past year when developing modules for clients and it works well, although I'm doing it more for good design as I haven't written a single unit test for these modules and didn't use an IoC container.

I'm interested to hear more of your thoughts on this.  Do you have a blog?


August 17. 2008 12:33
Charles Nurse
I agree with Don.

The TDD Module Development template that Phil Beadle has developed is based on the MVP pattern.  There are some improvements in DNN 5.0 which make it easier to apply the MVP pattern.  

In the next blog in this series, I will be discussing the design patterns so - stay tuned.


September 5. 2008 22:27
trackback
Trackback from Thoughts from the Wet Coast

Creating Testable Modules - Part 6, View Links

Comments are closed

 Search Blog

 Calendar

«  February 2012  »
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
2728291234
567891011
View posts in large calendar

 Tags

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012 Thoughts from the Wet Coast