May 2004 - Posts

Part 1: Automating Unit Tests with a Base Class

Summary:

Unit testing is quickly gaining traction within the .NET community.  By unit testing business objects developers are finding they are able to reduce the number of bugs they write, and improve the overall design of their applications.  The benefits of unit testing are well documented; however, unit testing objects doesn’t come free of charge.  Writing unit tests for each method of a business object is a time consuming task and often requires a lot of repetitive code.  This article discusses a method that can help reduce the leg work required to create a suite of unit tests for testing basic CRUD (create, read, update, delete) operations on business objects.  Removing the overhead of writing individual tests for each of the CRUD operations allows the unit testing effort to be focused on the area that it's most needed, the business logic of the application.

Note: This article focuses on automating the unit testing of objects in a domain model and ignores how some of the techniques could be used to test an application using a manager/service model.  Many of the ideas can also be applied to applications using the service model which I'll look to address in future postings/articles.

What is unit testing?

Before getting too far, let's briefly overview what unit testing encompasses.  Unit testing is the process of creating a set of automated tests that validate that the individual components (units) of an application behave as expected.  Each unit is tested via a test class, a “unit test.”  The unit test performs a series of assert’s to ensure each method exposed publicly provides the correct behavior when it’s provided different sets of information. 

Test driven development focuses on using unit tests to drive the development of software.  Rather then testing objects after they have been written, the tests for each class are written before the actual implementation.  Test driven development forces developers to design their applications with the users of the API in mind.  It results in a de-coupled API that is clearly focused on the tasks that the end developer will need to accomplish.

Creating automated tests for the objects within an application helps reduce bugs, and can result in a cleaner overall design for the application.  Both good things.

The Problem Area

Although unit testing provides many benefits it doesn’t come free of charge.  Unit testing objects takes time.  Over the course of a project unit testing will often end up saving time, however, the up front costs can’t be ignored.  Writing unit tests for every method of every business objects is time consuming and can involve a lot of repetitive coding. 

Each business object has a common set of operations.  These operations are typically referred to as CRUD (Create, Read, Update, Delete).  Each object needs to be able to be saved to the data store, read out of the data store, updated, and removed from the data store.  Every business object implements these features, and should have a unit tests validating that each of these operations performs as expected.  Although the implementation of each operation is similar across all business objects, it is different enough to require a separate unit test method for every single business object.  In a large application this adds hundreds of methods for testing a set of functionality which is consistent across all of our objects.  This forces us to write a lot of repetitive code.  But should it?

Why test with the database?

Before moving on to address whether testing the basic CRUD operations on business objects should require a lot of repetitive coding let me first address the age old question: “Should a database be included in my unit tests?” 

