Did you know about delayed Asserts in NUnit

by toni 13. August 2011 18:40

When writing unit tests for asynchronous code you sometimes have to use wait handles or other techniques to make sure asserts kick in after the asynchronous code has had a chance to execute. Did you know NUnit already supports this via delayed constraints.

In the example below we are testing that the LongRunningCalculationAsync method raises the Completed event. Instead of using wait handles we are testing the assertion using polling. We check the result every 100 milliseconds until the check passes or we run out of time.

[Test]
public void Completed_Event_Should_Be_Raised()
{
    var calculator = new Calculator();    
    var eventRaised = false;
    calculator.LongRunningCalculationCompleted += (sender, args) 
        => { eventRaised = true; };

    calculator.LongRunningCalculationAsync();

    var delay = TimeSpan.FromSeconds(10).Milliseconds;
    var pollingInterval = 100; // 100 milliseconds
    Assert.That(() => eventRaised, Is.EqualTo(true)
        .After(delay, pollingInterval));
}

I have to say I’m not a big fan of this feature because it makes it too easy to write tests that might pass or fail depending on the current CPU load and internal implementation of the asynchronous method. Even though I prefer using wait handles (which are not perfect either) I already found a valid use case for delayed constraints.

[Test]
public void Last_updated_label_should_be_updated()
{
    using (var appRunner = new ApplicationRunner())
    {
        var button = appRunner.GetControl<Button>("uiaUpdateButton");
        button.RaiseClickEvent();

        var label = appRunner.GetControl<Label>("uiaLastUpdated");
        Assert.That(() => label.Text, 
            Is.Not.EqualTo(string.Empty).After(15000, 100));
    }            
}

Test above is an end to end test and it uses White. In the application clicking the Update button performs asynchronous operation. After the operation is completed label is updated so that the user knows when the screen was last updated. Because White runs the actual executable I can only verify things by asserting on UI changes (text, states etc.). In this case the delayed assertion is a good way to check whether the label has been updated.

Pingbacks and trackbacks (1)+

Comments are closed