Mathias Brandewinder on .NET, F#, VSTO and Excel development, and quantitative analysis / machine learning.
by Mathias 2. August 2011 16:06

When working with Excel, it is common to use small optimization tricks, like setting Excel.ScreenUpdating to false to avoid un-necessary screen refreshes, during lengthy operations – something along these lines:

public void DoJob(Worksheet  worksheet)
{
   var excel = worksheet.Application;

   var initialScreenUpdating = excel.ScreenUpdating;
   var initialCursor = excel.Cursor;

   excel.ScreenUpdating = false;
   excel.Cursor = XlMousePointer.xlWait;

   // do stuff

   excel.ScreenUpdating = initialScreenUpdating;
   excel.Cursor = initialCursor;
}

This is a good outline of what we would like to happen, but as is, this code has limitations. We would like to be certain that whenever we capture the state, the final two lines, which reset the state to what it was originally, are executed.

More...

by Mathias 30. May 2010 11:01

Silence is gold. Or… is it? You may have noticed that VSTO swallows exceptions; that is, if something goes wrong in your add-in code, Office will discreetly carry on as if nothing had happened. Consider the following code:

public partial class ThisAddIn
{
    private int counter;

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        this.Application.SheetActivate += SheetActivated;
    }

    private void SheetActivated(object sheet)
    {
        MessageBox.Show("Counter = " + this.counter.ToString());
        throw new ArgumentException("Something went south here.");
        counter++;
    }

The add-in is supposed to maintain a counter of how many times the user has changed the activate sheet. However, a bug throws an exception right before the counter is updated. If you run this code, you’ll see that the MessageBox keeps being displayed every time you change the selected worksheet, but the counter stays firmly at zero, and never gets updated.

More...

by Mathias 8. June 2009 08:53

No matter how much you think you have your bases covered, users will do unexpected things with your application. Writing good unit tests: priceless. For everything else, there is logging. So I decided to add exception logging to Akin, and opted for NLog.

NLog rocks. It is very easy to configure: basically, add the NLog dll to your project, a configuration file defining what you want to log, and where it should go, and you are set. My configuration file looks something like that:

<?xml version="1.0" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets>
    <target name="file" xsi:type="File"
        layout="${longdate} ${stacktrace} ${message} ${exception:format=message,type,method,stacktrace}"
        fileName="${basedir}/logs/${shortdate}.log"
        concurrentWrites="true" />
  </targets>
  <rules>
    <logger name="*" minlevel="Trace" writeTo="file" />
  </rules>
</nlog>
Which I use then to log exceptions this way:
try
{
    // try to open a file
}
catch(Exception e)
{
    logger.TraceException(string.Format("Failed to open {0}.", path), e);
}

The exception gets appended to a file like 2009-06-08.log, in the logs folder located in the application folder, in that case, C:\Program Files\Akin; if the file or folder do not exist, it gets automatically created. This worked like a charm, once I realized I also needed to add the config file to the installer.

And then I deployed on a Vista machine. Everything looked fine (I checked that logging to a message box worked), except that… there was no log file to be found. Damn.

After much anxiety and help of StackOverflow, I found my logs. Turns out, there was a log file, but not where I expected it to be. Vista uses File System Virtualization, and writes the log to another location – in my case,

C:/Users/JohnDoe/AppData/Local/VirtualStore/Program Files (x86)/Akin/Logs/

So if you can’t find your log files, no worries. It’s just Vista playing hide-and-seek with you…

by Mathias 17. May 2009 02:25

Another nice improvement coming with NUnit 2.5 is the mechanism for data-driven tests. NUnit 2.4.7 included an extension by andreas schlapsi which permitted to write row tests, using the [TestRow] attribute.

NUnit 2.5 eases the process with the [TestCase] attribute. Unlike [TestRow], the [TestCase] attribute is available within the NUnit.Framework namespace, and doesn’t require including additional references.

Why do Data-driven tests matter? They are not technically necessary: you can write the same tests as easily using the standard [Test] attribute. However, it comes handy when you are testing a feature where you want to verify the behavior for multiple combinations of input values. Using “classic” unit tests, you will end up duplicating test code, and you will have to find different name for tests method which are in essence the same test.

Using [TestCase] instead, here is how it looks. Suppose your class MyClass has a method “Divide” like this one:

public class MyClass
{
    public double Divide(double numerator, double denominator)
    {
        if (denominator == 0)
        {
            throw new DivideByZeroException("Cannot divide by zero."); 
        }
        return numerator / denominator;
    }
}

One way to test that feature would be with a test like that one:

[TestCase(2.5d, 2d, Result=1.25d)]
[TestCase(-2.5d, 1d, Result = -2.5d)]
public double ValidateDivision(double numerator, double denominator)
{
    var myClass = new MyClass();
    return myClass.Divide(numerator,denominator);
}

More...

by Mathias 10. May 2009 23:24

Compared to the recent releases, NUnit 2.5 contains quite a few significant changes. One notable change is in the area of exception testing – and it is for the better.

Until NUnit 2.4.8, testing for exceptions was done by decorating tests with the [ExpectedException] attribute. NUnit 2.5 introduces a new assertion instead, Assert.Throws.

Why is this better?

I see at least 2 reasons: it makes it much easier to catch the exception precisely where it is expected to happen, and working with the exception itself is now a breeze.

While the ExpectedException attribute is typically sufficient, it is a bit of a blunt tool. What it does verify is that the code under test throws the expected type of exception; what it  doesn’t tell you is where. The tests are not fully explicit, and sometimes, they can result in unexpected “false positives”.

Consider the following situation: a class MyClass exposes a method that takes a positive int as argument, and throws an ArgumentException if a negative is passed. A test for this behavior would look something like this:

[Test]
[ExpectedException(typeof(ArgumentException))]
public void FalsePositive()
{
    MyClass myClass = new MyClass();
    // This call is test setup, but will
    // throw an unwanted ArgumentException.
    myClass.SomeMethodThatThrows();
    // We want to check that this call throws.
    myClass.SomeMethodThatRequiresAPositiveArgument(-5);
}

More...

Comments

Comment RSS