Wednesday, January 25, 2006

FitNesse: Using COM+ Enterprise Services to Manage Transactions

I’ve been working on integrating FitNesse and FIT into my current project. As with all automated testing, managing test data is a challenge.

To manage the data we have 3 options:

  1. Abstract the data from the system
  2. Restore the data to a known state before the tests run
  3. Create a reciprocating transaction. i.e. Each insert has a corresponding delete
  4. Rollback the test when it’s completed.

Option 1 is great, but it is difficult to abstract a system from the database especially if you are working with a pre-existing (legacy) system.

Option 2 is viable, but I hate having to do a database restore before I run a test suite.

I’m too lazy for option 3 and wouldn’t pick this option if there are a slew of user acceptance tests(UAT).

So I want to use option 4. Roy Osherove wrote a great article describing how to manage your unit tests using COM+ enterprise services and I have been using this method ever since, however, my tests use “Services Without Components” (SWC) included in COM+ 1.5.

I figured I could you the same concept with FitNesse! My solution is very simple. I created a ColumnFixture that can begin a transaction, commit a transaction, but most importantly rollback a transaction. The Fixture has 2 columns, Action and Result?. The Action column take one of three values: “begin”, “rollback”, and “commit”. The Result? column can be left blank. It will get populated with the System.EnterpriseServices.TransactionStatus after the Result() method is executed.

Now that I have this ColumnFixture, I created two pages: BeginTransaction and RollbackTransaction. These pages will be included before and after, any test fixtures that I want to run within a transaction. I prefer to use FitNesse’s !include widget, but you could also use the SetUp and TearDown pages.

Here's the code.

/// <summary>
    /// This class provides a simple interface to support COM+ transactions.
    /// </summary>
    public class TransactionFixture : ColumnFixture
    {
        public string Action = "begin";
        public string Result()
        {
            TransactionStatus retVal = TransactionStatus.NoTransaction;
            switch(Action.ToLower())
            {
                case "begin":
                    ServiceConfig config = new ServiceConfig();
                    config.Transaction = TransactionOption.RequiresNew;
                    ServiceDomain.Enter( config );
                    break;
                case "rollback":
                    
                    if( ContextUtil.IsInTransaction )
                    {
                        ContextUtil.SetAbort();
                    }
                    retVal = ServiceDomain.Leave();
                    break;
                case "commit":
                    
                    if( ContextUtil.IsInTransaction )
                    {
                        ContextUtil.SetComplete();
                    }
                    retVal = ServiceDomain.Leave();
                    break;
                default:
                    throw new ArgumentException("Invalid value", "Action");
            }

            return retVal.ToString();
        }
    }

Screenshot - Before


Screenshot - After


 

BeginTransaction Page

|!-GiffordConsulting.FitNesseAid.TransactionFixture-!|
|Action|Result?|
|begin||

RollbackTransaction Page

|!-GiffordConsulting.FitNesseAid.TransactionFixture-!|
|Action|Result?|
|rollback||

Putting it all together using import widget

!include BeginTransaction

|!-GiffordConsulting.FitNesseAid.SignonFixture-!|
|Username|Password|Save?|
|Tim|apassword|true|

!include RollbackTransaction

Saturday, December 10, 2005

Private Strong-named Assemblies Not Supported

I was surprised to learn (the hard way) this week that Microsoft doesn’t support strong-named assemblies if they are deployed to the \bin directory of an ASP.NET application. If you need proof, check out these links:

 

http://support.microsoft.com/?id=813833

http://support.microsoft.com/?id=324519

 

There are two reasons to sign you assemblies:

  1. Install in the Global Assembly Cache (GAC)
  2. Install a Serviced Component into a serviced or library Component Services application

 

Once you have signed an assemblies, that assembly can only reference other signed assemblies.

Previously to finding that deploying signed assemblies privately is not supported, I would sign my assemblies whenever I started a new project. This way if I decided down the line that I wanted to install in the GAC, I didn’t have to re-build with a sn.exe key.

Has anyone heard about this?

 

Friday, November 25, 2005

Unit Test Database Code with COM+ (Enterprise Services)

I’ve been using NUnit for a couple years now and love it. However, most of my applications use databases extensively and most of the features within these applications have to do with managing the data in the database. This means I don’t have a lot of business logic for these operations, but I do have a lot of code that interacts with the database. I need unit test for that code. This is where COM+ comes in.

