Convex Corners

2009/06/27

Using Moq / Mocking to flesh out interfaces

Filed under: Agile, TDD, blush — neil martin @ 1:55 pm

What are we doing here ?

One of the techniques i like to use when driving out specifications underneath BDD tests (to be clear we are  now talking about being down near the steal under your top level behaviour tests, not at the level of traditional unit tests but hovering some place in-between).

I generally don’t want to get tied up in implementation of anything other than the most simple types so i use Moq to help me out and i use a technique i refer to as coding deep and mocking wide.

So what do we get for our story points ?

Ok so very quickly we start to see a object model get introduced , via interface we delay implementation of the concrete till we absolutely have to build one therefore the cost of change is very small. This really helps when working with emergent design and architecture principals. The other plus point is we maintain high test coverage of our code base.

There are two techniques in play here, one many people have talked about in depth across the web which we will call “Interaction based testing” , what do we mean by this is if i do this to my object i will verify that “ this “ “and this” “and this” has happened to my injected or dependent mock’s so in other words if we do this thing inside the object model i will test that these actions have been called as a result of my action.

The other technique is what i call “ Value based testing” doing this you wont generally validate something has been called but instead you will use the mocks more like stubs by doing this you get to hammer out your interfaces without having to worry about how you will supply the concrete functionality till you have no choice and you have been driven some place were stubs wont sensibly go.

Working this way allows use to cover a massive amount of surface foot print in terms of your application and to very cheaply and quickly test and implement your architectural and design assumptions within the code base. I’ve supplied a basic example below.

The Test

using Blush.Interfaces;
using Blush.Services;
using Blush.Types;
using Moq;
using Moq.Language.Flow;
using NBehave.Spec.NUnit;
using Context = NUnit.Framework.TestFixtureAttribute;
using Concerning = NUnit.Framework.CategoryAttribute;
using Specification = NUnit.Framework.TestAttribute;

namespace Blush.Tests.Services.Card
{
    [Context, Concerning("Card Service")]
    public class CardService_specs
    {
        [Specification]
        public void Should_be_able_to_get_all_cards_sorted_into_catergories()
        {
            const string catergory = "Waiting";
            var repository = new Mock<ICardRepository>();
            var waitingCatergoryMock = new Mock<ICardCatergory>();
            waitingCatergoryMock.SetupGet(c => c.Name).Returns(catergory);
            waitingCatergoryMock.SetupGet(c => c.Cards).Returns(new CardCollection
                                                                    {
                                                                        MockCard(catergory).Object,
                                                                        MockCard(catergory).Object,
                                                                        MockCard(catergory).Object,
                                                                        MockCard(catergory).Object,
                                                                      });
            repository.Setup(r => r.GetAll()).Returns(new CatergorisedCardCollection
                                                          {
                                                              waitingCatergoryMock.Object
                                                           });
            ICatergorisedCardCollection collection = repository.Object.GetAll();
            collection.Count.ShouldEqual(1);
            collection[0].Cards.Count.ShouldEqual(4);
            collection[0].Name = catergory;

        }

        private Mock<ICard> MockCard(string Catergory)
        {
            var mock = new Mock<ICard>();
            mock.SetupGet(c => c.Catergory).Returns(Catergory);
            return mock;
        }
    }
}

The product of the test

namespace Blush.Interfaces

{

public interfaceICardRepository

{

ICard AddCard(ICard card);

ICatergorisedCardCollection GetAll();

}

}

namespace Blush.Interfaces
{
    public interface ICardCatergory
    {
        ICardCollection Cards { get; set; }
        string Name { get; set; }
    }
}

This interface has been hammered out by other tests as well

using System;

namespace Blush.Interfaces
{
    public interface ICard
    {
        string Title { get; set; }
        string Body { get; set; }
        string EstimatedSize { get; set; }
        string CardState { get; set; }
        Guid Id { get; set; }
        string Catergory { get; set; }
    }
}

The types below were first hammered out as interfaces but other tests i had wrote forced me to make them concrete , so as i already have concrete implementations i made use of them here.

using System.Collections.Generic;
using Blush.Interfaces;

namespace Blush.Types
{
    public class CardCollection :List<ICard>, ICardCollection
    {
    }
}

using System.Collections.Generic;
using Blush.Interfaces;

