Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Whats the best way to unit test from multiple threads?

Tags:

this kind of follows on from another question of mine.

Basically, once I have the code to access the file (will review the answers there in a minute) what would be the best way to test it?

I am thinking of creating a method which just spawns lots of BackgroundWorker's or something and tells them all load/save the file, and test with varying file/object sizes. Then, get a response back from the threads to see if it failed/succeeded/made the world implode etc.

Can you guys offer any suggestions on the best way to approach this? As I said before, this is all kinda new to me :)

Edit

Following ajmastrean's post:

I am using a console app to test with Debug.Asserts :)


Update

I originally rolled with using BackgroundWorker to deal with the threading (since I am used to that from Windows dev) I soon realised that when I was performing tests where multiple ops (threads) needed to complete before continuing, I realised it was going to be a bit of a hack to get it to do this.

I then followed up on ajmastrean's post and realised I should really be using the Thread class for working with concurrent operations. I will now refactor using this method (albeit a different approach).

like image 451
Rob Cooper Avatar asked Sep 03 '08 12:09

Rob Cooper


People also ask

How do you test threads?

To test multi-thread functionality, let the multiple instances of the application or program to be tested be active at the same time. Run the multi-thread program on different hardware. Thread testing is a form of session testing for which sessions are formed of threads.

What is multi threaded 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.

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.

How do I test a concurrent code?

One good way to test this is to make sure you have access to a multi-cpu machine, then run your test for as long a time/with as many iterations as possible. For example if you have a multithreaded producer consumer algorithm, fill the queue with a good sized list and use 2x as many threads as you might in production.


2 Answers

In .NET, ThreadPool threads won't return without setting up ManualResetEvents or AutoResetEvents. I find these overkill for a quick test method (not to mention kind of complicated to create, set, and manage). Background worker is a also a bit complex with the callbacks and such.

Something I have found that works is

  1. Create an array of threads.
  2. Setup the ThreadStart method of each thread.
  3. Start each thread.
  4. Join on all threads (blocks the current thread until all other threads complete or abort)
public static void MultiThreadedTest()
{
    Thread[] threads = new Thread[count];

    for (int i = 0; i < threads.Length; i++)
    {
        threads[i] = new Thread(DoSomeWork());
    }

    foreach(Thread thread in threads)
    {
        thread.Start();
    }

    foreach(Thread thread in threads)
    {
        thread.Join();
    }
}
like image 143
Anthony Mastrean Avatar answered Oct 22 '22 23:10

Anthony Mastrean


@ajmastrean, since unit test result must be predictable we need to synchronize threads somehow. I can't see a simple way to do it without using events.

I found that ThreadPool.QueueUserWorkItem gives me an easy way to test such use cases

 ThreadPool.QueueUserWorkItem(x => { 
    File.Open(fileName, FileMode.Open);
    event1.Set(); // Start 2nd tread;
    event2.WaitOne(); // Blocking the file;
});
ThreadPool.QueueUserWorkItem(x => { 
    try
    {
        event1.WaitOne(); // Waiting until 1st thread open file
        File.Delete(fileName); // Simulating conflict
    }
    catch (IOException e)
    {
        Debug.Write("File access denied");
    }
});
like image 24
aku Avatar answered Oct 22 '22 23:10

aku