Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi threading unit test

I have a C# method that will be called multiple times using different threads. So I want to create a unit test that will test this method on several threads, but I'm not sure I'm doing it right.

This is my unit test without threading:

    [TestMethod]
    public void FromLocalPoints()
    {
        var projectedCoordinates = this.ConvertFromLocalPoints();
        foreach (var projectedCoordinate in projectedCoordinates)
        {
            Debug.Write(projectedCoordinate.X);
            Debug.Write("; ");
            Debug.WriteLine(projectedCoordinate.Y);
        }
    }

this.ConvertFromLocalPoints() is calling the actual method I want to test.

I've created a delegate, an event and an handler:

public delegate void ReprojectCompleteHandler(IEnumerable<Coordinate> projectedCoordinates);
public event ReprojectCompleteHandler ReprojectCompleteEvent;
private void ReprojectHandler(IEnumerable<Coordinate> projectedCoordinates)
{
        Debug.WriteLine("Conversion is complete");
}

In my TestSetup I listen to my event:

    [TestInitialize]
    public void TestSetup()
    {
        this.ReprojectCompleteEvent += this.ReprojectHandler;
    }

My unit test is:

    [TestMethod]
    public void FromLocalPointsThreaded()
    {
        // Call FromLocalPoints multiple times in separate threads to check if it is thread safe
        for (var i = 0; i < 10; i++)
        {
            var myThread = new Thread(this.ConvertFromLocalPointsThreaded);    
        }

        Debug.WriteLine("FromLocalPointsThreaded is done");
    }

    private void ConvertFromLocalPointsThreaded()
    {
        var projectedCoordinates = this.ConvertFromLocalPoints();

        // Send result to delegate/event:
        if (this.ReprojectCompleteEvent != null)
        {
            this.ReprojectCompleteEvent(projectedCoordinates);
        }
    }

When I run this unit test I get once 'FromLocalPointsThreaded is done' in my output but no 'Conversion is complete'.

What am I missing to get this working? Or should I use a different approach?

Update We're currently switching libraries which is doing the actual conversion. The old library isn't thread-safe so we added locks. The new library should be thread-safe so I want to remove the locks. But I need a unit test which will prove our method using the new lib is really thread-safe.

like image 874
Paul Meems Avatar asked Jun 02 '15 08:06

Paul Meems


People also ask

What is multithreaded testing?

Multithread testing: Multithreaded testing is where concurrent transactions of an application are running at the same time. It can run on a single machine or distribute across multiple machines.

How can I test my multithreaded application?

Test your multithreaded program by having multiple instances of the program active at the same time. If your application allows the number of threads to vary, configure each instance of the program with a different number of threads.

Is junit multithreaded?

4.1 concurrent-junitConcurrent-junit library helps the users to test the methods for multi threading. It will create threads for testing methods. By default, number of threads created by this library is 4, but we can set the desired number of threads.

Why is testing multithreaded concurrent code so difficult?

Testing a multithreaded application is more difficult than testing a single-threaded application because defects are often timing-related and more difficult to reproduce. Existing code often requires significant re-architecting to take advantage of multithreading and multicontexting.


1 Answers

One of the properties of good Unit test is that it need to be repeatable. Every time it is run, it should run in same way as before. This is simply not possible with threading. For example, the test might run properly 999 times, but hit the deadlock 1 time. Meaning the thread is not only useless, but gives you false sense of confidence that your code actually doesn't have deadlock.

For testing threading safety, there are few other ways to accomplish it:

Mock out the threading

Extract away the threaded code and replace it with abstraction that can be mocked in test. This way, the unit test code will simulate multiple threads without threading itself being an issue. But this requires you knowing all possible paths threads can go through your code, making it useless for anything complex.

This can also be helped by using immutable data structures and pure methods. The tested code then is limited to small portion of code that will provide synchronization between the threads.

Endurance testing

Design the test to run for extremely long period of time, spawning new threads and calling code all the time. If it runs for few hours without a deadlock, then you get good confidence that there is no deadlock. This cannot be run as part of normal test suite, nor does it give you 100% confidence. But it is much more practical than trying to enumerate all possible ways threads can interact.

like image 138
Euphoric Avatar answered Sep 21 '22 12:09

Euphoric