Archive

Archive for July, 2009

Object Mothers as Fakes

July 30th, 2009 No comments

Update: I was in a pairing session and we decided that that this syntax is way too noisy. So we have written it here. Effectively to a.Banner.isValid().with(new{Name="john"})

This is a follow to Fakes Arent Object Mothers Or Test Builders. Over the last few weeks I have had the chance to reengage with MO and fakes. I am going to document a helper or two with building fakes using extensions. But before that I want to make an observation or two:

  • I have been naming my mother objects as ValidMO.xxxxx and making sure they are static
  • I find that I have a ValidMO per project and that is better than a shared one. For example, in my unit tests the validMO tends to need Ids populated and that is really good as I explore the domain and have to build up the object graph. In my integration tests, however, Id shouldn’t be populated because that comes from the database and of course changes over time. My MOs in the regression and acceptance test are different again. I wouldn’t have expected this. It is great because I don’t have to spawn yet another project just to hold the MO data as I have in previous projects.
  • I find that I only need one MO per object
  • Needing another valid example suggests in fact a new type of domain object
  • I don’t need to have invalid MOs (I used to)

Now for some code.

When building objects for test, the pattern is to either:

  • provide the MO
  • build the exceptions in a new object and fill out the rest with the MO
  • not use MO at all (very rarely)
  • I use this pattern to build objects with basic objects and not Lists – you’ll need to extend the tests/code for that

To do this I primarily use a builder as an extension. This extension differs between unit and integration tests.

Unit test object builder

This code has two tests: Valid and Invalid. The tests demonstrate a couple of things. The first of which is that I am bad by having three tests in the first test. Let’s just say that’s for readability ;-) The first set of tests check that I have setup the ValidMO correctly and that it behaves well with the extension helper “SetupWithDefaultValuesFrom”. This series of tests has been really important in the development of the extensions and quickly point to problems – and believe me this approach hits limits quickly. Nonetheless it is great for most POCOs.

The second test demonstrates testing invalid by exception. Here there rule is that the image banner is invalid if it has no name. So the code says, make the name empty and populate the rest of the model.

  using Core.Domain.Model;
  using Contrib.TestHelper;
  using Microsoft.VisualStudio.TestTools.UnitTesting;
  using UnitTests.Core.Domain.MotherObjects;
  using NBehave.Spec.MSTest;

  namespace UnitTests.Core.Domain.Model
  {
      /// <summary>
      /// Summary description for Image Banner Property Validation Test
      /// </summary>
      [TestClass]
      public class ImageBannerPropertyValidationTest
      {
          [TestMethod]
          public void Valid()
          {
              ValidMO.ImageBanner.ShouldNotBeNull();
              ValidMO.ImageBanner.IsValid().ShouldBeTrue();
              new ImageBanner().SetupWithDefaultValuesFrom(ValidMO.ImageBanner).IsValid().ShouldBeTrue();
          }

          [TestMethod]
          public void InvalidHasNoName()
          {
              new ImageBanner { Name = "" }.SetupWithDefaultValuesFrom(ValidMO.ImageBanner).IsValid().ShouldBeFalse();
          }
      } 
  }

Here’s the ValidMO.

  namespace UnitTests.Core.Domain.MotherObjects
  {
      public static class ValidMO
      {
          public static IBanner ImageBanner
          {
              get
              {
                  return new ImageBanner
                             {
                                 Id = 1,
                                 Name = "KiwiSaver",
                                 Url = "http://localhost/repos/first-image.png",
                                 Destination = "http://going-to-after-click.com",
                                 Description = "Kiwisaver Banner for latest Govt initiative",
                                 IsActive = true,
                                 IsDeleted = false
                             };
              }
          }
      }
  }

At this stage, you should have a reasonable grasp of the object through the tests and what we think is exemplar scenario data. Here’s the model if you insist.

  using Castle.Components.Validator;

  namespace Core.Domain.Model
  {
      public class ImageBanner : Banner
      {
          [ValidateNonEmpty, ValidateLength(0, 200)]
          public virtual string Url { get; set; }

          [ValidateNonEmpty, ValidateLength(0, 200)]
          public string Destination { get; set; }
      }
  }

