About Me

Training

Nothin But .Net Developer Bootcamp

Navigation

Search

Categories

On this page

Coincidence? I think not.
JP’s Daily Dose of Inspiration - #7
Test examples with MBUnit and jpboodhoo.bdd
Source code moved to assembla
Keep Moving Forward!!

Archive

Blogroll

 Agile Developer Venkat's Blog
 Ayende @ Blog
 B#
 Barry Gervin's Software Architecture Perspectives
 Boy Meets World
 Brad Abrams
 Canadian Developers
 Christopher Steen
 Claritude Software News
 Clemens Vasters: Enterprise Development and Alien Abductions
 Coding Horror
 Coding in an Igloo
 Dare Obasanjo aka Carnage4Life
 Darrell Norton's Blog [MVP]
 David Hayden [MVP C#]
 Don Box's Spoutlet
 Eric Gunnerson's C# Compendium
 EZWeb guy: Jeffrey Palermo [C# MVP]
 Fear and Loathing
 Generalities & Details: Adventures in the High-tech Underbelly
 Greg Young [MVP]
 Greg's Cool [Insert Clever Name] of the Day
 IanG on Tap
 Ingo Rammer's Weblog
 ISerializable - Roy Osherove's Blog
 James Kovacs' Weblog
 Jason Haley
 Jean-Luc David
 Jeremy D. Miller -- The Shade Tree Developer
 JetBrains .NET Tools Blog
 Jimmy Nilsson's weblog
 John Bristowe's Weblog
 John Papa [MVP C#]
 Jon Skeet's Coding Blog
 JonGalloway.ToString()
 Jump the Fence or Walk Around
 Lambda the Ultimate - Programming Languages Weblog
 Larkware News
 Lutz Roeder
 Marquee de Sells: Chris's insight outlet
 Martin Fowler's Bliki
 Mike Nichols - SonOfNun Technology
 MSDN Magazine - .NET Matters
 MSDN Magazine - All Articles
 OdeToCode Blogs
 Onion Blog
 Planet TW
 Raymond Lewallen [MVP]
 Rockford Lhotka
 RodMan's Corner
 Roger Johansson's blog
 Sahil Malik - blah.winsmarts.com
 Sam Gentile's Blog
 Scott Bellware [MVP]
 Scott Hanselman's Computer Zen
 ScottGu's Blog
 secretGeek
 Service Station, by Aaron Skonnard
 Signum sine tinnitu--by Guy Kawasaki
 Stephen Toub
 Steve Eichert's Blog
 Steven Rockarts
 The Blog Ride
 The Coding Hillbilly
 The Daily WTF
 TheServerSide.net: News
 Tim Gifford
 Vance Morrison's Weblog
 you've been HAACKED

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

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 519
This Year: 28
This Month: 0
This Week: 0
Comments: 1593

 Friday, January 30, 2009
Friday, January 30, 2009 12:47:00 PM (Mountain Standard Time, UTC-07:00) ( General )

Sitting up here in the office in a coding frenzy, I had to stop as I could hear the current Oprah show in the background and the topic was very interesting. She was interviewing young business moguls who have achieved incredible things at very young ages.

One of the common traits that all of the people shared was what? PASSION. They all reiterated something that I share with lots of people that I talk to:

“When you do something you are passionate about, it does not feel like work”!!

So many people get caught up in the pursuit of “money/security….” that they forsake the opportunity to pursue something that will have a meaningful return :

“The Realization Of Their dreams”

We live in a world where too many people  forsake their dreams for things that seem more attainable or safe. We fail because we don’t strive to reach something much higher.

I want to challenge you this year to reach for that goal that seems unattainable, I am sure that you might surprise yourself!!

Develop With Passion!!

Comments [3] | | # 
 Tuesday, January 27, 2009
Tuesday, January 27, 2009 6:31:00 AM (Mountain Standard Time, UTC-07:00) ( Inspiration )

Amazing video, amazing person. It is amazing what the love of God can allow people to accomplish!!

Are you going to finish strong
Comments [2] | | # 
Tuesday, January 27, 2009 6:08:00 AM (Mountain Standard Time, UTC-07:00) ( C Sharp | Programming )

The other day I placed a library up on assembla that I use as a place to store my current set of conventions on writing unit tests. My current flavour of testing focuses on the use of BDD to emphasize context and behaviour of a particular SUT (System under test) that I am exercising.

This post is not about detailing my current thinking on BDD, more to demonstrate some ways that you can use the very small framework in conjunction with MBUnit to remove a lot of cruft from your tests. To that end, the following are some sample tests written to demonstrate different aspects of the library:

1) Adding two numbers (without a because block):

 

    public class when_adding_2_numbers_together : observations_for_a_static_sut

    {

        [Observation]

        public void should_result_in_the_sum_of_the_2_numbers()

        {

            (2 + 2).should_be_equal_to(4);

        }

    }

Notice that the class simply inherits from a class named  observations_for_a_static_sut. This is the base class you will use when you are either testing a static class, or (as in this case) you are simply writing a quick inline test.

2) Adding two numbers with a because block (the because block is meant to focus your eyes to the actual behaviour you are exercising:

    public class when_adding_2_numbers_together : observations_for_a_static_sut

    {

        static int result;

 

        because b = () =>

        {

            result = 2 + 2;

        };

 

        [Observation]

        public void should_result_in_the_sum_of_the_2_numbers()

        {

            result.should_be_equal_to(4);

        }

    }

The behaviour being exercises is placed inside of a anonymous method block assigned to a delegate type (because). It is also important to note that the field is static.

Let’s look at a slightly more involved test that has some dependencies, a factory method for the system under test, etc.  Here is the start:

 

        [Concern(typeof (DatabaseGateway))]

        public class when_retrieving_a_set_of_rows_based_on_a_query : observations_for_a_sut_without_a_contract<DatabaseGateway>

        {

            static IEnumerable<DataRow> result;

            static IQuery query;

            static IDatabaseConnectionFactory connection_factory;

            static IDatabaseConnection connection;

            static IDbCommand command;

            static IDataReader reader;

 

            context c = () =>

            {

                connection_factory = an<IDatabaseConnectionFactory>();

                query = an<IQuery>();

                connection = an<IDatabaseConnection>();

                command = an<IDbCommand>();

                reader = an<IDataReader>();

 

                connection_factory.Stub(x => x.create()).Return(connection);

                connection.Stub(x => x.create_to_run(query)).Return(command);

                command.Stub(x => x.ExecuteReader()).Return(reader);

            };

 

            because b = () =>

            {

                result = sut.get_rows_matching(query);

                result.force_traversal();

            };

 

            [Observation]

            public void should_leverage_db_infrastructure_to_return_a_set_of_rows_from_the_db()

            {

                result.should_not_be_null();

            }

 

            [Observation]

            public void should_dispose_the_appropriate_items()

            {

                connection.was_told_to(x => x.Dispose());

            }

 

            public override DatabaseGateway create_sut()

            {

                return new DatabaseGateway(connection_factory);

            }

        }

Let’s start by taking a look at the context block:

            context c = () =>

            {

                connection_factory = an<IDatabaseConnectionFactory>();

                query = an<IQuery>();

                connection = an<IDatabaseConnection>();

                command = an<IDbCommand>();

                reader = an<IDataReader>();

 

                connection_factory.Stub(x => x.create()).Return(connection);

                connection.Stub(x => x.create_to_run(query)).Return(command);

                command.Stub(x => x.ExecuteReader()).Return(reader);

            };

In this block I define all of the dependencies that are going to come into play during the test. The “an” method, is a generic method that lives on the base class, which basically creates a mock of the contract in question. It carries on to setup return values for method calls that will be leveraged during the course of the SUT doing its work. Unfortunately, it is hard to identify which mocks are direct dependencies of the sut and which are collaborators. It is only when you look at the factory method for the system under test:

            public override DatabaseGateway create_sut()

            {

                return new DatabaseGateway(connection_factory);

            }

Here it is evident that the direct dependency of the DatabaseGateway is the connection_factory (IDatabaseConnectionFactory). The because block highlights the behaviour being tested:

            because b = () =>

            {

                result = sut.get_rows_matching(query);

                result.force_traversal();

            };

The force_traversal method is a utility method that forces the traversal of an enumerable. It is necessary as the implementation of the method under test uses deferred execution by nature of leveraging the yield keyword and returning an IEnumerable. Here is the implementation of the class under test:

        public class DatabaseGateway

        {

            IDatabaseConnectionFactory connection_factory;

 

            public DatabaseGateway(IDatabaseConnectionFactory connection_factory)

            {

                this.connection_factory = connection_factory;

            }

 

            public IEnumerable<DataRow> get_rows_matching(IQuery query)

            {

                var table = new DataTable();

                using (var connection = connection_factory.create())

                using (var command = connection.create_to_run(query))

                using (var reader = command.ExecuteReader())

                {

                    table.Load(reader);

                }

                foreach (DataRow row in table.Rows) yield return row;

            }

        }

Let’s now show the exact same test written with the minimum amount of plumbing code that is necessary:

        [Concern(typeof (DatabaseGateway))]

        public class when_retrieving_a_set_of_rows_based_on_a_query : observations_for_a_sut_without_a_contract<DatabaseGateway>

        {

            static IEnumerable<DataRow> result;

 

            context c = () =>

            {

                the_dependency<IDatabaseConnectionFactory>().Stub(x => x.create()).Return(the_dependency<IDatabaseConnection>());

                the_dependency<IDatabaseConnection>().Stub(x => x.create_to_run(the_dependency<IQuery>())).Return(the_dependency<IDbCommand>());

                the_dependency<IDbCommand>().Stub(x => x.ExecuteReader()).Return(the_dependency<IDataReader>());

            };

 

            because b = () =>

            {

                result = sut.get_rows_matching(the_dependency<IQuery>());

                result.force_traversal();

            };

 

            [Observation]

            public void should_leverage_db_infrastructure_to_return_a_set_of_rows_from_the_db()

            {

                result.should_not_be_null();

            }

 

            [Observation]

            public void should_dispose_the_appropriate_items()

            {

                the_dependency<IDatabaseConnection>().was_told_to(x => x.Dispose());

            }

        }

The factory method has been removed along with the fields to reference the dependencies that come into play. For readability, I think this approach loses out, so this last way is the way I would finish up with:

        [Concern(typeof (DatabaseGateway))]

        public class when_retrieving_a_set_of_rows_based_on_a_query : observations_for_a_sut_without_a_contract<DatabaseGateway>

        {

            static IEnumerable<DataRow> result;

            static IQuery query;

            static IDatabaseConnectionFactory connection_factory;

            static IDatabaseConnection connection;

            static IDbCommand command;

            static IDataReader reader;

 

            context c = () =>

            {

                connection_factory = the_dependency<IDatabaseConnectionFactory>();

                query = an<IQuery>();

                connection = an<IDatabaseConnection>();

                command = an<IDbCommand>();

                reader = an<IDataReader>();

 

                connection_factory.Stub(x => x.create()).Return(connection);

                connection.Stub(x => x.create_to_run(query)).Return(command);

                command.Stub(x => x.ExecuteReader()).Return(reader);

            };

 

            because b = () =>

            {

                result = sut.get_rows_matching(query);

                result.force_traversal();

            };

 

            [Observation]

            public void should_leverage_db_infrastructure_to_return_a_set_of_rows_from_the_db()

            {

                result.should_not_be_null();

            }

 

            [Observation]

            public void should_dispose_the_appropriate_items()

            {

                connection.was_told_to(x => x.Dispose());

            }

        }

This tests reintroduces the fields to store the mocks. It still removes the factory method, and it uses the following two different methods:

  • the_dependency<T>
  • an<T>

to differentiate between a constructor depedency and a mock that happens to come into play while collaborating with that dependency.

There are lots of other things you can do, and I will post more examples as requests come in!!

 

Develop With Passion!!

Comments [5] | | # 
 Thursday, January 22, 2009
Thursday, January 22, 2009 1:36:00 PM (Mountain Standard Time, UTC-07:00) ( Programming )

A couple of people have asked about where the source code I placed on google code had moved. It has all been moved over to assembla. Here are the projects that are currently up there:

bdddoc - http://svn2.assembla.com/svn/bdddoc – Tool for generating html documents based on your unit tests. Works with any attribute driven testing framework.


jpboodhoo.bdd - http://subversion.assembla.com/svn/jpboodhoo_bdd – Library that contains my current approach to writing tests. Is basically a thin wrapper on top of MBUnit 2 that has a much more natural feel to it. If you want some examples of how to write tests with this, please send email requests for a blog post!!


nbdn_web_store - http://svn2.assembla.com/svn/nbdn_web_store – Web store project that was harvested from the 2008 Germany Nothin But .Net course. Demonstrates the use of front controller architecture, fluent interfaces, bdd, interface based programming etc…

Develop With Passion!!

Comments [3] | | # 
 Monday, January 05, 2009
Monday, January 05, 2009 8:03:00 AM (Mountain Standard Time, UTC-07:00) ( General )

To steal a quote from Walt Disney,this is going to be the theme I will keep trying to encourage people about this year. Don’t get too focused on the person on your left, or to the person on your right, just move forward at your own pace!!

I pray that the 2009 year will bring all of you much joy and success in your personal and professional lives.

The 2009 Nothin But .Net course schedule has now been finalized. There are some locations that are still hovering on the radar that have not been posted. A significant change that will take place this year is the attendee cap which will be placed at 16 people. Just the right size for 4 groups of 4 people. If you are hoping to register for one of the upcoming courses you will have to be patient and give me a couple of weeks, as I am currently switching over to a new registration provider.

It is my hope and prayer that this year will allow you the opportunity to grow incrementally and consistently and that you will Keep Moving Forward!!

Develop With Passion!!

Comments [1] | | #