namespace Blush.Tests.Services.Card
{
    public class CatergorisedCardCollection :List<ICardCatergory>, ICatergorisedCardCollection
    {
    }
}

Conclusion

It can be seen from this tiny example that we get a huge amount of bang for bucks by delaying worrying about the HOW we do something till the last possible moment and instead concentrating on expressing what we want to do.

Good Article On Ruby On Rails : Models and Associations

Filed under: Agile, ror — Tags: , , , — neil martin @ 9:15 am

My Learning continues

I came across this really cool post that makes models a simple concept here is the link : http://www.tutorialspoint.com/ruby-on-rails/rails-models.htm

Hope you find it as useful as i did

Neil

2009/06/26

Open invite to the agile .net practitioners – UK linked group

Filed under: Agile, TDD — neil martin @ 9:34 pm

Hi all

Bob has asked me to moderate a new UK group on linked in we are hoping to try to get some good discussions going about topics which perticulary effect Agile in the UK and Europe and also to use it as a nice place for people to give feed back and commentaries on user groups and conferences they have attended.

If you are intrested in Agile in UK / Europe please do come along and join and contribute.

We look forward to seeing you there.

The Group is named
agile .net practitioners – UK

If you have any problems finding it on linked in please drop me a email to bluef1sh@hotmail.co.uk or comment on this article and ill send you an invite.

This is a good opertunity to get your user group known , or even to propose setting one up for your area.

Kind regards

Neil Martin

Rails : Select Box

Filed under: Agile, ror, ruby — neil martin @ 2:03 pm

Excellent tutuorial on setting up a select box in a view both from hash and from a model.

http://shiningthrough.co.uk/blog/show/6

my learning continues.

neil

2009/06/25

Excellent top level article on cucumber

Filed under: Agile, TDD, ror, ruby — neil martin @ 9:23 pm

I found this on a linked in post , and i have to say as a top level introduction it is one of the better quality articles i have read you can find it here : http://www.engineyard.com/blog/2009/cucumber-introduction/

If you want a 10 min whistle stop tour of cucumber i recommend you have a read of this excellent post, to be frank this is what is missing form the rspec book that is currently in beta, which i have to say otherwise is excellent but it starts assuming you know to much, this article addresses the gap.

neil

Rabbit holes, being brave and safety lines.

Filed under: Agile, TDD — Tags: , , , , — neil martin @ 12:41 pm

So your test passes you have hammered out some code that is fit for purpose but that little voice inside is saying really that should be a Request & Response pattern or i should implement a flyweight pattern or some such and no amount of green bars are making you feel better.

So we all know the work pattern RGR (Red , Green , Refactor) and now we come to the 3rd element so you dive in and start making changes to domain model , you change a couple of helpers for an aggregated service and you push in a couple of factories  and your tests feel good and your feeling ok about life and all is sun shine and roses.

Your pair says id like to try putting in a messaging pattern and a view model  he says  ‘im really uncomfortable with the direct binding to the domain shapes from the view model were exposing stuff we really shouldn’t be’, your stomach flutters you get a cold shiver down your spine and you think yep but no one else has done that before i dont want to be the first in the team to attack that , sure we have talked about it and we have said lets sort it out when a pair hits it but did it have to be us!!

This sounds quite uncommon but in fact during a lot of retrospectives you hear similar tails people dont feel brave enough to attempt cross cutting refactors on shared code bases id like to talk a little about being brave.

I think as well its important to remember here in a true agile team there are no SUPER Stars every one is equal and if you were not good enough you wouldn’t be there in the first place.

Doctor , Doctor

Ok so first some health check style questions that you should ask yourself and if required your team the answers should help to empower you.

  • Are you working in a true agile environment does your team feel empowered to change code without having to go to a architect / lead hopefully you don’t even have those roles in your team ?
  • Is there an acceptance that its ok to try things and be wrong , and that everyone accepts that time trying a technique that in the scope of the requirements is not time wasted. ?
  • Is the quality of the code base excepted as being A. Important and B.  Attaining a higher quality code base is an encouraged activity  ?
  • You do have source control right , and you trust it ?
  • You and your team do regular checkins ?
  • The code you intend to touch is covered by either Unit or BDD tests ( if it isn’t perhaps your first action should be to write some functional boundary tests around it so you can have surety the behaviour of the new code matches the old code you are refactoring) ?
  • Is your pair happy with what you intent to do , do not proceed if you cant get ‘ buy in ‘ rather call a huddle with some or all of the team remember a huddle is a 15 min or so in place meeting where every one has a chance to share there views on a action , problem , or activity or perhaps it is a opportunity to knowledge share a cross cutting piece of information.
  • The team feel empowered enough to roll out someone’s changes , or to change someone’s code should the need arise ,in short you have fully empowered cross team code ownership.