Builder extensions

Now for the extensions that hold this code together. It is a simple piece of code that takes the model and OM and merges them. Before we go too far. It is actually little more ugly than I want it to be and haven’t had time to think of a more elegant solution. There are actually two methods. One that overrides the model based on null/empty properties and one that also see zero ints and empty strings also as null/empty. So generally, you need to two.

  using System;
  using System.Linq;
  using Contrib.Utility;

  namespace Contrib.TestHelper
  {
      /// <summary>
      /// Test helpers on Mother objects
      /// </summary>
      public static class MotherObjectExtensions
      {

          /// <summary>
          /// Setups the specified model ready for test by merging a fake model with the model at hand. The code merges
          /// the properties of the given model with any defaults from the fake. If the value of a property on the model is an int and its value is 0 
          /// it is treated as null and the fake is used instead.
          /// overridden 
          /// </summary>
          /// <typeparam name="T"></typeparam>
          /// <param name="model">The model.</param>
          /// <param name="fake">The fake.</param>
          /// <returns>the model</returns>
          public static T SetupWithDefaultValuesFrom<T>(this T model, T fake)
          {
              var props = from prop in model.GetType().GetProperties() // select model properities to populate the fake because the fake is the actual base
                          where prop.CanWrite
                          && prop.GetValue(model, null) != null
                          && (
                              ((prop.PropertyType == typeof(int) || prop.PropertyType == typeof(int?)) && prop.GetValue(model, null).As<int>() != 0)
                           || ((prop.PropertyType == typeof(long) || prop.PropertyType == typeof(long?)) && prop.GetValue(model, null).As<long>() != 0)
                           || (prop.PropertyType == typeof(string) && prop.GetValue(model, null).As<string>() != String.Empty)
                              )
                          select prop;

              foreach (var prop in props)
                  prop.SetValue(fake, prop.GetValue(model, null), null); //override the fake with model values

              return fake;
          }
   
          /// <summary>
          /// Setups the specified model ready for test by merging a fake model with the model at hand. The code merges
          /// the properties of the given model with any defaults from the fake. This method is the same as <see cref="SetupWithDefaultValuesFrom{T}"/>
          /// except that empty strings or 0 int/long are able to be part of the setup model
          /// overridden 
          /// </summary>
          /// <typeparam name="T"></typeparam>
          /// <param name="model">The model.</param>
          /// <param name="fake">The fake.</param>
          /// <returns>the model</returns>
          public static T SetupWithDefaultValuesFromAllowEmpty<T>(this T model, T fake)
          {
              var props = from prop in model.GetType().GetProperties() // select model properities to populate the fake because the fake is the actual base
                          where prop.CanWrite
                          && prop.GetValue(model, null) != null
                          select prop;

              foreach (var prop in props)
                  prop.SetValue(fake, prop.GetValue(model, null), null); //override the fake with model values

              return fake;
          }
      }
  }

