May 2 2007

How to make unit tests transactional in TFS

Category: Selfish MotivationJoeGeeky @ 17:01

At some point, all good developers make the realization that Unit Testing is not evil and is the best way to ensure your code works as you expect it to. With that said, the moment you start writing tests for methods that interact with a database you start to run into some really unique problems that can lead to a lot of unneeded code. 

Generally speaking you always want to leave the system as you found it when testing started. That means that any data you add/edit/delete during the test needs to be restored when the test has concluded.  For the longest time I would spend my time writing test rigs to manage all these functions for each data method being tested.  It didn't take me long to realize that this was a waste of time and that there had to be a way to make this easier.

With that in mind  I set out to make my unit tests transactional since transactions have rollback support. Stealing a trick from the COM world I was able to find a way to make my test transactional. Here is what you need to do. As I go though this, keep in mind that I am using TFS Unit Tests run against a Microsoft SQL Server. This same technique can be used with other technologies (Ex. NUnit) although the syntax will be different.

One last note... If you look at the line "config.TransactionTimeout = 900", this may seem like a really long time. This is set to this length to ensure you have plenty of time to step through code during tests. Adjust this as needed.

Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports System
Imports System.Configuration
Imports System.EnterpriseServices

''' <summary>
''' Abstract class defining a transactional baseline for database driven unit tests
''' </summary>
<TestClass()> _
Public MustInherit Class DatabaseTransactionTestClass
    ''' <summary>
    ''' Hold a defined in progress transaction
    ''' </summary>
    Private TestTransactionScope As TransactionScope
    ''' <summary>
    ''' Init method to setup transaction requirements
    ''' </summary>
    <ClassInitialize()> _
    Public Shared Sub TransactionSetup(ByVal testContext As TestContext)
        Dim config As ServiceConfig = New ServiceConfig()
        config.Transaction = TransactionOption.RequiresNew
        config.TransactionTimeout = 900
        config.IsolationLevel = TransactionIsolationLevel.RepeatableRead
        ServiceDomain.Enter(config)
    End Sub
    ''' <summary>
    ''' Cleanup method to roll-back all database changes
    ''' </summary>
    <ClassCleanup()> _
    Public Shared Sub TransactionTearDown()
        RollbackTransaction()
        ServiceDomain.Leave()
    End Sub
    ''' <summary>
    ''' Init method to define the start of a transaction on a per-test basis 
    ''' </summary>
    <TestInitialize()> _
    Public Sub TestSetup()
        TestTransactionScope = New TransactionScope
    End Sub
    ''' <summary>
    ''' Cleanup method to close and abort the transaction
    ''' </summary>
    <TestCleanup()> _
    Public Sub TestCleanup()
        If Not TestTransactionScope Is Nothing Then
            TestTransactionScope.Dispose()
        End If
    End Sub
    ''' <summary>
    ''' Rolls back and existing test level transactions as defined by the TestTransactionScope
    ''' </summary>
    Public Shared Sub RollbackTransaction()
        If ContextUtil.IsInTransaction Then
            ContextUtil.SetAbort()
        End If
    End Sub
End Class

Tags: ,

Apr 15 2007

Reusable Test Rigs are your friend

Category: Selfish MotivationJoeGeeky @ 06:10

I am not really sure how many unit tests I have written in my life, but on my current project I have written more then a 1000 over that last few months. One of the things I learned a long time ago is that code should only be written when it needs to because you usually need to time to do more important things, like working with customers, designing your product, architectural planning, and most importantly being with your family. One practice that can really speed things along is to write a common, reusable, late-bound, test rig. Think about it... How many times have you written a property test to see if you are setting a String value correctly, a Boolean flag, Enum, Date, etc... Honestly, how many times do you really need to write that code?

Click below to see some simple examples of reusable test rigs for thigs like string, boolean, enum, and object test rigs

samplegenerictestrigs.htm (20.75 kb)

When you are designing your test rigs keep the following in mind

  • Keep things as generic and reusable as possible
  • Consider using a late-bound approach which can provide a lot of flexibility
  • Reflect, Reflect, Reflect...  Reflection technologies can really help you write code that can adapt to the objects being passed to the rigs.

Once you have your test rigs you will find that for common testing tasks, your tests will become a lot shorter and easier to write.

    '''<summary>
    '''A test for UserAgent()
    '''</summary>
    <TestMethod()> _
    Public Sub UserAgentTest()
        Dim target As NewMyClass
        GenericTestRigs.GenericStringPropertyTest(target, "UserAgent", "123", "", True)
    End Sub

As a side note, for those of you implementing CSLA-like architectures this will also allow your to encapsulate richer testing threshholds like management of overall object state, dirty flags, etc...

Tags: ,

Apr 30 2006

Automatic Code Generation, Code that writes itself!

Category: Selfish MotivationJoeGeeky @ 01:02

Billy Hollis once said that developers have an addiction... Writing code... After much sole searching and a little Freudian introspection, I realized that I was a code addict. Having faced my demon, I set out to address my addiction head-on.  What was the answer? Simple… write code that writes itself. 

As usual Microsoft was thinking ahead, and provided us with a very powerful .NET namespace containing tons of great classes to facilitate this process. That namespace is System.CodeDom…

Consider for a moment, how many times you’ve had to produce an information class filled with public properties and their private members. This is tedious work and really doesn’t lend itself to making you a better programmer. Like the first step in a 10-step program, my first application was geared towards making this portion of my job obsolete, allowing me to provide basic property information in a language neutral short-hand and then producing a complete code set in the language of my choice. I don’t normally post my code but this is something that more developers need to explore. To that end, the below links are provided to help proliferate this type of practice… 

Thanks Billy, you saved my soul….

Joes Property Code Generator - Binaries.zip (19.49 kb)

