views:

242

answers:

4

So I have a test case that I want to make into a thread. I cannot extend Thread nor can I implement runnable since TestCase already has a method void run(). The compilation error I am getting is Error(62,17): method run() in class com.util.SeleneseTestCase cannot override method run() in class junit.framework.TestCase with different return type, was class junit.framework.TestResult.

What I am trying to do is to scale a Selenium testcase up to perform stress testing. I am not able to use selenium grid/pushtotest.com/amazon cloud at this time (installation issues/install time/resource issues). So this really is more of a Java language issue for me.

FYI: SeleniumTestCase is what I want to make multi threaded to scale it up for stress testing. SelniumTestCase extends TestCase (from junit). I am extending SeleniumTestCase and trying to make it implement Runnable.

+4  A: 

In this case, you don't have other option: you have to delegate to another object instead of inheritance.

thSoft
+6  A: 

Create a inner class that implements Runnable and call it from a new Thread in com.util.SeleneseTestCase run() method. Something like this:

class YourTestCase extends SeleneseTestCase {
    public class MyRunnable implements Runnable {
        public void run() {
            // Do your have work here
        }
    }

    public void testMethodToExecuteInThread() {
        MyRunnable r = new MyRunnable();
        Thread t = new Thread(r);
        t.start();
    }
}

Update to use outside YourTestCase class

To run an inner class from another class you would need to make it public and then from the outer class execute this:

YourTestCase testCase = new YourTestCase();
YourTestCase.MyRunnable r = testCase.new MyRunnable();

But if you don't need to call it from inside your test case you'd better go with a normal class, make MyRunnable a public class without being in YourTestCase.

Hope it helps.

Felipe Cypriano
This won't compile since `void run()` can't be defined inside of SeleneseTestCase.
Zombies
Just remove void run() from YourTestCase and use the appropriate method from SeleneseTestCase, but you can keep the implementation to call MyRunnable. I don't know Selenium I can't exactly which method you should override, but this the idea.
Felipe Cypriano
Hm, I can't seem to instantiate the Runnable inner class outside of that class, which is what I am trying to do. For example, ` new Thread(YourTestCase.MyRunnable.class.newInstance()).start();` causes an InstantiationException.
Zombies
Edited to show how to instantiate an inner class from any other class.
Felipe Cypriano
A: 

extending TestCase is almost certainly not the correct OO model anyhow. model with "has a" not "is a". that is, create a new class that extends thread, and use instances of that class within your test methods.

farble1670
Extends Thread class isn't a correct OO model either, unless you're adding behavior specific for threads which isn't common. Implements Runnable is the best option when we want to execute things in another thread
Felipe Cypriano
+1  A: 

Keep in mind that if the thread throws any exceptions, the test would not necessarily fail. Instead of using Runnable and Thread, you might want to use ExecutorService.submit(Callable<T>):

public class SeleneseTestCase extends SeleniumTestCase {
  private class StressServer implements Callable<Void> {
    public Void call() {
      // do your work here
      return null;
    }
  }

  public void testUnderLoad() throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(
        NUM_CONCURRENT_WORKERS);
    List<Callable<Void>> stressers = new ArrayList<Callable<Void>>();
    for (int i = 0; i < NUM_WORKERS; i++) }
      stressers.add(new StressServer());
    }
    List<Future<Void>> futures =if ( executorService.invokeAll(
        stressers, TIMEOUT_IN_SECS, TimeUnit.SECONDS);
    for (Future<Void> future : futures) {
      if (!future.isCancelled()) {
        future.get(1, TimeUnit.MILLISECONDS); // may throw exception
      }
    }
    executorService.shutdown();
  }
}

Note if you want the workers to return the result, you can change the type of StressServer to Callable<YourResultType>

NamshubWriter
Heheh. I did end up doing this.
Zombies