oh, and I just noticed there is another little helper in there too. It is the object.As helper that casts my results in this case as a string. I will include it and thank Rob for the original code and Mark for an update – and probably our employer for sponsoring our after-hours work ;-) :

    using System;
    using System.IO;


    namespace Contrib.Utility
    {
        /// <summary>
        /// Class used for type conversion related extension methods
        /// </summary>
        public static class ConversionExtensions
        {
            public static T As<T>(this object obj) where T : IConvertible
            {
                return obj.As<T>(default(T));
            }

            public static T As<T>(this object obj, T defaultValue) where T : IConvertible
            {
                try
                {
                    string s = obj == null ? null : obj.ToString();
                    if (s != null)
                    {
                        Type type = typeof(T);
                        bool isEnum = typeof(Enum).IsAssignableFrom(type);
                        return (T)(isEnum ?
                            Enum.Parse(type, s, true)
                            : Convert.ChangeType(s, type));
                    }
                }
                catch
                {
                }
                return defaultValue; 
            }

            public static T? AsNullable<T>(this object obj) where T : struct, IConvertible
            {
                try
                {
                    string s = obj as string;
                    if (s != null)
                    {
                        Type type = typeof(T);
                        bool isEnum = typeof(Enum).IsAssignableFrom(type);
                        return (T)(isEnum ?
                            Enum.Parse(type, s, true)
                            : Convert.ChangeType(s, type));
                    }
                }
                catch
                {

                }
                return null;
            }

            public static byte[] ToBytes(this Stream stream)
            {
                int capacity = stream.CanSeek ? (int)stream.Length : 0;
                using (MemoryStream output = new MemoryStream(capacity))
                {
                    int readLength;
                    byte[] buffer = new byte[4096];

                    do
                    {
                        readLength = stream.Read(buffer, 0, buffer.Length);
                        output.Write(buffer, 0, readLength);
                    }
                    while (readLength != 0);

                    return output.ToArray();
                }
            }

            public static string ToUTF8String(this byte[] bytes)
            {
                if (bytes == null)
                    return null;
                else if (bytes.Length == 0)
                    return string.Empty;
                var str = System.Text.Encoding.UTF8.GetString(bytes);

                // If the string begins with the byte order mark
                if (str[0] == '\xFEFF')
                    return str.Substring(1);
                else
                {
                    return str;
                }
            }
        }
    }
    

Finally, if actually do use this code here are tests:

  using Contrib.TestHelper;
  using Microsoft.VisualStudio.TestTools.UnitTesting;
  using NBehave.Spec.MSTest;

  namespace Contrib.Tests.TestHelper
  {
      /// <summary>
      /// Summary description for MotherObject Extensions Test
      /// </summary>
      [TestClass]
      public class MotherObjectExtensionsTest
      {

          [TestMethod]
          public void EmptyString()
          {
              var test = new Test { }.SetupWithDefaultValuesFrom(new Test { EmptyString = "this" });
              test.EmptyString.ShouldEqual("this");
          }
          [TestMethod]
          public void ModelStringIsUsed()
          {
              var test = new Test { EmptyString = "that" }.SetupWithDefaultValuesFrom(new Test { EmptyString = "this" });
              test.EmptyString.ShouldEqual("that");
          }
          [TestMethod]
          public void EmptyStringIsAccepted()
          {
              var test = new Test { EmptyString = "" }.SetupWithDefaultValuesFromAllowEmpty(new Test { EmptyString = "this" });
              test.EmptyString.ShouldEqual("");
          }

          [TestMethod]
          public void ZeroInt()
          {
              var test = new Test { }.SetupWithDefaultValuesFrom(new Test { ZeroInt = 1 });
              test.ZeroInt.ShouldEqual(1);
          }
          [TestMethod]
          public void ModelIntIsUsed()
          {
              var test = new Test { ZeroInt = 2 }.SetupWithDefaultValuesFrom(new Test { ZeroInt = 1 });
              test.ZeroInt.ShouldEqual(2);
          }
          [TestMethod]
          public void ZeroIntIsAccpted()
          {
              var test = new Test { ZeroInt = 0}.SetupWithDefaultValuesFromAllowEmpty(new Test { ZeroInt = 1 });
              test.ZeroInt.ShouldEqual(0);
          }

          [TestMethod]
          public void ZeroLong()
          {
              var test = new Test { }.SetupWithDefaultValuesFrom(new Test { ZeroLong = 1 });
              test.ZeroLong.ShouldEqual(1);
          }
          [TestMethod]
          public void ModelLongIsUsed()
          {
              var test = new Test { ZeroLong = 2 }.SetupWithDefaultValuesFrom(new Test { ZeroLong = 1 });
              test.ZeroLong.ShouldEqual(2);
          }
          [TestMethod]
          public void ZeroLongIsAccepted()
          {
              var test = new Test {ZeroLong = 0}.SetupWithDefaultValuesFromAllowEmpty(new Test { ZeroLong = 1 });
              test.ZeroLong.ShouldEqual(0);
          }

          private class Test
          {
              public string EmptyString { get; set; }
              public int ZeroInt { get; set; }
              public long ZeroLong { get; set; }
          }
      }
  }