Many developers within the Unit Testing / Test Driven Development (TDD) community believe that unit tests should not include the database.  Including the database in unit testing and TDD efforts does slow down the process and can interrupt our coding “flow“, however it has benefits which can be extremely valuable:

  • Validate the stored procedures function as expected.
  • Provides an overall integration test for the application and database.
  • Forces you to think about deployment, integration, and setup of the database from the start.
  • Forces you into a one click build, from scratch, including the database.
  • Including the database has disadvantages as well:

    • Have to spend more time thinking about how to fit the database in with the unit tests.
    • Need to write scripts OR DTS packages to setup the database in a clean state.
    • Need to worry about cleanup of any data inserted during the running of the unit tests.
    • The tests will take longer to run when it’s running against the real database rather then just a Mock object.

    Over the last couple of years I’ve stood on both sides.  Early on I didn’t know any better so included the database in every aspect of my testing.  As I became more familiar with Unit Testing and TDD I slowly began introducing Mock Objects, and stub methods into my unit tests.  By reducing the interaction with the database I was able to increase the quality of my designs and get into more of a groove as I wrote my test classes.  Unfortunately, I also started noticing more problems with my database and stored procedures.  Usually the problem wasn’t significant, a missing parameter on a stored parameter or an improperly set default value for a column.  Clearly the database needed to be included in my testing process, but how?

    Next up: How do we automate our tests, and how does this compare to how we currently test our business objects

    Intro: Automating Unit Tests with a Base Class

    A couple weeks ago I posted a brief outline of an article which I've been wanting to spend some time writing.  Since I haven't had much success setting aside time to actually write the article I'm going to start posting my thoughts and excerpts to this blog in hopes that I actually get most of my thoughts, ideas, and code samples in a central place.  I'd appreciate any comments, questions, or insights which you might want to share!

    Do you have Guts?

    Last night I finished Guts written by Kevin and Jackie Freiberg. The book takes a look at “companies that blow the doors off business as usual.”  The book consists of a series of stories about “gutsy leaders“ who are leading their companies to extraordinary success.  Each chapter looks at a characteristic of leaders that could be seen as unconventional, unordinary, and just plane nuts.  Rather then following conventional “wisdom“ the leaders highlighted in Guts take a different approach.  They value their people, provide them with opportunity for growth and leadership, and provide an atmosphere where employees take ownership and responsibility for everything they do.  Leading a successful company, inspiring employees, and delighting customers cannot be done by following the path of those before you, to be truelly successful takes more, as the authors say it takes “Guts.“ 

    • Gutsy Leaders Blow the Doors Off Business as Usual
    • Gutsy Leaders Brand Their Cultures
    • Gutsy Leaders Create a Sense of Ownership
    • Gutsy Leaders Hire People Who Don't Suck
    • Gutsy Leaders Lead with Love
    • Gutsy Leaders Make Business Heroic
    • Gutsy Leaders Inspire Fun

    Although the title is a bit corny the book was a very interesting read. 

    WSE2 messaging internals and office mail

    Steve Maine provides a very good post detailing how the internals of WSE2 messaging is really just hyped up office mail.  :-)

    Microsoft is Agile, why aren't you?

    Has everyone noticed the iterative development cycles we're seeing with VS.NET 2005?  It seems as if Ward, Jim Newkirk and friends have persuaded the powers that be within Microsoft that agile development works.  They have a slightly extended iteration cycle (about two months) but considering the size of the “project” they're working on anything shorter probably wouldn't make sense.  It's interesting to watch a huge software company like Microsoft slowly adopt agile development methodologies.  Maybe there's something to this “Agile Manifesto”?  Then again maybe it's just a fad?

    How to Interview a Programmer

    We've recently brought in some peeps for a couple open positions we have at my gig.  We have not been impressed.  As we reviewed the candidates we started discussing the process of interviewing and things we could do to improve our interviewing process.  One of my colleagues came across How to Interview a Programmer which provided some decent insights into ways some industry “experts” go about finding good talent.

    • Explore an area of expertise
    • Hire for talent not for a position
    • Have them critique something
    • Ask them to Solve a problem
    • Look at their code
    • Find out what books they read
    • Ask about a people problem
    • Get to know them

    How do you uncover good talent?  What process do you have candidates go through?

    Hibernate & NHibernate

    I recently came across an interview with Gavin King, founder of the Hibernate open source object/relational mapping project.  Gavin talks about some of the challenges with o/r mapping and the reasons he decided to join JBoss.

    In related news I received a comment on my .NET O/R Mappers post from szoke letting me know that the NHibernate (sf.net) project, which is a .NET port of Hibernate, is “alive.”

    Are you building Alien Artifacts?

    Jon Eaves has an interesting post about building alien artifacts.  In his post he talks about how consultants need to be cognizant of the developers that will ultimately have to maintain the solution they are delivering.  If they don't take into account the skills and experience of the maintenance staff they may very well build an alien artifact. 

    One of the things that I worry about is a behavior which I shall call "building alien artifacts". This is where an external team (it may be external consultant, or in-house people, or even just senior people within the same department) help build a project in a manner that the incumbent team cannot fathom, maintain or update safely. Essentially an alien has dropped this highly useful, well built device into your lap, and if you press the wrong button, or combination of buttons, it's likely to explode or at the very least give you a nasty shock. To reinforce what I'm talking about here, the aliens have built a good system, not some piece of crap that can't be maintained, but the how and why is beyond the capabilities of the team who must take it over.

    Red Hat Web Application Framework & CMS

    Yesterday I did a quick evaluation of the Red Hat Web Application Framework as well as Red Hat CMS.  Red Hat acquired the rights to both from ArsDigita.  Below are some rough notes....

     

    Red Hat Web Application Framework

    What does it provide?

    • Persistence Layer (OR Mapping)
      • Handled by inheriting from DomainObject and defining .pdl mapping file.
      • PDL = Persistence Definition Language (Example Below)

    // next comes the "object type" keyword followed by the name of
    // the object type
    object type Publication {
       // the first block of code within the object type is a set of
       // mappings from the Attribute Java type and Attribute name to
       // the database column to which they correspond.
       BigDecimal id = publications.publication_id INTEGER;
       String name = publications.name VARCHAR(400);
    }

     

    • Handles Session and Transaction Management
    • Objects Retreived via OID (Object ID)
    • Set of objects retrieved via DataQuery – can apply Filters
    • Dynamic SQL is generated on the request for the first object

    // get all of the Publications in the system.  Calling "retrieve" triggers
    // the "retrieve all" event defined in the PDL file.  Note that
    // the string passed in to the method is the model name (tutorial)
    // followed by the object type name (Publication) separated by a dot (.).
    DataCollection pub = SessionManager.getSession().retrieve("tutorial.Publication");

    // now we want to filter on the ID of the publication
    pub.addFilter(pub.getFilterFactory().addLessThan("id", new Integer(100), false));

    // finally, we can loop through the publications and print out its name
    // the query to get the information out of the database is executed
    // when next() is called for the first time

    while (pub.next()) {
      System.out.println(pub.get("name"));
    }

    • Component Kernel
      • User & Group configuration
      • Object Permissions
      • Resources
    • Services
      • Object Auditing – Tracks when and by who an object was last modified
      • Categorization – Hierarchy of categories for categorizing objects (Article, Press Release, etc.)
      • Form Builder – Build web forms using a web based administration tool
      • Globalization
      • Mail/Messaging/Notification
      • Portal/Portlet support
      • Search Service – Using Lucene (http://jakarta.apache.org/lucene/) or Oracle interMedia
      • Workflow – Contains a set of tasks that can be enabled, disabled, finished.  Tasks can be assigned groups/permissions.
      • Versioning – Provides rollback, roll-forward capabilities and object diff functionality.

    http://www.redhat.com/docs/manuals/waf/rhea-dg-waf-en-6.1/index.html
    http://www.redhat.com/software/rha/

    Red Hat CMS

    • Built on top of Red Hat Web Application Framework
    • Content Types – Article, Press Release
      • Defines different types of content and their properties/attributes
    • Content Items – Contains the actual data for a piece of content
    • Content Bundle – A group of related content items (all content for all the different languages)
    • Workflows – All items start in Author State.  Author state only allows the changes to be submitted to the next step.  They then proceed through multiple Edit Steps.  After each edit step the content can be approved for rejected.  Rejected content is sent back to the previous step.  Final step is for the content item to be marked as deploy and assigned a lifecycle
    • Lifecycle – Defines what happens when a content item is published. Lifecycle consists of multiple phases.  A listener is used to move the item among its various phases.
    • Role based security
    • Editing and Live Server – Editing server is used to manage and edit the content.  The Live Server delivers content to the end user.
    • Content is organized into Containers – Folders, Content Bundles
    • After a content item is published it goes through a publishing process
      • Content item is cloned and has properties copied
      • Set Versioning attributes
      • Pending version is added to the database
      • Lifecycle is kicked off
      • Lifecycle system responsible for polling the database for publishined items and kicking off their assigned Lifecycle
      • PublishLifecycleListener promotes the pending version
      • Unpublishes the currently published version
      • Updates Versions
      • Set’s the content item to live
      • Generates a list of all live published content items which point to the content item being published and sets up associations.  All items pointing to this item are queued for re-publishing to have their links updated.
      • Generates a list of all the live published content items that the current content item point
    • Standard presentation involves generating an XML representation of the content item and applying an XML Style Sheet (XSL)
    • Xml Rendering is  done via the DomainObjectXMLRenderer in the Red Hat WAF
    • Content Type authoring is setup via configuration files (authoring kit, authoring steps)
    • Authoring Steps are individual steps in the creation of content (Properties, Page Content, etc.).  They are associated with UI elements for the step.
    • Templates can be written in JSP or XSLT
    • Authoring Kits, Content Loaders & Initializers are all configured via xml configuration files.   

    Presentation Tips

    These tips from Rebecca Dias are too good not to repeat:

    Some tips on how to build a great presentation

    I noticed that I have had some pretty consistent feedback with every speaker on the track.  Figured I would share this with everyone.

    • Tell the audience what you plan to tell them
    • Keep the audience awake while you pack their brain full of the material you promised - laughter helps keep people engaged
    • At the end, summarize what you have learned
    • Take a step back from your presentation, ask yourself the question, “If I was going to this session, what would I be expecting to leave with?“  Now ask yourself the question, did the presentation satisfy that need?
    • When you are reviewing your slides, think, what is the audience going to call B.S. on me for?  Make sure you are making strong arguments if you are making a claim that is hard to believe.  Otherwise, change your tone.
    • Then, once the flow of the presentation is solid, go back and remove all unnecessary wording, in fact cut all content from each slide, put it into the notes, and re-write the slide with only the highlighted words.  Remember in college when you highlighted the important key words.  Make your points, sweet, short, and concrete.  You want your audience listening to you, not reading
    • Don't use more than 6 bullets on a slide.
    • And finally, make friends with someone who is color blind, and give them your presentation.

    http://blogs.msdn.com/rdias/archive/2004/05/10/128889.aspx

    Real Programmers...

    Real programmers only comment what is absolutely necessary. Any time  we feel that the code needs a comment we should take a step back and think about ways in which we can make the code more clear.  Often times separating a set of conditional logic into a separate method that indicates its intention is enough.  I view the need for comments as a warning, if I need this comment is the code readable enough?  Probably not, however, it usually only takes a couple “Extract Method” and “Rename Method” refactorings before things become more clear. 

    Xml comments make it more difficult to stick by the “only comment what is necessary” rule.  The ability to generate full API documentation via Xml comments causes me to do a lot more commenting then I would like.  I'm still trying to find the right balance.

    What's your opinion?

    [Inspired by: Real Programmers....don't use comments?!?!]

    Are you using Enterprise Services, Brian asks why not?

    Brian Noyes has written up a detailed post addressing many of the typical excuses for not using Enterprise Services.  He helps to set straight some common misconceptions and provides a lot of good insight into why using ES might be a good option for your application.

    Check it out

    Jimmy, they're some of my favorites too!

    Jimmy Nilsson is running a book quiz on his favorite acronym friendly books.  They're some of my favorites as well!

  • DDD - Domain Driven Design
  • GoF - Design Patterns - Gang of Four
  • JDO - Java Data Objects
  • PoEAA - Patterns of Enterprise Application Architecture
  • POSA - Pattern-Oriented Software Architecture
  • PPP - Agile Software Development: Principles, Patterns, and Practices
  • TDD - Test Driven Development

    Unfortunetly I don't didn't know them all so don't get the secret prize :-(

  • Maybe we do need SOME documentation, even with Agile...

    James Ross posts about a recent experience where he had some difficulties ramping back up on an Agile project simply via conversation.  The experience has caused James to be a little less “dismisive of the value of documentation.” 

    Are we looking at our application architecture from the wrong angle?

    Ralf Westphal suggests that we change the view of basic application architecture by moving the business logic to the top.  At the center of any application is its business logic.  In today's view of an application we [1] usually center things around the UI.  This leads us [1] to design for user interface (UI) instead of for the most important aspect of our application, our business logic.

    [1] “we”and “us” refer to MS developers in general, not necessarily you the reader and I the writer

    Caching a page for a second does what?

    Steven Smith has written an interesting article about the dramatic effect caching a data intensive page for a single second can have on performance. 

    Domain Driven Design

    I've heard a lot of really good things about Domain Driven Design so I decided to pick it up today.   Maybe it will help me get out of my funk?

    A Thread on DataSet vs. Custom Classes

    Udi Dahan pointed me to a nice little discussion going on about DataSets and custom classes.  My personal preference is to use custom classes.  I've used DataSets on a couple prototypes, but, have primarily stuck with the custom class solution for my production applications.

    Check out the thread at: http://objectsharp.com/Blogs/barry/archive/2004/02/10/273.aspx

    I'm in a "blog funk"

    I've recently found myself in a bit of a “blog funk.” Last month I hit an all time low, only 13 posts for the month.  What does one do when they get caught up in a blog funk?  How does one escape and enter back into the blogosphere?  Something needs to change....but what?

     

    Confidence through TDD

    The last couple of days I've been working on some enhancement to an application that I wrote a little over a year ago.  As I begun to make changes I could feel my stress level rising, my confidence dropping, and my programming ego drowning in a pool of doubt.  Clearly this application was written before I had embraced test driven development (TDD).  I needed help, my ego clearly couldn't take much more....

    Red. Green. Refactor.
    Red. Green. Refactor.

    Ahhh, stress level dropping, confidence rising, ego climbing....thank you Mr. Tdd!

    Review: Extreme Programming Adventures in C#

    Last night I finished reading Extreme Programming Adventures in C# by Ron Jeffries.  Overall I enjoyed following Ron through his adventures. 

    The book takes you on a journey through the life of an extreme programming project.  Ron leads the way, providing insights and thoughts about how and why Extreme Programming works.  Throughout the project he focuses on the stories that are most important to his customer (which happened to be himself).  He attacks each feature using test driven development and makes out considerable well.  Along the way he finds many “code smells” which he goes onto remove via refactoring (when the time is right).

    The book offered a good look into how projects can be attacked using extreme programming.  Throughout the book Ron offers tips, insights, and advice which is valuable no matter what your chosen methodology.  Although the methods Ron used to implement the features of his project may not be what we all would have selected, the principles and practices he follows are something we should all consider adopting.  By focusing on keeping clean, well factored code, Ron was able to adapt extremely well to changing requirements and new features. 

    This book didn't teach me much about C#, or Extreme Programming (I already read a good number of books on those topics) but it did provide me a look inside the way a extreme programming veteran approaches projects.  I was able to learn many valuable lessons through Ron and was also able to pick up a couple good tips that will undoubtedly help me as I enjoy my own programming adventures. 

    Two books at once, not so much

    A couple weeks ago I posted the question, “How many books do you read at one time?“  It seems that I was in the minority, reading a single book at a time.  Since I didn't want to miss out I started reading a business book (Start Your Own Business) and technical book (Extreme Programming Adventures in C#) at the same time.  I quickly realized that I just don't have enough reading time available to pull this off, I think I'll just focus on my one book at a time until I find a way to extend my day past 24 hours.

    FABRIQ

    It looks like we're going to start seeing more of Clemens with the upcoming release of FABRIQ.  Get an early look into the architecture of a FABRIQ from the EMEA Architect Tour:

    http://www.dotnetmaailma.com/video/19042004/5/start.html