May 25, 2017

2 Dimensional List Sort Using Linq

A 2 dimensional list sort
[ Test ]
public void List2DSortTest()
{
    var table = new List<List<string>>
    {
        new List<string> { "1", "Mbukuravi", "2", "Wnuk-Lipinski Settlement", "M2M" },
        new List<string> { "2", "Liaedin", "Ulrich's Rock", "Valigursky Landing", "L1M" },
        new List<string> { "3", "Miao Thixo", "2 A", "Sekelj Laboratory", "M3M" },
    };

    var newTable = table.OrderBy( list => list[ 1 ] ).ToList();
    Assert.That( newTable[ 0 ][ 1 ] == "Liaedin" );
    Assert.That( newTable[ 1 ][ 1 ] == "Mbukuravi" );
    Assert.That( newTable[ 2 ][ 1 ] == "Miao Thixo" );

    var newTable2 = table.OrderByDescending( list => list[ 1 ] ).ToList();
    Assert.That( newTable2[ 2 ][ 1 ] == "Liaedin" );
    Assert.That( newTable2[ 1 ][ 1 ] == "Mbukuravi" );
    Assert.That( newTable2[ 0 ][ 1 ] == "Miao Thixo" );

    var newTable3 = table.OrderBy( list => list[ 2 ] ).ToList();
    var newTable4 = table.OrderByDescending( list => list[ 2 ] ).ToList();
}

March 2, 2017

An Exception Handling String Formatter

A string extension class to safely use string.Format().
public static class StringExtensions
{
    // Safe format, capture any Format Exceptions.
    public static string TryFormat(
        this string formatText,
        params object[] parameters)
    {
        string res = "";
        try
        {
            res = string.Format(formatText, parameters);
        }
        catch (FormatException fe)
        {
            string msg = "Formatting string error : formatText=" + formatText + 
                                ", parameters=\'" +
                              string.Join( ",", parameters ) + "\', exception=" + fe;
            Trace.WriteLine("string.Format code needs fixing - " msg);
            res = formatText;
            Debug.Assert(false, msg);
        }
        return res;
    }
}
I have seen this method take down a complete application because too few parameters were passed.

Thread Safe Enum Access Using Interlocked

Here is an example class that makes reading and writing an enum property thread safe (when writing or reading the enum value)
/// <summary>
///     A thread safe MyEnum.
/// </summary>
public class ThreadSafeMyEnum
{
 // Volatile is not needed (esp. on x64 or x86) : 
 // http://stackoverflow.com/questions/7177169/how-to-apply-interlocked-exchange-for-enum-types-in-c 
 // http://stackoverflow.com/questions/425132/a-reference-to-a-volatile-field-will-not-be-treated-as-volatile-implications
 private int _enumAsInt;

 public MyEnum Value // added for convenience
 {
  get { return ( MyEnum ) Interlocked.CompareExchange( ref _enumAsInt, 0, 0 ); }
  set { Interlocked.Exchange( ref _enumAsInt, ( int ) value ); }
 }
}

NUnit Parameterised Tests

NUnit can have class level parameterised tests:


[ TestFixture( MachineEnum.None ) ]
[ TestFixture( MachineEnum.Lathe ) ]
[ TestFixture( MachineEnum.Miller ) ]
public class SomeTests
{
  private readonly MachineEnum _machineEnum = MachineEnum.None;

  public SomeTests(
  MachineEnum machineEnum )
  {
    _machineEnum = machineEnum;
  }
  ...
}

Also the tests can be paramterised at the test level. Make sure the TestCase parameter match the order and type of the test method.

  [Test]
  [TestCase("some value", null,         ExpectedResultEnum.Paramater1Used)]
  [TestCase("some value", "over ride",  ExpectedResultEnum.Paramater2Used)]
  [TestCase("some value", "over ride",  ExpectedResultEnum.Paramater1Used)]
  [TestCase(null,         null,         ExpectedResultEnum.Paramater1Used)]
  public async Task ParamterisedTest(
    string param1,
    string param2,
    ExpectedResultEnum expectedResult)
{
    // Arrange

    // Act

    // Assert
    Assert.Multiple(() =>
    {
      Assert.That(var1 == null, Is.False);
      Assert.That(var2.Id, Is.EqualTo(expectedResult));
    });
    ...
}

February 20, 2017

Double Equals Extension Class

Doubles cannot be compared without specifying an acceptable error
//     A double extensions class.
public static class DoubleExtensions
{ 
 public static bool IsEqualTo(
  this double val1,
  double val2,
  double resolution ) // Resolution of the double comparison, specifies an acceptable error level
 {
  double compare = Math.Abs( val1 - val2 );
  bool res = compare < resolution;
  return res;
 }
}

Comand Line Parser Class

A special command line parser class that automatically parses command lines specified in a particular way
    // Parse command line arguments in the form
    // /xxx
    // -xxx
    // OR
    // /xxx:yyy
    // -xxx:yyy
    // where xxx is a parameter name and yyy, when present, is a value to associate with it
    // The actual command line argument is case insensitive (but not the value)
    // so /username:Bob is the same as /USERNAME:Bob
    public class CommandLineParser
    {
        readonly Dictionary<string, string> arguments = new Dictionary<string, string>();

        public void ParseCommandLineArguments(
            params string[] args )
        {
            const int NOTFOUND = -1;
            //string[] args = Environment.GetCommandLineArgs();
            Debug.WriteLine( "Args:" + string.Join( ",", args ) );
            int ix = 0;
            foreach ( string arg in args )
            {
                Debug.WriteLine( "arg[" + ix++.ToString() + "]=\'" + arg + "\'" );
            }
            foreach ( string rawArg in args )
            {
                // Get rid of whitespace chars at the beginning and end
                string arg = rawArg.Trim();
                bool argFound = ( arg.Length >= 2 ) && ( arg[ 0 ] == '/' || arg[ 0 ] == '-' );
                if ( !argFound )
                    continue;
                string argument = arg.Substring( 1 );
                int end = argument.IndexOf( ':' );
                string paramName = ( end > -1 ) ? argument.Substring( 0, end ) : argument;
                if ( ( end == NOTFOUND ) && ( paramName.Length > 0 ) )
                {
                    arguments.Add( paramName.ToUpperInvariant(), "" );
                }
                else
                {
                    string value = argument.Substring( end + 1 );
                    arguments.Add( paramName.ToUpperInvariant(), value );
                }
            }
            Debug.WriteLine( "Processed command line args:" );
            foreach ( string argName in arguments.Keys )
            {
                Debug.WriteLine( argName + " = " + arguments[ argName ] );
            }
        }

        public bool GetArgument(
            string arg,
            out string value )
        {
            value = "";
            return arguments.TryGetValue( arg.ToUpperInvariant(), out value );
        }

        // eg '/u' could select the argument /username:Jim as long as no other arguments starts with 'u'
        public bool GetUniqueArgumentStartingWith(
            string startsWith,
            out string value )
        {
            value = "";
            bool res = string.IsNullOrEmpty( startsWith.Trim() );

            if ( !res )
            {
                var keys = arguments.Keys.Where( ky => ky.StartsWith( startsWith.ToUpperInvariant() ) ).ToList();
                res = ( keys.Count == 1 );
                if ( res )
                {
                    res = arguments.TryGetValue( keys[ 0 ], out value );
                }
            }
            return res;
        }

        public bool HasUniqueArgumentStartingWith(
            string startsWith )
        {
            bool res = !string.IsNullOrEmpty( startsWith.Trim() );

            if ( res )
            {
                var keys = arguments.Keys.Where( ky => ky.StartsWith( startsWith.ToUpperInvariant() ) );
                res = ( keys.Count() == 1 );
            }
            return res;
        }

        public bool HasArgument(
            string arg )
        {
            return arguments.ContainsKey( arg.ToUpperInvariant() );
        }

        public IEnumerable<KeyValuePair<string, string>> Arguments()
        {
            foreach ( var entry in arguments )
            {
                yield return entry;
            }
        }
    }
Unit testss that accomapny and demonstrate the use of the class:
[ TestFixture ]
public class CommandLineParserUnitTests
{
    [ Test ]
    public void SeveralValidArgsTest()
    {
        CommandLineParser clp = new CommandLineParser();
        clp.ParseCommandLineArguments( "/user:John", "-password:All0aJadgar", "-IncludeMetaData" );

        Assert.That( clp.HasArgument( "IncludeMetaData" ) );
        string value;
        bool res = clp.GetArgument( "user", out value );
        Assert.IsTrue( res );
        Assert.That( value == "John" );
        res = clp.GetArgument( "smugering", out value );
        Assert.IsFalse( res );
    }

    [ Test ]
    public void EmptyArgAndValueTest()
    {
        CommandLineParser clp = new CommandLineParser();
        clp.ParseCommandLineArguments( "/:" );

        Assert.That( !clp.HasArgument( ":" ) );
    }

    [ Test ]
    public void NoValueSpecifiedTest()
    {
        CommandLineParser clp = new CommandLineParser();
        clp.ParseCommandLineArguments( "/dufftest:" );
        string value;

        Assert.That( clp.GetArgument( "dufftest", out value ) );
        Assert.That( value.Length == 0 );
        Assert.That( clp.HasArgument( "dufftest" ) );
    }
}

October 12, 2016

Using NSubstitute

A good quick guide is provided - Quick Guide

Create a mock for a given inteface:
MockIXXX = Substitute.For<Ixxx>();
The mocked methods always do nothing and return the default value.

Afterwards can mock a return value:
MockIXXX.GetDuplicates().Returns( GetSomeTestResults() ); 
where GetSomeTestResults() is a test method returning the desired results.

A property can be Mocked using standard notation (if it has a getter and a setter)
MockIXXX.Name = "Algol";
When the property is a getter only use the following technique.
MockIXXX.Key.Returns(999);

Do something when a method AddSelection(ISelection) is called with any parameters:
MockIXXX.When( x => x.AddSelection( Arg.Any<ISelection>() ) ).
    Do( arg => dummySelections.Add( arg.Arg<ISelection>() ) );
here dummySelections is a list local to the test.

When testing results: 
// Test 1 call to UpdateView was received on the given MockObject
MockObject.Received(1).UpdateView();
// Test a property was set to a particular value
MockObject.Received().SomeProperty = 10.0d;
// Test no calls to RemovePage were received on the given MockObject with the specified arguments  
MockObject.DidNotReceive().RemovePage( Arg.Any<IControl>() ); 

// Test 1 call to Add() was received on the given MockObject with the given argument
MockObject.Received(1).Add( Arg.Is<INotification>( arg => arg.Id == NotificationEnum.Clean ) ); 
// No calls to Add() were received on the given MockObject with the given argument
MockObject.DidNotReceive().Add( Arg.Is<INotification>( arg => arg.Id == NotificationEnum.Clean ) )
// Test a call was received regardless of the argument value
MockObject.Received( 1 ).Calculate( Arg.Any() );

// When you have multiple tests in a test fixture you sometimes need to clear the received calls
// otherwise the previous tests could have increased the call count
MockObject.ClearReceivedCalls();

Checking calls were received in a particular order:
Received.InOrder(() =>
{
 MockIXxx.SomeMethodCall();
 MockIYyy.AnotherMethodCall(Arg.Any<string>());
});

NSubstitute syntax for raising events is a bit more subtle:
MockObject.SomeEvent += Raise.EventWith(new object(), new EventArgs());
See the NSubstitute documentation here