Saturday, May 23, 2009

Revving up the TDD engine

tach

I’m still in the early stages of writing unit tests at work… but I did commit 26 passing tests to source control this afternoon!  The pain is fading, I’m gaining confidence and speed and I’m getting excited about the number of tests I’ve written.  We’re no mature TDD shop yet, but it is an enjoyable stage when the shiny new unit tests still make us go “ah”.

In this post I’ll finish out the TDD section of my NCharlie project series by walking through some code that tests the interaction between a controller and view.  It includes using Rhino Mocks to raise an event and verify that the controller calls the correct method on the view in response.  I know in my last post I practically gave up on Rhino Mocks in favor of writing my own mock classes and methods… well, I changed my mind.  RM is a great tool, and I’m getting used to the syntax required for .Net 2.0 projects.  So here goes…

search-results

I want to test the behavior when a user clicks one of the “[show]” links in the Task Search results list.  The application should show the Task Detail view when this happens:

task-detail

So I’ll name my test accordingly:

[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
}


Before I start into the body of this test method, there is some setup code that I need to get in place:



[TestFixture]
public class TaskManagerControllerTests
{
MockRepository mocks;
ITaskManagerView viewMock;
ITaskRepository repository;

[SetUp]
public void SetUp()
{
mocks = new MockRepository();
viewMock = mocks.DynamicMock<ITaskManagerView>();
repository = mocks.CreateMock<ITaskRepository>();
}



The mock view will allow me to test my controller code without needing to have a view implementation (ASPX page) wired up and working first.  First I arrange the needed elements for the test by creating the event arguments object that will be passed with the event and an event raiser named “clickEvent”:



[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
string taskID = "12345678-1234-1234-1234-123456789012";
TaskSelectedEventArgs e = new TaskSelectedEventArgs(taskID);

IEventRaiser clickEvent = Expect
.Call(delegate { viewMock.TaskSelected += null; })
.IgnoreArguments()
.GetEventRaiser();



Next I use the Rhino mocks “Expect.Call” method to state that I expect the view’s “ShowTask” method to be called with with my test task ID as the parameter.  The expectations are finished with a call to the R.M. “ReplayAll” method:



[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
string taskID = "12345678-1234-1234-1234-123456789012";
TaskSelectedEventArgs e = new TaskSelectedEventArgs(taskID);

IEventRaiser clickEvent = Expect
.Call(delegate { viewMock.TaskSelected += null; })
.IgnoreArguments()
.GetEventRaiser();

Expect.Call(delegate { viewMock.ShowTask(e.TaskID); })
.Repeat.Once();
mocks.ReplayAll();
}



Finally, I execute the code that will test this behavior… I instantiate a new TaskManagerController (this happens when the view is created) and raise the click event.  The R.M. “VerifyAll” method verifies that all my expectations are met when the code executed:



[Test]
public void Should_call_show_task_when_task_selected_event_is_raised()
{
string taskID = "12345678-1234-1234-1234-123456789012";
TaskSelectedEventArgs e = new TaskSelectedEventArgs(taskID);

IEventRaiser clickEvent = Expect
.Call(delegate { viewMock.TaskSelected += null; })
.IgnoreArguments()
.GetEventRaiser();

Expect.Call(delegate { viewMock.ShowTask(e.TaskID); })
.Repeat.Once();
mocks.ReplayAll();

new TaskManagerController(viewMock, repository);
clickEvent.Raise(null, e);
mocks.VerifyAll();
}


That’s it.  The code to make it pass is painfully simple (painful because the code to test it is so much longer… I’m getting less and less offended by this state of affairs though, since the tests look like this for complicated code under test as well.  Besides, these tests copy and paste very easily!)  Here is the code from the controller under test:



private void OnTaskSelected(object sender, TaskSelectedEventArgs e)
{
view.ShowTask(e.TaskID);
}


And that makes it pass:



tests-passed



 



 

Thursday, May 14, 2009

Do we have time to write tests on our projects?

This is a question I would like to answer in the context of my day job.  It came up again today as I was talking with the other developers about some of the “new methods” I would like to integrate into our development process.  The title of this post is how the question sounds now in my head.  This afternoon it went more like this: “We don’t have time to write tests on our projects!”

Granted the developer who made this statement is a big believer in the “speak first, reason it out later” method of communicating… this is his knee-jerk reaction to someone telling him we would write more code for the same functionality.  I can sympathize with him… we have deadlines on our projects to meet.  But I don’t agree with him.  I’ve already written some tests at work to solve a problem in the business logic of software we released 2 months ago.  The exercise helped me find other problems in that code and refactor it to a state that will be much easier to maintain.  Do we have time to maintain legacy code that is hard to understand and has no tests written against it?  I don’t.

But… even though I am convinced we need to write tests, I want to be practical.  Will my team benefit from this?  Are there certain types of developers or certain types of projects that will never see the benefit of writing tests against code?  Maybe so – but I hope that isn’t a description of the team I work with.  And I think the best way to find out is to do the best I can to set us up for success.  That is a big reason I am writing about my experience building up the NCharlie project.  I have some work to do before we are there though.  As I mentioned before, TDD still feels like a pain point for me because of the way my tests look using Rhino Mocks to mock objects like the database access code.  When I mentioned this pain point to my boot-camp instructor his advice was to “abandon ship”… not on TDD, but on the Rhino Mocks Expect-Replay-Verify model and use the easier to understand Arrange-Act-Assert model of testing (I know AAA is possible with Rhino Mocks… but not with nice syntax in .Net 2.0).

So, I am going to follow my instructor’s advice and abandon ship.  I’m going to start writing tests without a mocking framework.  I can create a class quickly that mocks a database access class without using Rhino Mocks.  Sure it will be a bit more code to write, but I think the clarity it will bring to the tests will be worth it.  I also think it will be a good exercise even if I do end up coming back to a mocking framework like Rhino Mocks… I will appreciate it more after manually building mock objects.

This means I am going to stay on the topic of writing tests for at least one more post.  Earlier in this series I wrote some tests to verify that the controller class for the Task Search page in the NCharlie project was correctly responding to events raised in the view.  I didn’t show the code for the test in the post (it was available in the code repository) because I did not want to distract from the intent of that post.  Now it is time to show that code… almost (actually, in the next post).  First, let me answer the question I posed in the title of this post:

Yes, we do have time.  It will make us go faster because our code will end up being easier to work in now, and easier to extend or fix later.

Tuesday, May 5, 2009

TDD Pain Points, A Retrospective

This is the fourth weekend into writing about test driven development… taking agile methods I learned in boot-camp back to work.  Time for a retrospective…

First I will say that writing about this process has been a tremendous help in making these concepts gel.  Try teaching someone about something you are trying to learn.  I don’t care if no one ever reads these posts – the process of writing them has been invaluable to me.

Now, for the pain points:

Supervising controller:

I chose this pattern (a flavor of Model-View-Presenter) for two reasons.  1) We use .Net 2.0 at work and our developers have a lot invested in webforms.  2) It helps me separate functionality away from code-behind files and adhere to the Single Responsibility Principle, which is especially important if the code will be tested.

