Monday, January 18, 2010

Currently I am working on upgrading an existing complicated spreadsheet which makes extensive use of VBA.  It is used for formulae prototyping and then the code is translated (manually) into C#.  This is far from ideal not to mention slow so I am converting it to use VSTO.

Personally, I am not a big fan of VSTO it feels like a hack to allow .Net developers to extend Office applications (usually Excel).  But under the hood it is basically wrapping the code into a COM wrapper to allow it to work.  Can you believe that after ten years of .Net, there is still no native support for .Net inside Office applications. Ok, thats my rant for the day.

The process is pretty straight forward, using the templates provided in Vs2008, however there are a number of "gotchas" I thought I would record for when I come back to this project some months later and wonder why.

  1. TURN OFF RESHARPER!!
    Currently I am using Resharper for C# v4.5, and although this is one of my favourite tools of all time, it doesn't play nice with Excel and VSTO. Turn it off using Tools-Addin Manager and untick the box in Vs2008.  With it on it will consistently crash (hang more precisely) Vs and Excel about every 2-4 minutes.

  2. When writing data to an Excel sheet, do not loop through many cells writing data this will be very slow.  Obviously there is a lot of overhead writing data to a cell.  Instead write it to a jagged array and write the array in one chunk to a range. Using a named range will probably be tidiest.

              
                var lTable = new object[calc.Term + 1, 10];
                foreach (var lLine in calc.CashflowSolution) {
                    // Get Data - details not important
                    int lPeriodNumber = ++lLineNumber;
                    DateTime lPeriodDate = GetDate();
                    var lPrincipal = GetPrincipal();
                    var lPayment = GetPayment();
                    var lClosingBalance = GetClosingBalance();
                    var lInterest = GetInterest();
                    var lAdminFee = GetAdminFee();
                    var lTotalInstalment = lPeriodNumber == 0 ? 0 : GetInstalment();

                    lTable[lRow, PeriodColumn] = lPeriodNumber;
                    lTable[lRow, DateColumn] = lPeriodDate;
                    lTable[lRow, PrincipalColumn] = lPrincipal;
                    lTable[lRow, InterestColumn] = lInterest;
                    lTable[lRow, PaymentColumn] = lPayment;
                    lTable[lRow, ClosingBalanceColumn] = lClosingBalance;
                    lTable[lRow, AdminFeeColumn] = lAdminFee;
                    lTable[lRow, TotalInstalmentColumn] = lTotalInstalment;
                    lRow++;
                }

                Range lRange = this.get_Range(string.Format(CultureInfo.InvariantCulture, "B40:I{0}", lTable.GetUpperBound(0) + 40), Missing.Value);
  3. When using an object array to "paste" data in one big hit into a sheet, be sure the clear the area first, otherwise the second invocation could produce a smaller array than the first leaving some bad data!
  4. There are at least two commonly used overloads for getting a Range.
    this.InterestAccrualTable.ClearContents(); // A named ranged defined in the sheet as B2:C10000
    int lNumberOfDays = 1082;
    var lTable = new object[lNumberOfDays + 1, 2];
    // Overload 1
    Range lRange = this.get_Range("B2", "C" + lNumberOfDays + 2);
    // Overload 2Range lRange = this.get_Range(string.Format(CultureInfo.InvariantCulture, "B2:C{0}", lTable.GetUpperBound(0) + 2), Missing.Value);

    Overload 1
    The first overload seem to produce "#N/A"'s underneath the range specified in the method.

    Overload 2
    Works much better:

  5. I'm currently having deployment problems as well. This is the error message I'm getting after installing on a target machine (with Office 2007 SP2).
    "The common language runtime could not be loaded by ..."

    After dealing with various issues (ensuring .Net runtime, Office 2007 Sp2 etc), I am starting to see VSTO is shakey at best to deploy and use.  I read about a known issue with Office apps not being able to reliably select the appropriate .Net runtime.  The recommendation in a forum was to create an Excel.Exe.Config file...
    <?xml version="1.0"?> 
    <configuration> 
        <startup>
            <supportedRuntime version="v2.0.50727"/>
        </startup>
    </configuration>
    This, however does not work in my case.

    I found another article recommending not using a Setup Project (which is what I was doing here) but rather use the Publish feature by right clicking the VSTO Project. This creates a folder containing various files, most importantly a Setup.Exe.

    This fixes the issue of being able to install on a target machine, however the install process is not customisable! So you cannot add a shortcut etc.

Friday, January 15, 2010

PLINQ

Here's a summary of some great new (and some improved) features in LINQ and most importantly PLINQ.


PLINQ will actually be slower than LINQ to objects if there is no expensive filtering, or projection process.  Here are some examples when using PLINQ is a good idea.

Where selecting has a time consuming process:

IEnumerable<int> src = ...
var query = 
      src.AsParallel()
      .Where(x => x % 2 == 0)
      .Select(x => Foo(x));
Using ForAll with an expensive projection function and possibly an expensive loop:

int[] src = Enumerable.Range(0, 100).ToArray();
var query = src.AsParallel()
             .Select(x => ExpensiveFunc(x));

int resultSum = query.ForAll(
      x => Console.WriteLine(x)
);
Using a Partitioner to ensure load balancing:

int[] src = Enumerable.Range(0, 100).ToArray();
var query = Partitioner.Create(src, true).AsParallel()
             .Select(x => ExpensiveFunc(x));

foreach(var x in query)
{
      Console.WriteLine(x);
}

An expensive filter:

int[] src = Enumerable.Range(0, 100).ToArray();
var query = src.AsParallel()
             .Where(x => ExpensiveFilter(x));

foreach(var x in query)
{
      Console.WriteLine(x);
}
Sequence zipping (takes two elements from two input arrays and outputs one resulting element):

int[] arr1 = ..., arr2 = ...;
int[] results =
      arr1.AsParallel().AsOrdered()
      .Zip(
           arr2.AsParallel().AsOrdered(),
           (arr1Elem, arr2Elem) => ExpensiveFunc(arr1Elem, arr2Elem))
      .ToArray();
A reduction extension method:

public static double Average(this IEnumerable<int> source)
{
      return source.Aggregate(
             () => new double[2],
             (acc, elem) => {
                   acc[0] += elem; acc[1]++; return acc;
             },
             (acc1, acc2) => {
                   acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1;
             },
             acc => acc[0] / acc[1]);
}

Wednesday, January 6, 2010

Accessing Internal Members

5-January-2010
Happy new year!  Just had to document this quickly. Accessing internal members is necessary for testing, but also sometimes for production code.  I found this to be the case optimising a day-end process which read some database records copied them elsewhere and needed to save. Unfortunately by doing so resets the connection object inside the persistence layer (an old proprietary ORM unchangeable right now). This meant that the records then needed to be re-read, to prevent access to stale objects that would not have future changes updated into the database.

This was fixed by calling an internal method on the connection object that registers database entities into an internal collection.  A bit of a hack, but fixes the performance issue without getting caught up in fixing a persistence layer that will be replaced soon.

But there were two possible approaches.  
1) You can grant another library permission to access its internal (or friend in vb) members; 
2)  Or you can allow access to a internal member with an extension method.

Grant access to all internals
Lets start with granting access to another library to access the internal members. This will give the other library full access to all internal members in the source library. This will only work if both libraries are signed with a strong name. To find out how to do that go here.

Open the library (DLL) that contains the internal members you would like to access externally.  Find the assemblyinfo.vb (or .cs in c#) and add the following line at the bottom:



[assembly: InternalsVisibleTo("MyUnitTestLibrary, PublicKey=002400000480000094000000060200000024000052534131000400000100010015b2942f80eea6e7c6ee614974fefc2820236c27c4c0dd221c6469178e7e34884466e5dfb8f1958f0feff6dc71f00176927ce3a3d360b50c08880efa9de0a8cb33a80d4cf3ed6849a5f1d0699b64346f94b505c2b6c585b1e0dd3929640ad3f23ce35a0f79e6539dd74f1ab9f25c9a366124f1d84117126b7c5d83e37fbc6ddb")]

You will need to import "Imports  System.Runtime.CompilerServices".

Replace the "MyUnitTestLibrary" with the name of the other library where you need to call the internal methods of this library.  

The next thing to do, is to obtain the public key signature data.  This is done by using the Sn.exe command line utility.
Use the following command line (in which the parameters are case sensitive):
sn -Tp YourDllNameHere.dll

Output should look something like this:

Microsoft (R) .NET Framework Strong Name Utility  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Public key is
002400000480000094000000060200000024000052534131000400000100010015b2942f80eea6
e7c6ee614974fefc2820236c27c4c0dd221c6469178e7e34884466e5dfb8f1958f0feff6dc71f0
0176927ce3a3d360b50c08880efa9de0a8cb33a80d4cf3ed6849a5f1d0699b64346f94b505c2b6
c585b1e0dd3929640ad3f23ce35a0f79e6539dd74f1ab9f25c9a366124f1d84117126b7c5d83e3
7fbc6ddb

Public key token is ee02eaa036161368
Copy and past the public key data into the assemblyinfo file, obviously removing the carriage returns.

Build both libraries and you can now access the internals.  This is normally fine for testing but to expose all internals for only one use case feels dirty for production code.

Grant access to one method using an extension

Heres the class that owns the internal member.

Public Class Connection
   Friend Sub RegisterObject(newObject As BaseEntity)
        ' Inner workings not important
    End Sub
End Class

And the use case from the other library...

Dim objects As IEnumerable(Of BaseEntity) = connection.GetObjects(...) 'How to get objects is unimportant...
Me.PerformSomeOperation(objects)
connection.Commit() ' This resets the internal collection and the above array of objects is now stale and unusable, all changes to them will not be saved.
For Each(Dim x As BaseEntity In objects)
    connection.RegisterObject(x)  ' Need to be able to do something like this, but can't right now.
Next

The plan is to add an extension to the library that contains the extension.

Imports System.Runtime.CompilerServices

Namespace Extensions
    Public Module ContainerJobExtensions
        <Extension()> _
        Public Sub RegisterObjects(ByVal instance As Connection, ByVal objects As BaseEntity())
            Array.ForEach(Of BaseEntity)(objects, AddressOf instance.RegisterObject)
        End Sub
    End Module
End Namespace

Now with that I can re-register the objects with the connection like so...

Dim objects As IEnumerable(Of BaseEntity) = connection.GetObjects(...) 'How to get objects is unimportant...
Me.PerformSomeOperation(objects)
connection.Commit() ' This resets the internal collection and the above array of objects is now stale and unusable, all changes to them will not be saved.
connection.RegisterObjects(objects)

By putting the extension in another namespace you can selectively import this only into the use case where you need to use it.

Done!

Monday, December 28, 2009

Unit Testing 101 Guidelines Part 4

Also see See also Unit Testing Guidelines Terminology, Part1, Part2, Part3, Part4


Standard Practices & Guidelines

Code Coverage Levels

·         DO have at least 60% code coverage with any new Microsoft.Net code written.

·         CONSIDER aiming for 80% + (Remember it is not possibly to unit test ALL code, so don't beat yourself up if you can't get to 100%).

·         DO analyse your code using the Code Coverage panel in Visual Studio. This will show you the code paths not tested.

Structure of Test Fixtures and Projects

·         DO write at least one Test Fixture per production class.

·         CONSIDER writing more than one Test Fixture per production class. Test Fixtures with fewer methods and with clear themes are easier to maintain.

·         CONSIDER creating one test project per Visual Studio solution, not one test project per production project.

·         DO NOT add references to test libraries in the production projects. (ie NunitFramework.dll, RhinoMocks.dll, YourTestProject.dll etc).

·         DO give your test fixtures strong names with no acronyms.  Better it be long and descriptive than short and cryptic.

·         DO put Integration Tests and Unit Tests in different namespaces within your test project. This will make it easier for people to bypass the longer larger integration tests if they choose to do so.

·         DO NOT inter-mingle unit tests and integration tests in the same test fixture.

·         AVOID using constructors in test fixtures. Use methods decorated with the [Setup] attribute instead.

·         DO NOT use IDisposable or destructors in test fixtures instead use the [Teardown] attribute on your clean up method.

·         DO put all your accessors in a sub-folder and different namespace within your test project.

·         DO put all your mocks and stubs in a sub-folder and different namespace within your test project.

Single Test Design

·         CONSIDER the theme of your test.  Each test should be testing a specific use case or code path. Better to the have lots of simple tests than few complex difficult to maintain tests.

·         AVOID designing your tests to be slower than 500ms each.

·         CONSIDER optimising until they are running in less than 100ms each.

·         CONSIDER keeping your tests to 50 lines of code or less.

·         DO NOT let your test exceed 100 lines of code.

·         DO give your tests strong names with no acronyms.  Better it be long and descriptive than short and cryptic.

·         CONSIDER giving all your tests descriptions using the [Test] attribute. For example: [Test(Description = “My test that tests the something method and looks for this...”)].

·         DO NOT write tests that could affect the running of other parallel tests. For example avoid using class level or static variables, except if they are readonly.  Tests should always be able to run in parallel; in fact most tools do this by default (Resharper and NUnit Gui included).

·         DO NOT write tests that fail periodically and pass sometimes. Tests should always be consistent.

·         AVOID writing tests that access more than one public method or entry point into a class. Write more tests.

·         DO always add the [Timeout] attribute to all your tests.  Give it at most a 500ms timeout. This will prevent failing tests waiting for internal timeouts to expire to fail the test. (You will need to remove the attribute to debug the test).

·         CONSIDER using a Mock framework like RhinoMocks to automatically generate your mocks and stubs. Writing them by hand is tedious and time consuming.

·         CONSIDER extensively commenting your tests.  Tests are commonly used for explaining how to use a particular class.  It also increases maintainability of the test.

·         DO use a wide range of input values for a test. Always test fringe data like null, empty, zero, and negatives where appropriate.

·         CONSIDER using the [Values] attribute rather than copying and pasting the same test over and over but with different input data for the targeted method.

·         AVOID using try...catch to catch expected exceptions in tests.  For example if you want to ensure a NullArgumentException is thrown when a consumer tries to pass null to a method, use the [ExpectedException] attribute rather than wrapping the test in try...catch.

·         DO test all exceptions thrown by a code path. If the method being tested has code that specifically throws exceptions, write tests for these use cases.

·         DO check the state of the class as well as return values of functions.  A function could change the fields within the class as well as return a value.

Dependencies

·         DO mock all references the class under test has to other classes.  Exceptions are listed below in this section.

·         AVOID mocking/stubbing dependencies of type ICommand.  Commands are one of the few very simple standard objects that can be exempted.  This only applies to Commands of type RoutedCommand and RelayCommand. If you have a custom implementation then it will need to be mocked.

·         AVOID mocking/stubbing dependencies that are Data Transfer Objects (DTOs).  These are objects that are used to transfer data to and from a WCF service.  These objects are basically structs and do not contain any logic.

·         CONSIDER using Strict mocks when using Rhino Mocks whenever possible as they catch a much wider range of issues with much less code.

·         AVOID using a string based private accessor. Prefer instead a strongly typed private accessor like those generated by the PrivateAccessorGenerator class.

What to test

·         DO test all public methods of a class. Most often the non-public members will be called by the public members. If the non-public members are not being covered by testing only the public members consider testing them too.

·         CONSIDER testing all paths through a method of code. Use the Code Coverage analysis tool inside Visual Studio to show you the paths currently not being tested (they will be highlighted in pink).

·         DO test all main points of entry into the class. An entry point might be a public method, or protected or internal. 

·         DO test the constructors of a class to ensure the class is in a predictable defined state upon instantiation.

·         CONSIDER testing internal and protected members if the public methods of a class do not call all internal and protected methods.

·         DO NOT test properties, fields, structs, and enums. These members should not contain any logic.  The only exception to this rule is the properties who raise the INotifyPropertyChanged.PropertyChanged event.

·         DO test properties that intentionally throw exceptions.  This technique is sometimes used to validate property setters in WPF. These setters should be tested with some known valid and invalid cases.

Design for Testing

·         DO NOT write tests that require user intervention.

·         DO NOT add test code or test concerns to production code. Unit testing is supposed to be unobtrusive into the production code and leave no footprint on the production code.  This means no test libraries should be referenced by production assemblies. There should be no if statements or compiler switches for testing versus production. By looking at the production code you should not be able to tell unit tests are being used against a class.

·         DO use interfaces for references to other classes.

·         CONSIDER using a basic abstract class instead of an interface but prefer interfaces.

·         DO use the following dependency injection techniques in this order or preference:
1)            Interfaced properties that use a backing field, that if null creates the production instance of that type.  A private setter can be used to inject a test mock.
private IMessageBoxService backingMessageBoxService;
public IMessageBoxService MessageBox {
    get {
        return this.backingMessageBoxService ?? (this.MessageBox = new WpfMessageBoxService());
        }

        private set {
            this.backingMessageBoxService = value;
        }
    }
}
This is best when only a test mock and a production type are used. If there could be more then rather use an Object Factory to get the instance.