I hope that helps.

Regex in Find-and-replace in Visual Studio for left-angle brackets

July 18th, 2009 No comments

My problem is simple. Sandcastle requires encoded html to parse correctly. Having generics in the documentation causes it to break. I need to replace the '<' with &lt;. I just now need to do this by the solution in Visual Studio. Of course, microsoft requires me to know another regex set of expresssions: http://msdn.microsoft.com/en-us/library/2k3te2cs(VS.80).aspx

Here’s the simple regex:

  • Find: ///{.*}{[^:b\>\.]}(\<)
  • Replace: ///&lt;

The regex looks for a left angle bracket on the end of a word (ie no space, no period). This means that it also leaves html in place.

Find and Replace in Visual Studio 2008

Note: I wouldn’t do a global replace but use it to step through each.

Before:

    /// <summary>
    /// Used for testing the redirection of action on successful and failing calls to an action.   
    /// <example>
    ///    [TestClass]
    ///    public class UserControllerRedirectsTest
    ///    {
    ///        [TestMethod]
    ///        public void SuccessfulCreateRedirectsToIndex()
    ///        {
    ///            Controller<UserController>
    ///                .ShouldRedirectTo(ResfulAction.Index)
    ///                .IfCallSucceeds()
    ///                .WhenCalling(x => x.Create(null));
    /// </example>
    /// </summary>
    /// <typeparam name="T"></typeparam>

After:

    /// <summary>
    /// Used for testing the redirection of action on successful and failing calls to an action.   
    /// <example>
    ///    [TestClass]
    ///    public class UserControllerRedirectsTest
    ///    {
    ///        [TestMethod]
    ///        public void SuccessfulCreateRedirectsToIndex()
    ///        {
    ///            Controller&lt;UserController>
    ///                .ShouldRedirectTo(ResfulAction.Index)
    ///                .IfCallSucceeds()
    ///                .WhenCalling(x => x.Create(null));
    /// </example>
    /// </summary>
    /// <typeparam name="T"></typeparam>
Categories: Uncategorized Tags: ,

Creating a tftp server on OS X so that I can update my cisco router

July 12th, 2009 Comments off

Creating a tftp server on Mac OS X so that I can update my cisco router

Setting up

Option One: point to new directory

A config file, tftp.plist for tftpd(8) is in /System/Library/LaunchDaemons/ directory.
This is an XML file. If you need to change tftpd(8) root directory to something other than
/private/tftpboot, edit tftp.plist file and change the <array> tag as follows:

<array>
  <string>/usr/libexec/tftpd</string>
  <string>-i</string>
  <string>/private/tftpboot</string>
</array>

Note: you must restart the tftp server after a change

Option Two: symlink

# sudo ln -s /Users/me/src/running-config running-config

Permissions

chmod 777 file


Personally, what I have done it symlinked files/folders from this directory.

Starting up

If you ever need to use tftpd(8) server on Mac OS X:

# sudo /sbin/service tftp start


This will start a tftpd(8) server on Mac OS X.

Stopping

After the change, tftpd(8) needs to be restarted.

# /sbin/service tftp stop


h2. Checking

To check if everything is working fine type (my ip at the time was 192.1.168.101). I need to set the mode to octet via binary

$ tftp
tftp> connect 192.168.0.101
tftp> status
Connected to 192.168.0.101.
Mode: netascii Verbose: off Tracing: off
Rexmt-interval: 5 seconds, Max-timeout: 25 seconds
tftp> verbose
Verbose mode on.
tftp> trace
Packet tracing on.
tftp> binary
mode set to octet

Test Run

To get a file type

tftp> get running-config
Categories: Uncategorized Tags: ,

Creating a restful-resources application in rails

July 12th, 2009 Comments off

I am creating a rails application and I haven’t used rails in 2 years and, of course, version 2.2.2. So I thought that I had better record my major steps. I also needed to learn how to use rspec with rails (rather than the unit tests).

Update all the gems

gem update 

Install the plugins

  sudo gem install rspec
  sudo gem install cucumber
  sudo gem install rcov
  sudo gem install rspec-rails
  
  script/plugin install git <-- rspec
  script/plugin install git://github.com/phorsfall/rspec_on_rails_nested_scaffold.git
  script/plugin install git://github.com/activescaffold/active_scaffold.git

Install Jquery

  ./script/plugin install http://ennerchi.googlecode.com/svn/trunk/plugins/jrails
  

Tutorial for logins

git clone git://github.com/activefx/restful_authentication_tutorial.git new_folder

./script/generate rspec_scaffold Skill name:string category_id:integer description:string

Categories: Uncategorized Tags: , ,

Manual Regressions: an oxymoron?

July 12th, 2009 No comments

I was at a testing talk the other night. It turned to automated testing which got me asking the question. Are manual regressions an oxymoron? I was thinking that no it isn’t if regression is simply the idea of re-testing. I would have thought that re-testing the application for fit-for-purpose is one type of regression, as it is that a particular business rule is applied. But it does make us think about why we are regression-ing in the way we are either manually or automated.

Luckily the speaker replied concurring with my thoughts:

No, I don’t think it’s an oxymoron. It may be cheaper to manually test some (hopefully rare) aspects repeatedly, where a very high cost of automation is unlikely to give sufficient payback over the lifetime of the project. An extreme version of that is automated usability testing, which we can’t do. But I agree that it’s a useful first-step generalisation, given that many people don’t see manual regression testing as an oxymoron under any circumstances.

How then would we capture these regression tests? Are they part of a test plan? How does the team know to do them? Are they part of the done criteria? How do we maintain these lists? How do we make sure that they are followed and that new members are inducted?

It seems to me that there should be scripted (not in the programatic sense) tests. Where these are held is debatable. In my teams, I would want them as close to the source code as possible (ie in the source code). I want the in plain text if at possible. I want them as short as possible. They should resemble smoke tests.

In teams that tend to keep the testers separate to developers, I see them kept in separate sources: excel, word, tracking systems (eg Test Warehouse) or bug trackers (eg JIRA) or systems that are supposed to link everyone (eg TFS 2010).

However, I find that usually these approaches try to hide that there is a lack of commitment to continuous integration, continuous deployments, good test automation strategy layering and a lot of multitasking and handoffs.

Configuration DSL – Part III: Writing a Fluent Interface for Configuration in C#

July 12th, 2009 No comments

This is the third entry on creating configuration DSLs in C#. The previous entry looked at the implementation. The basis of this code is to solve the problem that there are multiple configurations an application may require: development, test and moving through environments up to production. This solution makes the distinction that there are profiles of settings which are distinct from the values in each setting. Before I address the problems in this design let’s try and see what patterns are used in the DSL and relate them to Fowler’s DSL patterns.

Patterns used …

Problems: Making the configuration immutable behind a factory

Using Asp.Net MVC – basic resources

July 5th, 2009 No comments

I’ve just started working with a team on asp.net mvc. I’m now starting to create a list of resources that I am finding useful. You’ll notice that I have been reading around Steve Sanderson’s work because our team is tending to focus around his solutions.

General books

Sample Code Downloads

Blogs/Tutorials

Libraries

Other libraries that I will fill out as needed:

  • moq
  • nbehave (for the assert helper syntax)
  • storyq – acceptance testing
  • selenium/watin – browser testing
  • jquery/jsspec – for gui specific testing (see this blog for samples and jqueryplugingen for scaffolding)
  • sdc tasks – for deployment
  • teamcity/tfs for CI
  • migratordotnet – for migrations (I’m also thinking SqlLite for base dev testing)
  • Gallio -

Strategies:
* fakes, object mothers and using extensions

Categories: Uncategorized Tags: