Archive

Archive for the ‘Unit Testing’ Category

Authorize.Net Code Release

September 29, 2008 6 comments

Back in February I posted the beginnings of a project to wrap Authorize.Net credit card transactions in C# .NET code. I have been working on this project off and on, in conjunction with a new website we are developing, and have been meaning to post the production version for some time.

Today, I am publishing the current version of the code, DevelopingForDotNet.AuthorizeNet, along with a few supporting updates. I’d like to thank everyone who posted comments on that entry and the First Foray into Unit Testing entry. Most of those suggestions made it into the final version and I learned a lot about Unit Testing along the way.

This version is slightly different than the original post. Here are the major differences:

Validity Checking

This version incorporates validity checking on the following TransactionRequest class properties:

  • EMail
  • Zip
  • SecurityCode
  • CardNumber
  • ExpDate

EMail, CardNumber, and ExpDate validation have been completely rewritten.

ExpDate now accepts the following formats:

  • MMYY
  • MM/YY
  • MM-YY
  • MMYYYY
  • MM/YYYY
  • MM-YYYY

The Validity Checking uses a set of Regular Expression patterns that I have put into another namespace, DevelopingForDotNet.RegexSupport. It will be available on the Free Code page as well.

Right now, all the failures throw an ArgumentException, which is very heavy handed but I haven’t had a need to improve it yet.

INotifyPropertyChanged

Each of the three classes implements INotifyPropertyChanged so you can use them for data binding if you wish. If you have never implemented this interface before, it is very easy. Add a reference to System.ComponentModel to your code. Then add the inheritance statement to your class:

public class TransactionRequestInfo : INotifyPropertyChanged
{
    ...
}

Then implement the PropertyChangedEventHandler and add a method to fire the event:

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Then call the method whenever a property changes:

public string FirstName
{
    get { return _first; }
    set
    {
        _first = value;
        OnPropertyChanged("FirstName");
    }
}

Easy as can be!

Transaction.ProcessPayment

Transaction is a static class with ProcessPayment as its single static method. In reviewing the project, I realized that this was a perfect case for an Extension Method, so I added this before the first keyword, and now calling the method is even nicer than before:

// Account is built above...
TransactionResponseInfo pmtResponse = pmtInfo.ProcessPayment(Account);

Unit Testing

I really got my feet wet with Unit Testing on this project. I followed the advice I got from FreekShow and implemented the testing of Exceptions in a much cleaner fashion. The whole experience got me thinking about why Unit Testing is so beneficial, and as I began rewriting the code I started by writing tests that fail first and then coding my way into success. Just for grins, the testing project for this solution is included in the download.

First Foray into Unit Testing with Visual Studio 2008

June 12, 2008 12 comments

I’ve read about Unit Testing and Test Driven Development (TDD) but have never attempted to use it or even really understand it. I recently became intrigued by it watching Rob Conery’s excellent video series. Today I began putting the final touches on the Authorize.Net code I am going to release, so I thought this would be a good opportunity to try some testing.

I have never done any Unit Testing, and even though I wasn’t sure where to start, I figured it out pretty quickly. First things first, I added a Test Project to my solution. This created all the necessary framework code as one might expect. I deleted the default TestMethod and began adding TestMethods of my own, intuitively marked with the [TestMethod] attribute. A little Google hopping and I quickly learned about Assert.xxx() methods.

When it came time to actually run the tests, I was a little stumped. I read where you could right click the method name and execute “Run Tests”, but it seems to only run one at a time. In the test results window, there is a button for “Run All test”, but it too only ran the last executed test. Finally, I changed the Test project to my Solution Start Project, and pressing F5 to execute will run all the tests.

Here is the code from my first stab at it:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DevelopingForDotNet.AuthorizeNet;

namespace TestAuthorizeNet
{
    ///
    /// Summary description for UnitTest1
    ///
    [TestClass]
    public class UnitTest1
    {
        public UnitTest1()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        ///
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void TestCreditCardNumberWithCharactersConvertedToJustNumbers()
        {
            TransactionRequestInfo req = new TransactionRequestInfo();
            string testValue = "1234-5678-9012-3456";
            req.CardNumber = testValue;
            Assert.AreEqual("1234567890123456", req.CardNumber);
        }

        [TestMethod]
        public void TestZipCodeNotNumericThrowsArgumentException()
        {
            TransactionRequestInfo req = new TransactionRequestInfo();
            string testValue = "034JB";
            try
            {
                req.Zip = testValue;
                Assert.Fail("Exception not thrown.");
            }
            catch (ArgumentException aex)
            {
                Assert.IsTrue(true, "Exception Thrown Properly");
            }
        }

        [TestMethod]
        public void TestZipCodeNumericButGreaterThan99999()
        {
            TransactionRequestInfo req = new TransactionRequestInfo();
            string testValue = "58634789";
            try
            {
                req.Zip = testValue;
                Assert.Fail("Exception not thrown.");
            }
            catch (ArgumentException aex)
            {
                Assert.IsTrue(true, "Exception Thrown Properly");
            }
        }

        [TestMethod]
        public void TestZipCodeValidReturnsLeadingZeros()
        {
            TransactionRequestInfo req = new TransactionRequestInfo();
            string testValue = "586";
            req.Zip = testValue;
            Assert.AreEqual("00586", req.Zip);
        }
    }
}

A few notes worth mentioning:

  1. I found a bunch of sites that talked about Testing in Visual Studio, about half and half claiming it was a good thing. What I did not find so readily was a good tutorial. I did finally come across a good post at http://www.geekzone.co.nz/vs2008/4819, a blog I had never visited before.
  2. What I have done so far would certainly not qualify as TDD, I’m just experimenting at this phase. I did, however, try to write tests that failed before correcting them to pass, but they were all on pre-existing methods.
  3. I tried to follow the “use long, descriptive test method names” rule.
  4. I need to understand mocking. Right now, I am creating full fledged class instances.
  5. It seems a tad slow. I can’t imagine what this would be like with hundreds of tests to run. I’m sure there are ways to handle this issue.

My plan is to include the test Project along with the entire Authorize.Net Solution. Whether it will be helpful or not, I don’t really know.

Follow

Get every new post delivered to your Inbox.