Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test a method that runs into an infinite loop for some input?

This question just occurred to my mind and I want to ask this here.

The case is intentional, I just write a loop which runs infinitely. How do I go about unit testing it?

I ask this because, this situation may occur anywhere in the code. Say my method delegates to several other methods, and I want to know

  • How it ran into an infinite loop
  • What set of input caused it
  • Call to which method (from this method) has caused this

I have no code written for this. The question is purely for knowledge sake as to what to do if this situation arises in future. Please respond.

like image 756
Shankar Raju Avatar asked May 11 '11 04:05

Shankar Raju


People also ask

How do you test an infinite loop?

You need to replace the code inside the infinite loop with a function. You then write a unit test for that function. Show activity on this post. Obviously you can't test if a loop is really "infinite".

Can you use a for loop in a unit test?

Yes you can have loops in unit test, but with caution. As mentioned by Alex York, loops are acceptable if you test one thing; i.e. one expectation. If you use loops, then I recommend that you must do two things: As mentioned above, test for a non-empty iteration set.

How do you break an infinite loop?

You can press Ctrl + C .

How can a for loop be infinite?

Example. You can run a for loop infinitely by writing it without any exit condition.


3 Answers

How to unit test a method that runs into an infinite loop for some input?

You can test the nearly opposite: "How to unit test a method so that the method will not run longer than Xxxx milliseconds for some input". If this test fails you may have found a candidate with an infinite loop.

NUnit 2.5 has a TimeoutAttribute that makes a test fail if the test takes longer than the given amount of milliseconds.

like image 123
k3b Avatar answered Oct 10 '22 21:10

k3b


Have the function that loops delegate the loop check to an injected dependency:

interface IShouldLoop
{
    bool ShouldLoop();
}

class ClassToTest
{
    private final IShouldLoop shouldLoop;

    public ClassToTest(IShouldLoop shouldLoop)
    {
        this.shouldLoop = shouldLoop;
    }

    public void MethodToTest()
    {
        while(shouldLoop.ShouldLoop())
        {
            // do whatever
        }
    }
}

You can test that it delegates the loop check to the IShouldLoop dependency every time, and you can control the looping in your test, so that it only loops the number of times you want. In the production environment, instantiate it with an instance of IShouldLoop that always returns true.

like image 31
Scott Whitlock Avatar answered Oct 10 '22 21:10

Scott Whitlock


I hope you mean some kind of message-pump/event-handling loop. (Most infinite loops are bad).

I'd ensure that the loop delegates to some class which processes the input. Test this class thoroughly.

The probability of a loop construct failing to work is minimal.. So I'd test this out via an acceptance test or manually.

This is somewhat similar to testing the Main function of an executable. The trick here is also to ensure that Main delegates to a testable class.

like image 7
Gishu Avatar answered Oct 10 '22 23:10

Gishu