If you are happy with the answers to these questions it time for you and your pair to be brave and to dive in.

So make your mark

So source control is your friend its really important that you have done the following before you start the refactoring exercise .

  • Do an update
  • Satisfy Merge sets
  • Rerun your tests make sure your all green
  • Check in and make sure you add notes about what you have done , remember people can see your change set you don’t need to tell them what you have changed just what you were trying to achieve , and a reference back to your requirement card your initials if working on a global pair station that isn’t using a personalised source control account.
  • Wait for your CI (cruise or whatever) to run and make sure your all green and clean across the board.

At this point depending on how big your change set is likely to be and upon your risk foot print and if your source control system supports it you might want to consider applying a label to the source your decision should also be governed by your team policy on labels, remember there is no shame in calling a quick huddle if you and your pair feel it will give you confidence to proceed.

So Lets make a start

TEST TEST and More TESTS :So as with all good Agile development be driven by test if you feel the refactoring you are doing needs a new piece, a factory or something of that nature write tests and be driven to the code you finally produce.

Its ok to be wrong :  Remember this is not an operation on someone’s life we do have take backs so if you find you have got it wrong and you have gone down a rabbit hole STOP , LOOK, LISTEN and THINK.

STOP : The moment you don’t feel comfortable your spidy sense is kicking off stop typing hands down push the keyboard away form you or get your pair to stop.

LOOK: Go back over what you have done pull up your change set since last checkin

LISTEN: Talk to your pair listen to what he has to say dont do anything till your both comfortable again and have a way forward.

THINK: Both of you take a flight up to 10,000 ft and make sure you are actually solving the problem you started out trying to solve, think about the whole picture not just the microscopic of the class your coding right at this moment follow the code path back look for deviation form task.

Ok having had a chin wag and a chat with your pair if your still not happy just rollback to your last good checkin dont be scared yes its a bit of wasted dev time you say but is it ?   You have discoved a rabbit hole you can now mark it in a huddle or post scrum meeting with a big red flag save someone else dropping into it. 

Be brave rollback , don’t push a bad position and risk the task.

IF your happy push on and at the next passing test or opportune moment where you wont break the build checkin.

Round up

Well ill just finish with a few guide lines:

  • Regular checkin
  • Don’t ignore broken build
  • Small change set
  • BE BRAVE
  • Use your source control dont be scared of it
  • Dont be afraid to speak up or ask for a huddle
  • Speak and listen to your pair
  • Above all have fun

2009/06/24

Sh#rp Architecture

Filed under: Agile — neil martin @ 5:12 pm

I was recently pointed towards an architectual framework which i feel warents further examination and although it would not be my first option for  alot of the work i do , i think it should be considered in the mix of alternatives when thinking about new projects , i then hunted out a top level introduction on the framework which can be found here: http://devlicio.us/blogs/billy_mccafferty/archive/2008/04/21/asp-net-mvc-best-practices-with-nhibernate-and-spring-net.aspx

Neil

2009/06/23

MVC ASP : Best Practises

Filed under: Agile — neil martin @ 12:47 pm

Fantastic article on ASP MVC best practises :http://blog.maartenballiauw.be/post/2009/05/06/More-ASPNET-MVC-Best-Practices.aspx i found a lot of helpfull infromation here.

Microsoft .net / CLR team want to know what you think

Filed under: Agile — neil martin @ 9:56 am

In case your RSS hasent picked it up microsoft are running a survey on this link http://dotnetfxperf2009.questionpro.com/ remember you cant complain about the product if you dont tell them whats wrong with it.

I would encourage everyone to go and submit your views these folks love there product and want to do an excellent job lets help them out.

neil

2009/06/20

Db4 Objects

Filed under: Agile — Tags: — neil martin @ 5:30 pm