If you have talked to me about unit testing, I have probably mentioned using COM+ with unit tests to rollback any database transactions that occur within the context of the unit test. This means you can insert, update, delete and select data from within your unit test and when the test in completed, all changes will be rolled back. Since I’ve started using it, I can’t live without it. I don’t have any database dependencies with my tests, they are all self supporting. Plus, if you run the tests against a production database (on accident or to troubleshoot) the production data will not be modified.

Roy Osherove gives the details here.

One other tip I just learned that is associated with this method. You can read the “dirty” records within the database if you are stepping thru your COM+ unit tests by changing the transaction isolation level in Query Analyzer.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

 

Saturday, November 19, 2005

Agile Management

 I’m sure you have seen the Agile Dilbert cartoon. I’ve been sent this cartoon from a couple people at work and now Javier is looking for my comments…So here goes.

The comic highlights that management doesn’t seem to understand the business impact of agile methods. There is a strong, embedded culture in management for fixed feature, fixed budget, and fixed timeline projects. In most organizations, this culture comes from the budget process. The budget process is similar to the waterfall method for software development. You define your objectives for the following year (scope), determine the hard costs to achieve those objectives (costs), track the budget through out the year(deadline) and tie a bonus for staying within budget.

What happens at the end of the year? If there is money left in the budget, managers find a way to allocate the money so they won’t lose the budget next year. Not very efficient! If they are short on money either move money from another budget, or find some ways to cut some costs last minute.

I think management would improve by implementing a more agile process. What if they supplement the long term objectives with short term goals (iterations), track progress along with costs (burn down) and have the option to change or cancel the objective if the business value isn’t found.

We are a long ways away from this happening, but there is hope. In Jack Welch’s new book, Winning, he talks about changing the fixed budget culture within G.E. to an “Operations Plan” culture. The operations plan is a yearly plan that outlines goals and costs for the company with flexibility to change over time. This frees managers to make decisions that are good for the business, not just good for their bonus.

Thursday, November 10, 2005

VS.NET SQL Projects

On my current project, we’ve been using the SQL Project that’s included with VS.NET. I did this with some hesitation. I wanted the scripts to be integrated with the IDE, but I’ve never had any luck with managing SQL scripts. I had 3 issues:

  1. The command file that VS.NET generates never executed my scripts in the correct order. If you execute a stored procedure that has a column that doesn’t exist, you’ll get an error
  2. How do you manage scripts that should only be run once? You don’t want to add the same field twice.

  3. Keeping code synchronized with the database changes

After some research and trial and error we fixed the first issue. I didn’t realize (since it isn’t documented anywhere that I could find) that the command file uses the script’s file extension to determine the order of scripts in the .cmd file. So it is important to name your files with the correct file extension.

The “Rules”:

  1. Table files with the .tab file extension
  2. Stored procedures with .prc
  3. Finally .sql files for all data modifications

The second problem, we fixed with a simple rule: “All scripts must be able to be run multiple times”. What this rule means is that if a script is going to add a column to the table, the script needs to check if the columns already exist before running. This rule also makes it possible to integrate our SQL changes into our nightly build process. This is great because we validate our scripts every night; schema changes, data, and security settings.

Third, we simply created a folder for each version of the software. Under each version folder we added a folder for each database. The database folders allow us to right click and “Create Command File…”.

How do you handle your database changes? I’m always interested in suggestions.

Saturday, September 17, 2005

Architecture and XP - Kent Beck's perspective

Two questions continually haunt with with Agile practices:

1.) How do you handle fixed bid/fixed scope projects without affecting quality?
2.) Where and when is the architecture defined?

In this article Kent Beck provides his perspective. Well worth the read.

"My experience with architecture shapes the architecture strategy in XP, I repeatedly ran into architectures that were developed up-front, without feedback, and by groups which didn't have to live with the day-by-day consequences of their decisions. What I observed about successful architectures was that they were grown little-by-little." - Kent Beck

http://www.theregister.co.uk/2005/09/11/beck_on_xp_architecture/

Thursday, September 15, 2005

First Iowa Agile Meeting, 9/22 @ 6PM


We'll have our first Iowa Agile meeting on Thursday, September 22, 2005 at 6:00 PM at Rock Bottom Brewery in West Des Moines.

Thanks to Kent McDonald for setting this up.