Joes Property Code Generator - VS 2K5 Source Code.zip (26.81 kb)

Note: You must have both the .NET Runtime and the J# 2.0 Runtime installed to use this.

Tags: ,

Jan 16 2006

My Windows Cleaner

Category: Selfish MotivationJoeGeeky @ 12:49

During my time as a systems integrator I found myself manually cleaning out system refuge prior to every system delivery. This is an extremely tedious process that can really eat up a lot of time. With no shortage of things to do, I needed to get a little selfish and make an app to deal with this. Enter, the Windows Cleaner… A nifty little .NET application that is extensible for my fellow integrators. For this project I even created a little SDK that added a cleaner module project type to Microsoft Visual Studio.NET allowing developers to easily create new/custom cleaner modules. As a side note, if you are not aware of the VS.NET extensibility model, then you really need to look in to that.  Ahhh…  you have to love the little things in life…  Why not just buy a commercial product?...  Ummm... have you not been paying attention?  I'm a GEEK and this is free!

BTW, if you want something like this for use at home, I recommend Windows Washer from Webroot.

Application Screen Capture

Tags:

Dec 15 2005

Audit Assistant

Category: Selfish MotivationJoeGeeky @ 23:16

This one was a lot of fun... We needed something to help audit our systems. On the surface a simple task, but this is one of those cases when one thing leads to another and pretty soon you’re on your way to developing enterprise services (boggle). There are a lot of nifty features here, but since this is for the geeks in the house, this included tons of owner-drawn stuff using GDI+ and more brute-force pagination than I ever want to repeat again :-)... To round things out, are sprinkles of XML/XSD, serialization, interoperability with the Windows Instrumentation Engine, SOA based services, and a partridge in a pear tree. This also gave me a chance to explore some IUI concepts in human engineering and process automation. Although I developed this on my own time this has gotten some attention and may grow up to be something larger in the future.

Tags:

Dec 2 2005

processMonkey

Category: Selfish MotivationJoeGeeky @ 03:22

This is another case where 'sometimes' the best solution is the one you create yourself. In this scenario, I was faced with the crippling process of gathering and analyzing metrics for our SW-CMM initiatives. After doing this by hand a few times I realized that I had to find a way to automate the process and define more objective measuring criteria for the team. Here is where the geek part comes in... All of the data was stuck in a proprietary portal engine that had no 'advertised' interfaces... 'They' said I was only allowed to view content via the browser. You know 'They', because we all work for 'Them'. There are those of us who understand what we do not manage, which is often managed by those that do not understand what 'They' manage... Got it?... Good!... Ok, I will play... In this application I embedded a number of browsers and created bots that would crawl through the portal, scrape the data out, normalize it, model it, cache it, and then apply it to a charting engine I developed for the font-end. This process was eventually relagated to a server-based product with a service layer allowing access to scraped data by clients.  One thing led to another, and I found myself integrating with Microsoft Outlook, implementing full-screen briefing support, chart image capturing and extraction, and the aforementioned implemention of a service oriented layer to support multiple client access. Ok... A little out of control?... Maybe... but it made my job; in this area; super easy and I had a lot fun working with the embedded browsers, DOMs, bot methods, service layers, owner-drawn charting, etc. Hey, it’s a geek thing...  :-)

As a side note...  Sadly...  Sometimes I find that I am one of 'Them', ohhh the horror!  Nevermind, it comes with a pay raise...  :-)

Tags:

Nov 11 2005

MD5 Calculator Add-in for Visual Studio.NET

Category: Selfish MotivationJoeGeeky @ 11:35

Got an email one day that said, '...all files that must be audited, shall be submitted with an MD5 signature...'. Hmmm, what to do then? I could (a) use an external product to calculate the signature, transfer them to a file and email the file to all the interested parties or (b) do the geek thing and write an app to do it for me... Duhhh, I have to do the geek thing. In this case, I explored the VS.NET Extensibility Framework. If you have not used this before it is worth investigating. This little gem stays out of site and out of mind, silently calculating MD5 signatures for all the compiled elements of your project, and drops an XML file with all the details in your project directory updating it when you recompile. Add this artifact to your source repository and you can find your file signatures quick and easy. I added a search module in the aforementioned audit tool that could perform audits based on this output file. Ahhh, I love it when a plan comes together.

Tags:

Oct 10 2005

AutoMailer.NET

Category: Selfish MotivationJoeGeeky @ 19:37

One day, an acquaintance of mine said... "I sure wish I could schedule emails to be sent on a recurring basis". Hey, I'm a nice guy and little bit of a sucker... so I dove in on my own time and wrote a little program for him. In this case, I explored the Windows Service development Framework in .NET, Explorer pane implementations, a templating/variables engine, a recurrence scheduler, spell-checker, MS Outlook integration, as well as socket-based communications to send mail messages via SMTP. After all that, wouldn't you know it... He changed his mind and said... "But I want my existing mail program to do it" I know!... I know!...  users NEVER change their requirements. It's ok though, I love using this thing and he can bite me.  :-) 

Tags:

Sep 22 2005

Joe's Simple Port Scanner

Category: Selfish MotivationJoeGeeky @ 16:39

One day, a friend came to me and asked how to scan a TCP or UDP port.  With that question, I wrote a simple little port scanner to demonstrate at least one approach to the problem. Once written I found out that it wasn't one port but thousands. Well, now it is time for some metrics... As it turns out, my little sample took 2 minutes and 5 seconds to scan 1024 ports. While it worked, it needed to be faster.  After scratching my head a bit, I wrote a new port scanner that performed scans on a pool of threads.  Now it scanned the same port range in 2.2 seconds. What can I say, multithreading is groovy stuff.  :-)

 

Tags: