in

 

AgileJoe

Answering all world issues with, "...it depends..."

June 2007 - Posts

  • Introducing NUnit.Behave or insert what ever other catchy name

    OK I was bored yesterday and I decided to update what I had worked on the other day from Dan North's post on rbehave.

    Let look at my original attempt.

            [Test]
            public void Transfer_to_cash_account()
            {
                /*
                     As a savings account holder
                     I want to transfer money from my savings account
                     So that I can get cash easily from an ATM)
                 */
    
                Account savings = null;
                Account cash = null;
    
                Scenario("savings account is in credit");
                Given("my savings account balance is", 100,
                      delegate(int accountBallance)
                          {
                              savings = new Account(accountBallance);
                          });
    
                Given("my cash account balance is", 10,
                      delegate(int accountBallance)
                          {
                              cash = new Account(accountBallance);
                          });
    
                When("I transfer to cash account", 20,
                     delegate(int transferAmount)
                         {
                             savings.TransferTo(cash, transferAmount);
                         });
    
                Then("my savings account balance should be", 80,
                     delegate(int expectedBallance)
                         {
                             Assert.AreEqual(expectedBallance, savings.Ballance);
                         });
                Then("my cash account balance should be", 30,
                     delegate(int expectedBallance)
                         {
                             Assert.AreEqual(expectedBallance, cash.Ballance);
                         });
    
            }

    This will work but the delegates can get really old especially is you want to have several scenarios.  So I decided to use basially make a composite key out of the behavior and the message.  I then created a Hashtable to store the key with the corresponding delegate.  What does this allow me to do.  Well now I can write additional scenarios with out having to worry about the initial plumbing.  Observe.

            [Test]
            public void Transfer_to_cash_account()
            {
                /*
                     As a savings account holder
                     I want to transfer money from my savings account
                     So that I can get cash easily from an ATM)
                 */
    
                Account savings = null;
                Account cash = null;
    
                Scenario("savings account is in credit");
                Given("my savings account balance is", 100,
                      delegate(int accountBallance)
                          {
                              savings = new Account(accountBallance);
                          });
    
                Given("my cash account balance is", 10,
                      delegate(int accountBallance)
                          {
                              cash = new Account(accountBallance);
                          });
    
                When("I transfer to cash account", 20,
                     delegate(int transferAmount)
                         {
                             savings.TransferTo(cash, transferAmount);
                         });
    
                Then("my savings account balance should be", 80,
                     delegate(int expectedBallance)
                         {
                             Assert.AreEqual(expectedBallance, savings.Ballance);
                         });
                Then("my cash account balance should be", 30,
                     delegate(int expectedBallance)
                         {
                             Assert.AreEqual(expectedBallance, cash.Ballance);
                         });
                
                Given("my savings account balance is", 400);
                Given("my cash account balance is", 100);
                When("I transfer to cash account", 100);
                Then("my savings account balance should be", 300);
                Then("my cash account balance should be", 200);
    
            }

    Much nicer but then I didn't like how it read so I created a template pattern that would allow the Given, When, Then methods to return a conjunction type that would allow me to write more readable scenarios. For instance:

                Given("my savings account balance is", 500)
                    .And("my cash account balance is", 20)
                    .When("I transfer to cash account", 30)
                    .Then("my savings account balance should be", 470)
                    .And("my cash account balance should be", 50);
    
    
                Scenario("savings account is overdrawn");
                Given("my savings account balance is", -20)
                    .And("my cash account balance is", 10)
                    .When("I transfer to cash account", 20)
                    .Then("my savings account balance should be", -20)
                    .And("my cash account balance should be", 10);

    Yup that's the ticket.  Now you can run the test from within NUnit and the test runner will produce the following output in the console.

    -----------------------------------------------------

    Scenario: savings account is in credit
    Given my savings account balance is: 100
    And my cash account balance is: 10
    When I transfer to cash account: 20
    Then my savings account balance should be: 80
    And my cash account balance should be: 30

    Scenario: savings account is in credit
    Given my savings account balance is: 400
    And my cash account balance is: 100
    When I transfer to cash account: 100
    Then my savings account balance should be: 300
    And my cash account balance should be: 200

    Scenario: savings account is in credit
    Given my savings account balance is: 500
    And my cash account balance is: 20
    When I transfer to cash account: 30
    Then my savings account balance should be: 470
    And my cash account balance should be: 50

    Scenario: savings account is overdrawn
    Given my savings account balance is: -20
    And my cash account balance is: 10
    When I transfer to cash account: 20
    Then my savings account balance should be: -20
    And my cash account balance should be: 10
    -----------------------------------------------------

     

    As you can see the message heap evaluates for redundant actions ("Given" "Given") and replaces the second instance with "And" making the output much more readable.

    Here is the entire test fixture.

    using NUnit.Behave;
    using NUnit.Framework;
    
    namespace BehavioralExample
    {
        public class Account_Specs : BehavioralFixture
        {
            [Test]
            public void Transfer_to_cash_account()
            {
                /*
                     As a savings account holder
                     I want to transfer money from my savings account
                     So that I can get cash easily from an ATM)
                 */
    
                Account savings = null;
                Account cash = null;
    
                Scenario("savings account is in credit");
                Given("my savings account balance is", 100,
                      delegate(int accountBallance)
                          {
                              savings = new Account(accountBallance);
                          });
    
                Given("my cash account balance is", 10,
                      delegate(int accountBallance)
                          {
                              cash = new Account(accountBallance);
                          });
    
                When("I transfer to cash account", 20,
                     delegate(int transferAmount)
                         {
                             savings.TransferTo(cash, transferAmount);
                         });
    
                Then("my savings account balance should be", 80,
                     delegate(int expectedBallance)
                         {
                             Assert.AreEqual(expectedBallance, savings.Ballance);
                         });
                Then("my cash account balance should be", 30,
                     delegate(int expectedBallance)
                         {
                             Assert.AreEqual(expectedBallance, cash.Ballance);
                         });
    
                Given("my savings account balance is", 400);
                Given("my cash account balance is", 100);
                When("I transfer to cash account", 100);
                Then("my savings account balance should be", 300);
                Then("my cash account balance should be", 200);
    
                Given("my savings account balance is", 500)
                    .And("my cash account balance is", 20)
                    .When("I transfer to cash account", 30)
                    .Then("my savings account balance should be", 470)
                    .And("my cash account balance should be", 50);
    
    
                Scenario("savings account is overdrawn");
                Given("my savings account balance is", -20)
                    .And("my cash account balance is", 10)
                    .When("I transfer to cash account", 20)
                    .Then("my savings account balance should be", -20)
                    .And("my cash account balance should be", 10);
            }
        }
    }
    
    public class Account
    {
        private int accountBallance;
    
        public Account(int accountBallance)
        {
            this.accountBallance = accountBallance;
        }
    
        public int Ballance
        {
            get { return accountBallance; }
            set { accountBallance = value; }
        }
    
        public void TransferTo(Account account, int amount)
        {
            if (accountBallance > 0)
            {
                account.Ballance = account.Ballance + amount;
                Ballance = Ballance - amount;
            }
        }
    }

    I am uploading the code to Google code and should have it ready shortly.  Just having trouble with Ankh and Tortoise. 

    I am not to crazy about inheriting an abstract class as Scott Bellware mentioned but I just can't seem to get around it since C# is not a dynamic language.  Let me know what you all think?  Am I on the right track?  Either way I am having fun coding!

    You can download the code from the following link:

    http://code.google.com/p/nunitbehave/source

  • Dependency Patterns

    Scott Bellware has an excellent post on dependency injection patterns.  By far this has been a concept that I struggle with in explaining to other developers.

    When I first heard of frameworks such as Sprint.Net, Windsor, StructureMap, it took me a while to grasp their usefulness.  I simply saw them as a strategy for making testing easier.  I had know idea the benefit they would lend to my architecture.  The ability for an IoC container to resolve my dependencies automatically, simply from a configuration file is genius. 

    The difficult part is wrapping your head around the intended behavior of the "transparent" dependency.  As you inject a transparent dependency into class, you must expect it to behave a certain way when the consuming class acts upon it.  By using Mock objects in place of the physical dependent class you can evolve an interfaces intention upon the acting class through proper TDD testing. I know, I know show us the code.  I will, just really busy right now with work!  I struggle to find how Ayende is able to find the time in the day to work and blog.  I am truly not a blog Jedi yet.

    I posed the following question to Scott as a joke but he gave and excellent response.

    " I was wondering what a property injection would be called. Perhaps “Translucent Dependency” "

    Scott's reply

    "Joe,

    Property injection is still a transparent dependency.  Properties are typically used for lessor and infrastructural dependencies, like logging, if they're used at all.

    They're good for the things that don't have to do with the class's main concern. The dependencies that are property-injected would muddy the constructor signature with ancillary plumbing and cloud the principal purpose of creating an instance of the class.

    If the dependency isn't something that's key to solving the concrete business scenario that the class serves, it likely shouldn't be a constructor argument.  By making it a property, it can still be assigned (like an instance of ILogger, for example), but it doesn't obscure the primal intension of an instance.

    Setter dependencies are optional.  Their types should have a Null Object pattern implementation, and if not it's often a good idea to decorate them with one.  For example, if an optional dependency hasn't been set, it might not be desirable to have a null reference exception when a method is invoked on it.  Optional dependencies reserve the right to not be assigned to by the very nature of them not being mandatory or primal constructor arguments."

  • Behavior Driven Design with NUnit User Group Presentation - Level 100

    I recently gave a presentation on Behavior Driven Design at the AlamoCoders user group here in San Antonio.

    Given the hour constraint I had and the level 100 rating of the presentation, I was pressed to deliver the absolute essentials to get someone up and running with BDD.

    One of the more challenging aspects of presenting an entry level BDD presentation is the fact that you have to assume that some people have no exposure to any XUnit type development.  The founding principles of TDD (Red, Green, Refactor) must be reiterated before diving into BDD.  Once we got passed just what TDD is, the transition to BDD went much more smoothly then I had ever hoped.

    If you are interested I have uploaded the presentation and the source to the Los Techies downloads library.

  • RBehave with NUnit

    I just read Dan North's article on Introducing RBehave.

    In a jealous rage of not being able to utilize Ruby fully in .Net. (YET)  I decided to see if I could pull off what Dan had created in rbehave using NUnit.  Because I am a huge proponent of reuse, I didn't want to extend my existing Test Coverage with a brand new framework.  After all BDD coupled with ReSharper and Visual Studio make for happy testing. 

    Now before I have the entire TDD community up in arms with what I am about to propose this is merely a pattern for the porting of rbehave to NUnit without having to invest in a whole new framework.

    I would like to reiterate Dan's vision of what rbehave is intended to be.

    "rbehave is a framework for defining and executing application requirements. Using the vocabulary of behaviour-driven development, you define a feature in terms of a Story with Scenarios that describe how the feature behaves. Using a minimum of syntax (a few “quotes” mostly), this becomes an executable and self-describing requirements document."

    Now here is Ruby code for using rbehave:

    require ‘rubygems’
    require ‘rbehave’
    require ’spec’ # for "should" method

    require ‘account’ # the actual application code

    Story "transfer to cash account",
    %(As a savings account holder
      I want to transfer money from my savings account
      So that I can get cash easily from an ATM) do

      Scenario "savings account is in credit" do
        Given "my savings account balance is", 100 do |balance|
          @savings_account = Account.new(balance)
        end
        Given "my cash account balance is", 10 do |balance|
          @cash_account = Account.new(balance)
        end
        When "I transfer", 20 do |amount|
          @savings_account.transfer_to(@cash_account, amount)
        end
        Then "my savings account balance should be", 80 do |expected_amount|
          @savings_account.balance.should == expected_amount
        end
        Then "my cash account balance should be", 30 do |expected_amount|
          @cash_account.balance.should == expected_amount
        end
      end

      Scenario "savings account is overdrawn" do
        Given "my savings account balance is", -20
        Given "my cash account balance is", 10
        When "I transfer", 20
        Then "my savings account balance should be", -20
        Then "my cash account balance should be", 10
      end
    end

     So I needed a way to capture the story concept using NUnit.  I figured why not use the class text fixture attribute.

    NUnit Syntax
        public class Transfer_to_cash_account : NBehaveAbstractFixture
        {
            /*
             As a savings account holder
             I want to transfer money from my savings account
             So that I can get cash easily from an ATM)
             */

    }

    RBehave Syntax Story "transfer to cash account",
    %(As a savings account holder
      I want to transfer money from my savings account
      So that I can get cash easily from an ATM) do

    As you can see the story "transfer to cash account" is the name of the public class Transfer_to_cash_account.  As I am sure you all noticed the [TestFixture] attribute is missing but you will also notice that the Transfer_to_cash_account class inherits from NBehaveAbstractFixture, more on this later.  Lets talk about the real meat here, the "Given" "When" "Then" constructs.

    NUnit
    Syntax
            [Test]
            public void savings_account_is_in_credit()
            {
                Account savings = null;
                Account cash = null;
    
                Given("my savings account balance is", 100,
                    delegate(int accountBallance)
                    {
                        savings = new Account(accountBallance);
                    });
    
                Given("my cash account balance is", 10,
                    delegate(int accountBallance)
                    {
                        cash = new Account(accountBallance);
                    });
    
                When("I transfer", 20,
                    delegate(int transferAmount)
                    {
                        savings.TransferTo(cash, transferAmount);
                    });
    
                Then("my savings account balance should be", 100,
                    delegate(int expectedBallance)
                    {
                        Assert.AreEqual(expectedBallance, savings.Ballance);
                    });
    
            }
    RBehave Syntax   Scenario "savings account is in credit" do
        Given "my savings account balance is", 100 do |balance|
          @savings_account = Account.new(balance)
        end
        Given "my cash account balance is", 10 do |balance|
          @cash_account = Account.new(balance)
        end
        When "I transfer", 20 do |amount|
          @savings_account.transfer_to(@cash_account, amount)
        end
        Then "my savings account balance should be", 80 do |expected_amount|
          @savings_account.balance.should == expected_amount
        end
        Then "my cash account balance should be", 30 do |expected_amount|
          @cash_account.balance.should == expected_amount
        end
      end

    I have intentionally left the account assertion at 100 so it will generate the following stack trace.

    System.ArgumentException: 
    -Behavior Heap-
    Given my savings account balance is: 100
    Given my cash account balance is: 10
    When I transfer: 20
    Then my savings account balance should be: 100
    

    at AlamoCoders.BDD.Domain.Specs.NBehaveAbstractFixture.Then[T](String message, T actionValue, action`1 delegateAction) in NBehaveAbstractFixture.cs:line 59
    at AlamoCoders.BDD.Domain.Account_Specs.Transfer_to_cash_account.savings_account_is_in_credit() in RBehave.cs:line 40
    NUnit.Framework.AssertionException:   Expected: 100
      But was:  80
    

    The magic is in the anonymous generic delegate.  Rather than tell you how this works let me show you.  Here is the code for the the NBehaveAbstractFixture.

    using System;
    using System.Collections.Generic;
    using System.Text;
    using NUnit.Framework;
    
    namespace AlamoCoders.BDD.Domain.Specs
    {
        [TestFixture]
        public class NBehaveAbstractFixture
        {
            private string messageHeap;
    
            protected delegate void action<T>(T value);
    
            [SetUp]
            protected virtual void SetUp()
            {
                messageHeap = "\r\n-Behavior Heap-\r\n";
            }
    
            [TearDown]
            protected virtual void TearDown()
            {
                messageHeap = string.Empty;
            }
    
            protected void When<T>(string message, T actionValue, action<T> delegateAction)
            {
                try
                {
                    InvokeDelegateAction("When", actionValue, delegateAction, message);
                }
                catch (Exception e)
                {
                    throw BehaviorException("When", actionValue, e, message);
                }
            }
    
            protected void Given<T>(string message, T actionValue, action<T> delegateAction)
            {
                try
                {
                    InvokeDelegateAction("Given", actionValue, delegateAction, message);
                }
                catch (Exception e)
                {
                    throw BehaviorException("Given", actionValue, e, message);
                }
            }
    
            protected void Then<T>(string message, T actionValue, action<T> delegateAction)
            {
                try
                {
                    InvokeDelegateAction("Then", actionValue, delegateAction, message);
                }
                catch (Exception e)
                {
                    throw BehaviorException("Then", actionValue, e, message);
                }
            }
    
            private void InvokeDelegateAction<T>(string methodBehavior, T actionValue, action<T> delegateAction, string message)
            {
                delegateAction(actionValue);
                AddMessageToMessageHeap(actionValue, message, methodBehavior);
            }
    
            private ArgumentException BehaviorException<T>(string methodBehavior, T actionValue, Exception e, string message)
            {
                AddMessageToMessageHeap(actionValue, message, methodBehavior);
                return new ArgumentException(messageHeap, e);
            }
    
            private void AddMessageToMessageHeap<T>(T actionValue, string message, string methodBehavior)
            {
                messageHeap += string.Format("{0} {1}: {2}\r\n", methodBehavior, message, actionValue);
            }
        }
    }
    

    As you can see this is very crude but it works!  Let me know what you think.

  • Wife 1.0

    I got his in an email this morning and I just had to share this.  I am sure it has been proliferated through the SPAM network I mean Internet but who I am to slow innovation.  Enjoy

    Subject: wife 1.0

    Dear Tech Support:

    Last year I upgraded from Girlfriend 7.0 to Wife 1.0. I soon noticed

    that

    the new program began unexpected child processing that took up a lot of space and valuable resources.

    In addition, Wife 1.0 installed itself into all other programs and now monitors all other system activities, such as Poker Night 10.3, Football 5.0, Going To The Pub 7.5, and Softball 3.6

    I can't seem to keep Wife 1.0 in the background while attempting to run my other favorite applications. I'm thinking about going back to Girlfriend

    7.0 , but the uninstall doesn't work on Wife 1.0.

    Please help!

    Thanks,

    Troubled User.....

    _____________________

    REPLY:

    Dear Troubled User:

    This is a very common problem that men often complain about.

    Many people upgrade from Girlfriend 7.0 to Wife 1.0, thinking that it is

    just a Utilities and Entertainment program. Wife 1.0 is an OPERATING

    SYSTEM and is designed by its Creator to run EVERYTHING!!! It is also impossible to delete Wife 1.0 and to return to Girlfriend 7.0 . It is impossible to uninstall, or purge, the program files from the system once installed.

    You cannot go back to Girlfriend 7.0 because Wife 1.0 is designed to not allow this. Look in your Wife 1.0 manual under Warnings: Alimony-Child Support . I recommend that you keep Wife 1.0 and work on improving the situation. I suggest installing the background application Yes Dear 2.7 to alleviate your program problems.

    The best course of action is to enter the command C:\APOLOGIZE! because ultimately you will have to give the APOLOGIZE command before the system will return to normal anyway.

    Wife 1.0 is a great program, but it tends to be very high maintenance!

    Wife

    1.0 does come with several support programs, such as Clean and Sweep 3.0, Cook It 1.5, and Do Bills 4.2

    However, be very careful how you use these programs. Improper use will cause the system to launch the program Nag Nag 9.5 . Once this happens, the only way to improve the performance of Wife 1.0 is to purchase additional software. I recommend Flowers 2.1 and Diamonds 5.0

    WARNING!!! DO NOT, under any circumstances, install Secretary With Short Skirt 3.3 . This application is not supported by Wife 1.0 and will cause irreversible damage to the operating system!

    Best of luck,

    Tech Support

    Posted Jun 11 2007, 10:23 AM by Joe Ocampo with no comments
    Filed under:
Copyright Los Techies 2007. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems