Radoslav Hristov
Radoslav Hristov

Reputation: 1053

Timeout for individual tests in NUnit

I'm aware that there is a Timeout attribute in NUnit. My problem is that the unit tests actually spawn a new process which, if frozen, is never killed by NUnit. How can I implement a timeout which will actually get rid of the rogue process?

Upvotes: 22

Views: 12184

Answers (5)

rklec
rklec

Reputation: 177

In new NUnit versions (could not find out when it was added in the changelog), you can use the CancelAfterAttribute (current source code). See the linked docs, it works very simple by taking a CancellationToken as a parameter that is cancelled after the timeout:

[Test, CancelAfter(2000)]
public void RunningTestUntilCanceled(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        /* */
    }
}

[CancelAfter(2000)]
[TestCase("http://server1")]
[TestCase("http://server2")]
public async Task PotentiallyLongRunningTest(string uri, CancellationToken token)
{
    HttpClient client = _httpClientFactory.CreateClient();
    HttpContent content = CreateContent();
    await client.PostAync(uri, content, token);
    HttpResponseMessage response = await client.GetAsync(uri, token);
    /* */
}

Edit: Given the git repo the feature was likely added in NUnit 4, which this doc seems to confirm.

Upvotes: 0

razon
razon

Reputation: 4030

[Test, Timeout(2000)]
public void PotentiallyLongRunningTest()
{
    ...
}

http://www.nunit.org/index.php?p=timeout&r=2.5.1 :

The TimeoutAttribute is used to specify a timeout value in milliseconds for a test case. If the test case runs longer than the time specified it is immediately cancelled and reported as a failure, with a message indicating that the timeout was exceeded.

The attribute may also be specified on a fixture or assembly, in which case it indicates the default timeout for any subordinate test cases.

Upvotes: 5

ashes999
ashes999

Reputation: 10163

Edit: The accepted answer is a better one.

If your test eventually times out (albeit later than you hope), you can always use the MaxTime attribute: http://www.nunit.org/index.php?p=maxtime&r=2.5.1 and clean up the thread yourself:

[Test, Maxtime(2000)]
public void TimedTest()
{
    ...
}

Otherwise, your best option might be to implement your own timing mechanism. Use a timer (or a busy while loop) and if the timeout is exceeded, then kill the process (maybe in the ShutDown method if it's generic across tests) and signal failure.

NUnit timeouts don't have any events that allow you to run code after the test times out. You have to roll your own, it looks like.

Upvotes: 6

Radoslav Hristov
Radoslav Hristov

Reputation: 1053

OK. After I've tried all the features built in NUnit and failed to achieve what I needed, I did the following: I've added a timer which is being set in a function attributed [SetUp] on a fixture level and thus is called before each Test. If the timer ticks before the test has finished, I just do the clean-up in the timer callback.

Upvotes: 0

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236188

You can use timeout for assertion, instead of timeout for whole test method:

Assert.That(actual, Is.EqualTo(expected).After(5000, 50));

Upvotes: 18

Related Questions