2)            Constructor injection. The number of constructor arguments should be no more than 3 or 4.

public FormController(IContactDataService contactDataService) { … }

3)            Use an Object Factory to get an instance of an interface.

private IMessageBoxService backingMessageBoxService;
public IMessageBoxService MessageBoxService {
    get {
        if (this.backingMessageBoxService == null) {
            this.backingMessageBoxService = StructureMap.ObjectFactory.Container.GetInstance<IMessageBoxService>();
        }
 
        return this.backingMessageBoxService;
        }
    }
}




·         DO NOT use property injection. It is very slow in comparison to constructor injection and object factory look-up.

·         DO NOT call the static class MessageBox directly. Instead see this example: Message Box Usage

·         DO NOT show Windows directly. Ie Do not call Window.Show().  Instead see this example:
·         Showing Another Window From a Controller
·         AVOID static properties or fields in a class. Rather ask the object factory to return you a singleton reference.  The key piece is the .Singleton() method call.
ObjectFactory.Initialize(init => {
    init.For<ITestSingleton>().Singleton().Use<TestSingleton>();
});
var singleton = ObjectFactory.GetInstance<ITestSingleton>();

In this example the same instance will be returned whenever someone asks for an instance of ITestSingleton.

Bugs

·         DO write at least one test every time you find a bug or are given a bug report to resolve. This ensures the exact same bug cannot reoccur. The test should reproduce the bug and fail.  You can then write code to make the test pass. Ensure your test(s) covers all scenarios documented in the bug report.

·         CONSIDER writing more tests if you can see more than one way the bug could manifest itself.

·         DO write only the code necessary to make your tests pass.