The Db4Objects team have made semi breaking changes that don’t seem to have been fully reflected in the documentation . however this post out lines them : http://programing-fun.blogspot.com/2008/10/changes-in-db4o-configuration.html

2009/06/11

Mocking the Repository

Filed under: Agile, TDD, blush — Tags: , , — neil martin @ 11:54 am

I recently received an email asking me how i start to develop a service repository relationship so i decided to post a quick example using MOQ.

So straight to it here is the code for Unit style test i have been driven to write for the GetAll Operation on a repository that doesn’t exist yet in in process Service im still constructing.

The Test

using System.Collections.Generic;
using Blush.Interfaces;
using Blush.Services;
using Blush.Services.Repositories;
using Moq;
using NBehave.Spec.NUnit;
using Context = NUnit.Framework.TestFixtureAttribute;
using Concerning = NUnit.Framework.CategoryAttribute;
using Specification = NUnit.Framework.TestAttribute;

namespace Blush.Tests.Services.Card
{
    [Context, Concerning("Card Service")]
    public class CardService_specs
    {
        [Specification]
        public void Should_be_able_to_get_all_cards()
        {
            var repository = new Mock<ICardRepository>();
            repository.Setup(r => r.GetAll()).Returns(new List<ICard>
                                                          {
                                                              new Mock<ICard>().Object,
                                                              new Mock<ICard>().Object,
                                                              new Mock<ICard>().Object
                                                          });

            ICardService serviceUnderTest = new CardService(repository.Object);
            serviceUnderTest.GetAll().Count.ShouldEqual(3);
        }
    }

}
The Interface
using System.Collections.Generic;
using Blush.Interfaces;

namespace Blush.Services.Repositories
{
    public interface ICardRepository
    {
        IList<ICard> GetAll();
    }
}

I hope this helps. 
 

2009/06/04

This post is a response to : Linked in post Good apps ain’t cheap and cheap apps ain’t good

Filed under: Agile — neil martin @ 4:18 pm

The following post would not fit in linked in reply text box so i posted it here the link to the discussion is here: http://www.linkedin.com/groupAnswers?viewQuestionAndAnswers=&gid=37631&discussionID=3928317&commentID=4070342&trk=NUS_DIG_DISC_Q_ucg_mr&goback=.hom#commentID_4070342

I would like share some of the development style i have promoted in the past in terms of testing code  my  hope is it may open up this valuable discussion yet further.

Scenario : Iteration Zero

Setting the scene

When we enter into a iteration we will run a IPM { Iteration Planning Meeting } in that meeting we will play the shopping game or some variation and from that meeting a number of stories will be selected for the iteration, those stories will have been costed in story points and the corresponding cards will move into the waiting queue to be picked up by dev’s.

Enter stage right the developer pair, QA and BA.

The pair will pick up card let’s say “As a user i Expect to be able to register my details with the system”

The pair will then have a pre-card huddle with the QA and the BA where they will walk over the acceptance criteria and the QA will start to think about who they will test the exit criteria for the card and also will input any thoughts that didnt get expressed in the IPM about negative testing and edge cases these will then be re-wrote into the card and estimated if the estimate is massively effected the BA will make the call to either split the card or drop it fomr the iteration or except greeter risk within the iteration. As a group they will work through any questions they might have and finalize the acceptance statements together this might last 15 minutes or so.

Que Audio : Tapping fingers.

The pair will then set themselves up at a pair station and take a look at the first acceptance criteria and it could look something like this

Acceptance criteria 1 example 1

As a potential new User
Given that i am on the ‘Registration’ Page
I wish to enter the following information:
UserName , Text , 25 max , no symbols
Password ,Text , 6 char minimum, 20 char max , must have at least one number , must have at least 1 capital letter, Make them enter the password twice and check they match.
First Name  , Text ,255 max
Second Name , Text ,255 max
Date Of Birth , Text , 255 max
Email Address , Text ,100 max
When i have filled in this information i Then press create user and i Expect the following:
An email confirmation with my username and password follow lnk ‘X’ for the text template.
An Confirmation message displayed telling me i have successfully registered
A link to take me to the application home page.

Or the acceptance criteria may look like this which is my preference.