I like most of the Supervising Controller pattern in the context of webforms.  What I don’t like (pain point) is the "loop" of event handling: view fires event, then raises another event that the controller is subscribed to, then the controller responds by executing some logic and then calling a function back in the view to render results.  This is convoluted... I like the separation of concerns, but I don't like having to subscribe to events more than once.  Can I just call controller methods directly from the view?  Maybe what I'm describing is called the "Passive Controller"... I need to look into it.  This is really, probably, a pain point that should be attributed to webform development.  But hey, webforms pay the bills!

TDD:

Yes, as of now I’m listing Test Driven Development as a pain point.  I really like testing my code.  I don't really like the syntax I'm using to mock functionality.  Mocking my dependencies is necessary to write unit tests, but the Record, Replay, Verify syntax in Rhino Mocks is not natural for me to set up and harder to explain to my team.  I am still trying to shove the Rhino Mocks 3.3 RRV syntax into the Arrange, Act, Assert (AAA) method I learned in boot-camp.  I need to change the way I'm using Rhino Mocks, or I need to start using a different mocking framework (Rhino Mocks supports the AAA syntax and is explained really well... Using .net 3.x lamba expressions.  AAA is possible with Rhino Mocks, but the 2.0 syntax is painful.

That’s it for pain points for now.  These by no means mean I am giving up on TDD or Supervising Controller.  Although painful right now, I think these are birth-pangs… I am hopeful that in 2 or 3 months they will be big giant assets in my toolbox.  I’ll end now on a (what is the opposite of a pain point?) happy point: Resharper 4.5 is incredible.  It makes me go faster… I intend to dedicate a future post to my top X favorite features.