Acceptance criteria 1 example 2
Story
As a potential new user Given that i am on the ‘Registration’ page i wish to enter my registration information.
Scenario 1 [ Happy Path ]
As a registering user When i fill in a textbox with caption UserName with “Becky01″
And I fill in  Password with “Flowers09″
And I fill in  First Name with “Danielle”
And I fill in Second Name with “Martin”
And I fill in Date Of Birth with “22/08/45″
And I fill in  Email Address with “rebeccamartin@me.com”
And I press a Button with the caption “Send Registration”
Then i Expect to be sent a confirmation Email with my username and password listed and using the attached Text template.
And i Expect to see a confirmation message saying ” You have successfully registered click link ‘X’ to go to the home page”
And i Expect a registration record to be created within the system for my details.

A bit of commentary

You might notice that the second Acceptance Criteria dosen’t express and validation or data rule this is intentional it is meant to express the happy path form this the developer will write the BDD acceptance test and the QA will write a test into her acceptance script / regression script.

The developers hammer out a BDD test to represent the criteria expressed in the second example this might warrent a card on its own or there may be more on the card depending on the story point costing for the criteria lets assume that we had enough fat left to add more criteria to this card.

Scenario 2

As a registering user When i enter a username longer than 25 Characters and i Then press the “Submit Registration Button” I Expect to the page to not submit and a validation message to be shown telling me i my username is to long.

Scenario 3
As a registering user When i enter a username which has a Symbol in it and i Then press the “Submit Registration Button” I Expect to the page to not submit and a validation message to be shown telling me i cant have Symbols in my username

….. and so on….

The developer pair would write test for each expressed scenario and the QA would test this validation logic as part of the exit criteria for the card.

Now i know your all going yep this is cornflakes and milk what is your point , the point is the dev’s will only write tests that are spelt out on the card and will only write code that there test drive them too.

So it feasible that several cards may get played to deliver 1 feature because over time more cards are required to express new or missed validation logic this is not a bug it is simply that the requirements are emergent, one such card might be a card from the security team about guarding against SQL injection attracts.

Enter stage left : QA , BA for post card huddle.
The QA perform a Quick QA , where the QA  validates on the developers machine that the cards exit criteria are satisfied once this is done and the BA is happy the dev’s push the code + tests up to the CI via the Source control system checking that the CI is still green they exit the card and the card gets moved to the QA stream on the card wall.

The QA will get the feature in the card in there nightly build so the next day the regression pack runs over it and makes sure nothing has been broken the QA reviews the report from this.

The QA picks up the card and retests the card know on the QA server, the QA then goes about trying to break the registration process raising Defect cards as required and rating them as long as they are below critical ( the QA may consult a BA and or a Dev to make this determination), they go into the QA back log to be played against features in the next IPM for dev time. If they are critical / show stopper the original story card is placed back in the waiting queue to be picked up by a pair , the card now has a red Defect card stapled to it the next available dev pair will pick this up ahead of any other stories.

Time goes by ………

We reach the end of the release cycle and all the QA regression tests are run again and the QA retest the system performing Dip testing and smoke testing. The release is show cased to the Client and BA’s and we start all over again into the next IPM this time with a combination of stories and defect cards to play.

The final way defects can be raised is when defects get reported form the wild by the customers users then QA validates the defect writes a defect card , a pair pick it up write a failing test make the test pass and then go through the post card huddle and QA process and the fix is put into the next release to the wild.

So i guess my point here is that there is no disparity about how much you test or how much it costs because using this process or something similar there is no code written with out tests, the same with coverage i think its more functional coverage we should concern ourselves with when talking about the scope of our tests. These are my thoughts anyway.

Excellent Article on Classic NBehave with ASP.mvc

Filed under: Agile — Tags: , , — neil martin @ 8:22 am

Russel , has written a brilliant post on using classic nbehave with asp mvc it can be found here : http://russelleast.wordpress.com/2009/01/20/tddbdd-with-aspnet-mvc/

2009/06/03

Setting up SqlLite to run as a file based test database

Filed under: Agile, TDD — Tags: , , , , — neil martin @ 12:14 pm

 

My preference is to use DB4objects or to SqlLite in memory and normally either having a shared static connection or writing my tests in such a way that i don’t need persistence across boundaries means this is sufficient.  However there are circumstances were you do need to persist data across boundaries and where a shared connection is not desirable  i recently had such a situation and felt it might be worth while sharing the code.

So what did i want to do ?

I wanted to set up some pre-test data into a data container and i then wanted to kick off a multi threaded program in a different process to transform that data and i wanted to do it from a NBehave style test using the extended NBehave Dll i also wanted to use separate steps files.

Setting up the Data Container Configuration

So the first thing i needed to do was to set up some config so hares a whistle stop tour of that code

The test specs

using NBehave.Narrator.Framework;
using NBehave.Spec.NUnit;
using NeilMartin.DataGateway.Configuration;
using Context = NUnit.Framework.TestFixtureAttribute;
using Concerning = NUnit.Framework.CategoryAttribute;
using Specification = NUnit.Framework.TestAttribute;

namespace NeilMartin.DataGateway.Tests.Configure_application_tests
{
    [Theme, Context, Concerning("Application, Configuration")]
    public class Can_configure_application_spec
    {
        [Specification]
        public void Should_be_able_to_read_the_output_file_path_from_the_application_configuration_file()
        {
            const string expectedFilePath = "testFilePath";
            var dataGatewayConfigurationSection= DataGatewayConfigurationSection.GetConfig();
            dataGatewayConfigurationSection.DataGatewaySettings[0].FilePath.ShouldEqual(expectedFilePath);
        }
        [Specification]
        public void Should_be_able_to_read_the_connection_string_from_the_application_configuration_file()
        {
            const string expectedConnectionString = "testConnectionString";
            var dataGatewayConfigurationSection = DataGatewayConfigurationSection.GetConfig();
            dataGatewayConfigurationSection.DataGatewaySettings[0].connectionString.ShouldEqual(expectedConnectionString);
        }

    }
}
 
The config section,collection and element
 
public class DataGatewayConfigurationSection : ConfigurationSection
  {
      private const string ConfigurationSectionName = "DataGatewayConfiguration";

      public static DataGatewayConfigurationSection GetConfig()
      {
          return (DataGatewayConfigurationSection)ConfigurationManager.GetSection(ConfigurationSectionName);
      }

      [ConfigurationProperty("DataGatewaySettings")]
      public DataGatewaySettingsCollection DataGatewaySettings
      {
          get
          {
              return (DataGatewaySettingsCollection)this["DataGatewaySettings"];
          }
      }
  }
 
 

public class DataGatewaySettingsCollection : ConfigurationElementCollection

    {
        protected override ConfigurationElement CreateNewElement()
        {
            return new DataGatewaySettingsElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((DataGatewaySettingsElement)element).Key;
        }

        public DataGatewaySettingsElement this[int index]
        {
            get
            {
                return BaseGet(index) as DataGatewaySettingsElement;
            }
            set
            {
                if (BaseGet(index) != null)
                {
                    BaseRemoveAt(index);
                }
                BaseAdd(index, value);
            }
        }

    }

 

public class DataGatewaySettingsElement:ConfigurationElement
   {
       [ConfigurationProperty("key", IsRequired = true)]
       public string Key
       {
           get
           {
               return this["key"] as string;
           }
       }
       [ConfigurationProperty("FilePath", IsRequired = true)]
       public string FilePath
       {
           get
           {
               return this["FilePath"] as string;
           }
       }
       [ConfigurationProperty("ConnectionString", IsRequired = true)]
       public string connectionString
       {
           get
           {
               return this["ConnectionString"] as string;
           }
       }

   }
 
An example resultant configuration file 
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="DataGatewayConfiguration"  type="NeilMartin.DataGateway.Configuration.DataGatewayConfigurationSection, NeilMartin.DataGateway" />
  </configSections>

  <DataGatewayConfiguration>
    <DataGatewaySettings>
      <add key="AcceptanceTesting"  FilePath="c:\testoutput.file" ConnectionString="Data Source=c:\testDatabaseSqllite.file;Version=3;Pooling=true;Max Pool Size=1;Synchronous=Full"  />
    </DataGatewaySettings>
  </DataGatewayConfiguration>
</configuration>

 

Setting up the Data Container SpecBase

So this was the code i ended up with after i had used (DRY) to push it down into a spec base form my original Steps file as i built a further Steps file which required the same functionality.

using System;
using System.Data.SQLite;
using System.IO;
using NBehave.Spec.NUnit;
using NeilMartin.DataGateway.Configuration;

namespace NeilMartin.DataGateway.Features.Process_text_records_feature
{
    public abstract class DatabaseSpecBase:SpecBase
    {
        private static DataGatewaySettingsElement settings;
        private const string outputFilePath = @"c:\testoutput.file";
        private const string databaseFilePath=@"c:\testDatabaseSqllite.file";
        private const string databaseScheamaStatement = @"CREATE TABLE messages(id INTEGER PRIMARY KEY ASC,input_reference int NOT NULL,text varchar(50) NOT NULL)";
        protected SQLiteConnection connection { get; private set;}
        public override void MainSetup()
        {
            settings = DataGatewayConfigurationSection.GetConfig().DataGatewaySettings[0];
            connection = new SQLiteConnection
                             {
                                 ConnectionString =settings.connectionString
                             };
            connection.Open();
            SetupDatabase();
            base.MainSetup();
        }

        private void SetupDatabase()
        {
            using (var command = connection.CreateCommand())
            {
                const string createTableCommandText = databaseScheamaStatement;
                command.CommandText =createTableCommandText;
                command.ExecuteNonQuery();
            }
        }
        public override void MainTeardown()
        {
            try
            {
                connection.Close();
                connection.Dispose();
                GC.Collect();
            }
           finally
            {
                File.Delete(databaseFilePath);
                File.Delete(outputFilePath);
            }
            base.MainTeardown();
        }
    }
}

Their are 2 operations taking place here the first is to set up my final output file for the sake of what were discussing here we can ignor this the other is to set up and teardown the sql database which is the stuff we are interested in here.

Step 1

Get the DLL ‘s for SqlLite and the .net connector they can be downloaded from these sites :

http://www.sqlite.org/download.html

http://sourceforge.net/project/showfiles.php?group_id=132486&package_id=145568

After you have these we then set up a connection  like so :

settings = DataGatewayConfigurationSection.GetConfig().DataGatewaySettings[0]; connection = new SQLiteConnection {

ConnectionString =settings.connectionString

};

Next we execute the database setup by running a command to create the table im interested in

private const string databaseScheamaStatement = @”CREATE TABLE messages(id INTEGER PRIMARY KEY ASC,input_reference int NOT NULL,text varchar(50) NOT NULL)”;

using (var command = connection.CreateCommand())

{

const string createTableCommandText = databaseScheamaStatement;

command.CommandText =createTableCommandText;

command.ExecuteNonQuery();

}

Then we run our features and there associated steps and then we teardown

connection.Close();

connection.Dispose();

GC.Collect();  // Required because of file locks

File.Delete(databaseFilePath);

The Repository

Inside the application code to allow use to configure a repository for the test we use the repository pattern

The interface :

using NeilMartin.DataGateway.Types;

namespace NeilMartin.DataGateway.Repositories
{
    public interface IMessagesRepository
    {
        IMessagesCollection GetAll();
        IMessageRepositoryBatchOptions GetBatchOf(int batchSize);
        int GetCount();
    }

    public interface IMessageRepositoryBatchOptions
    {
        IMessagesCollection From(int index);
    }

The SqlLite Repository :

using System;
using System.Data.SQLite;
using NeilMartin.DataGateway.Types;

namespace NeilMartin.DataGateway.Repositories
{
    public class SqlLiteMessagesRepository : IMessagesRepository, IMessageRepositoryBatchOptions
    {
        private readonly string connectionString;
        private readonly SQLiteConnection connection;
        private int batchSize = 1;
        public SqlLiteMessagesRepository(string ConnectionString)
        {
            connectionString = ConnectionString;
            this.connection = new SQLiteConnection
                                  {
                                      ConnectionString = ConnectionString
                                  };
        }

        public IMessagesCollection GetAll()
        {
            var collection = new MessagesCollection();
            try
            {
                connection.Open();
                using (var command=connection.CreateCommand())
                {
                    command.CommandText ="select * from messages";
                    SQLiteDataReader reader = command.ExecuteReader();
                    while(reader.Read())
                    {
                        collection.Add(new Message(reader.GetInt32(1).ToString() ,reader.GetString(2)));
                    }
                }
            }
            finally
            {
                connection.Close();
            }
            return collection;
        }