<< NCharlie: TDD – Part 3 (a UI test)

Geo Tracks – 2009 May Cinco

I’m a little late this week because we moved last weekend.  Now I am closer to work (cut 2 hours per day off the commute!)… which means less time with the podcasts and more time with the family – a nice trade I think.  I’m still listening to book one in the Wheel of Time series, and will be for while.

Saturday, April 25, 2009

Geo Tracks – 2009 Apr 25

Hanselminutes 158 - Visiting Fog Creek Software and Joel Spolsky… I’m still not sure what exactly FogBugz is, but I learned a lot about how it was built and has evolved? Also, good to get some encouragement to keep writing, even if no one ever notices your blog :)

Psalm 80 – Psalm 85 ESV read by Max McLean

I started book 1, The Eye of the World, in Robert Jordan’s Wheel of Time series. Jeremy Miller put this at the top of his book list… I had never heard of it, so I’m giving it a try.  (Thanks for the iTunes gift cert Lucas!)

That’s it for this week… I worked from home Friday, so no commute.  Thursday I brought my wife to work with me so she could spend the day looking at places to live and schools in the area I work in… which means no podcasts since the wife likes to talk to me instead. :)  We may be moving closer to work soon!

NCharlie: TDD – part 3 (a UI test)

In this post I tackle the last task on my list for the task manager search feature: “Write tests, then implement the ShowSearchResults method.”

In part one I wrote unit tests to verify my TaskManagerController class is listening (subscribed) to the SearchRequested event, and that it correctly responds by calling the TaskManagerView class “ShowSearchResults” method.  In part two I verified that the TaskRepository correctly returns tasks when the Search method is called.

I admit: as I write this sentence I’m not sure how I will accomplish writing a test to verify that ShowSearchResults works… so I posted the question to Twitter:

I wrote a unit test to verify my controller calls my view's "ShowResult" method... What kind of test verifies ShowResult shows the result?

…and got a reply from my boot-camp instructor:

@charliesolomon we automate testing the ui. don't know that there's a great name for that other than automated ui test. or just ui test.

@mhinze So at this point (UI testing) it is time for me to use WatiN or equivalent?

@charliesolomon yes, sounds like it.

So here I go… WatiN is an open source web application test framework for .Net that will spin up an instance of my web browser and verify things on a web page.  To verify that ShowSearchResults is working I want to verify that the correct search results display on screen when the ShowSearchResults method is called on the TaskManagerView.

TaskManagerSearch_2

First I create a new class library project named UITests.  I want to keep these tests in a separate project because they take much longer to run than my unit tests.  If I’m going to keep this example strictly “Test First”, I need to, well, write my test first:

[Test]
public void Should_show_search_results()
{
Task task = new Task("foo");
TaskRepository repository =
new TaskRepository(new HybridSessionBuilder());
repository.Save(task);

using (IE ie = new IE("http://localhost:1035/Default.aspx"))
{
Button search = ie.Button(Find.ById("btnSearch"));
search.Click();

Div tasks = ie.Div(Find.ById("tasks"));

Assert.IsTrue(tasks.InnerHtml.IndexOf("foo") >= 0);
}
}


I’m not showing the [SetUp] method here for this Test Fixture… it ensures I have a clean database before running this test.  The test above just adds a task to the database, fires up the web page and verifies the search results come up correctly.



Default.aspx is a very simple page… just a text field, button and repeater to show the results. The “ShowSearchResults” method is what I’m interested in implementing and testing for this feature.  For the sake of brevity in this post, I will just refer you to the code to see how the ASPX page and code-behind file are constructed.  Here is the ShowSearchResults method from Default.aspx.cs:



public void ShowSearchResults(ICollection<Task> tasks)
{
rptTasks.DataSource = tasks;
rptTasks.DataBind();
}



I run my test and see WatiN fire up Internet Explorer, click the “Get” button, then search the results for my test record…



watin-clicking-get



watin-showing-results



…and the Resharper test runner shows the results:



ui-tests-passed



That’s it!  Of course it looks really simple here, and it is… but it actually took me 3 hours to get this simple test working.  Here’s why:



NUnit uses multi-threading by default, WatiN requires a single-threaded execution.  I solved this using a config file (“NCharlie.UITests.dll.config”… naming this config file correctly was actually the biggest time sink for this exercise.  I ended up adding a test to check that my config file was being read – thanks Charlie Poole)



For more information, check out the tdd-demo code branch and see the WatiN getting started guide.



<< NCharlie: TDD – part 2 (an integration test)  TDD Pain Points, A Retrospective >>

Saturday, April 18, 2009

NCharlie: TDD – part 2 (an integration test)

In my last post of this series I wrote unit tests to verify that an event (SearchRequested) from the View was handled by the Controller in my Agile/TDD sandbox application NCharlie.  I started with a sequence diagram showing the interactions needed to accomplish a search, then wrote down the tasks needed to complete this feature:

  1. Create interfaces for TaskManagerView and TaskRepository.
  2. Write tests, then write code to raise and handle the SearchRequestEvent method.
  3. Write tests, then implement the Search method.
  4. Write tests, then implement the ShowSearchResults method.

Two down, two to go.  The first two tasks could be test driven using unit tests.  Rhino Mocks allowed me to create a mock View and a mock Repository and concentrate on the TaskManagerController class… making sure it responded and handled the SearchRequested event correctly.  Now I want to wire up the Search method to return some actual results, and I want to show those results in an ASPX page, like this:

TaskManagerSearch

Since the Search method will be interacting with my database, I’ll need to test it using an integration test.  I like the way CodeCampServer keeps integration tests in a separate project… from the Resharper test runner it is easy to run all the tests in a project – so keeping the fast-executing unit tests separated seems to be a good idea.  I will add a new project to the NCharlie solution for integration tests and get to work (source is available in the tdd-demo branch of the NCharlie project.)

Here is the test method I want to build:

[Test]
public void Should_search_by_task_description()...


To write this test I will need to able to save Task entities to the database, retrieve them using the Search method, and make sure that the returned items contain the correct search results.  The saving part is accomplished in NCharlie using NHibernate and some helper classes that can be found in the open source projects CodeCampServer and Tarantino: IRepository, PersistentObject and HybridSessionBuilder.  These are mostly the same in NCharlie, though I did make a few changes so they would be .Net 2.0-friendly for this project.  The “PersistEntities” method below saves entities to the database, ensures the transaction is committed and the session is closed, so that subsequent calls to the database in this test can count on the entities being there.  I have not shown it here, but when running integration tests against a database it is important to setup the test first and make sure the database is in a consistent state.  This is done via a [SETUP] method in the RepositoryTestBase class, which my TaskRepositoryTester class is derived from.  Here is the test that verifies the search method is working correctly:



[Test]
public void Should_search_by_task_description()
{
Task task1 = new Task("foo");
Task task2 = new Task("xFOo1");
Task task3 = new Task("no fu");

PersistEntities(task1, task2, task3);

TaskSearchSpecification searchSpecification =
new TaskSearchSpecification();
searchSpecification.Description = "foo";

ITaskRepository repository =
new TaskRepository(new HybridSessionBuilder());
Task[] tasks = repository.Search(searchSpecification);

CollectionAssert.Contains(tasks, task1);
CollectionAssert.Contains(tasks, task2);
CollectionAssert.DoesNotContain(tasks, task3);
}


The “TaskSearchSpecification” class contains the search input fields (in this example I’m only searching on the Description field.)  Finally, I call the actual “Search” method on the TaskRepository and verify the results using the “CollectionAssert” class (part of NUnit.)



This test fails initially, and I implement the search method in TaskRepository to make it pass:



public Task[] Search(TaskSearchSpecification specification)
{
ICriteria criteria = GetSession()
.CreateCriteria(typeof (Task));

IList<Task> tasks = criteria
.Add(Restrictions
.InsensitiveLike("Description",
specification.Description,
MatchMode.Anywhere)
)
.List<Task>();

Task[] taskArray = new Task[tasks.Count];
tasks.CopyTo(taskArray, 0);

return taskArray;
}



task-search-test


For more information:



As I was writing this post I ran across Billy McCafferty’s article on NHibernate Best Practices with ASP.Net… I highly recommend it if you are interested in how these patterns are implemented.  I know things have changed in our field since he wrote this article (Billy later contributed the S#arp architecture which uses ASP.Net MVC), but this article is a great resource… especially for someone like me who works in a place where Webforms are still the tool we use to get our work done.  It is also very apparent from reading Billy’s article just how much it has influenced the ASP.Net world since it was written.  The CodeCampServer project I’m basing NCharlie on uses much of the architecture and patterns first described in Billy’s article and later in his S#harp architecture.



<< Previous NCharlie: TDD – part1, Next NCharlie: TDD – part 3 >>