        public IMessageRepositoryBatchOptions GetBatchOf(int requiredBatchSize)
        {
            this.batchSize = requiredBatchSize;
            return this;
        }

        public int GetCount()
        {
            var count = 0;
            try
            {
                connection.Open();
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = string.Format("select count(*) from messages");
                    count=Convert.ToInt32(command.ExecuteScalar());
                }
            }
            finally
            {
                connection.Close();
            }
            return count;

        }

        IMessagesCollection IMessageRepositoryBatchOptions.From(int index)
        {
            var collection = new MessagesCollection();
            try
            {
                connection.Open();
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = string.Format("select * from messages where id >{1} LIMIT {0} ", batchSize, index);
                    var reader = command.ExecuteReader();
                    while (reader.Read())
                    {
                        collection.Add(new Message(reader.GetInt32(1).ToString(), reader.GetString(2)));
                    }
                }
            }
            finally
            {
                connection.Close();
            }
            return collection;
        }
    }

    public class Message : IMessage
    {
        public string InputReference { get; private set; }

        public string Body { get; private set; }

        public Message(string inputReference, string body)
        {
            InputReference = inputReference;
            Body = body;
        }
    }
}

 

I hope this has been of help.

2009/05/30

Excellent Post : Teams participating in the cycle of change

Filed under: Agile — Tags: , , , — neil martin @ 9:15 am

Fantastic post by coach Kevin E. Schlabach on the subject of teams needing to empower management and being active participants in the cycle of change. The post can be found here : http://agile-commentary.blogspot.com/2009/05/participate-in-change-dont-expect-it-to.html its well worth reading

2009/05/27

Db4Objects Taken over by Versant

Filed under: Agile — neil martin @ 12:04 pm

Yep the DB4Objects site has a nice red colour theame and a new owner see here for further details : http://openhandsetmagazine.com/2008/12/versant-corporation-acquired-db4objects/ i do wonder what changes this will bring about and if the same level of aggressive , high quality development we have seen and has made the product so attractive over the last few years will continue.

We await results but i for one hope Versent let the Db4 Team have there head and continue as they have.

2009/05/23

Cucumber support : in ruby mine

Filed under: Agile, TDD, ror, ruby — Tags: , — neil martin @ 5:26 pm

Well done to the ruby mine team , they have added direct support for cucumber to the latest version of tool.

here is a screen shot

IDE with cucumber running

Excellent move guys and a big thank you from me.

2009/05/22

Ruby Mine : Licensing Issue’s

Filed under: Agile, ror, ruby — Tags: , , , , — neil martin @ 10:50 am

I decided to bite the bullet and make use of my discount token and to buy a copy of RubyMine before the token expired.

There the good experience ended :
So i went on there site registered input the token number in the little box, went through all Element 5 billing got my emails telling me i had paid and i would get a license key via email.

24hrs later no email , emailed Idea they said we dont have your order so sent them the PDF copy i had downloaded they sent me the key.

Then i open up RM which i had been using as a trial look at the email it says go help / register ok so i type in the help box register ( im on a MAC) nothing relevant pops up on the list, i email support nothing , i look in the forums yet again nothing.

So i start digging around turns out under /Users//Library/Preferences there is a rubymine folder in there is a .key file if you delete that the next time you start up RM you will get the chance to enter new registration details.

hope this helps other people with the same issue.

2009/05/18

Reiki Healing, energy Balancing

Filed under: Agile — Tags: , , , , — neil martin @ 7:34 pm

I would recommend checking out this site, this lady does a world of good when your stressed or out of balance . Trust me in this world you need her services. Whats better she will come to you , so either as a team treat after a stressful sprint or if your warn out after managing a hard release give Michelle a call.

Neil
Here is her link :
http://www.amphiptere-healing.com/

2009/05/12

DZone Quick Reference Cards

Filed under: Agile — neil martin @ 4:55 pm

I recently received a email from DZone advising me that they have a new quick reference card available on DB4Objects and could i feed back on it. I then went and had a look around the Quick reference cards and was presently surprised at both there quality and content.

The subject they cover are wide spread but include Agile , Scrum, DB4objects , resharper.

I recommend you add them to your favourite’s

here is a link :http://refcardz.dzone.com/

oh and there Free.

Older Posts »

Blog at WordPress.com.