Concurrent JUnit Tests with Parameters

白昼怎懂夜的黑 提交于 2019-12-23 16:46:10

问题


So I'm attempting to run parallel parameterized tests. I have a solution where the same test can run in parallel with the parameters supplied for example say I have the following:

@Test
public void someTest1(){
}

@Test
public void someTest2(){
}

I can get someTest1() to run with all the parameters concurrently, but someTest2() will have still have to wait for someTest1() to complete with all parameters before executing. I was wondering if anyone knew of a solution to be able to run someTest1() with all parameters and someTest2() with all parameters concurrently? I've tried tempus-fugit concurrent test runner, which works great for tests that are not parameterized...

Below is code that I have for currently running each parameter test in parallel.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.junit.runners.Parameterized;
import org.junit.runners.model.RunnerScheduler;

/**
 * Class used from the following source:
 * http://jankesterblog.blogspot.com/2011/10
 * /junit4-running-parallel-junit-classes.html
 * 
 * @author Jan Kester
 * 
 */
public class Parallelized extends Parameterized {

    private static class ThreadPoolScheduler implements RunnerScheduler {
        private ExecutorService executor;

        public ThreadPoolScheduler() {
            String threads = System.getProperty("junit.parallel.threads", "16");
            int numThreads = Integer.parseInt(threads);
            executor = Executors.newFixedThreadPool(numThreads);
        }

        public void finished() {
            executor.shutdown();
            try {
                executor.awaitTermination(12, TimeUnit.HOURS);
            } catch (InterruptedException exc) {
                throw new RuntimeException(exc);
            }
        }

        public void schedule(Runnable childStatement) {
            executor.submit(childStatement);
        }
    }

    /**
     * Instantiates a new parallelized.
     * 
     * @param klass
     *            the klass
     * @throws Throwable
     *             the throwable
     */
    public Parallelized(Class<?> klass) throws Throwable {
        super(klass);
        setScheduler(new ThreadPoolScheduler());
    }
}

The code below is an example test, BaseSuite doesn't contain anything of much importance. These are being used with selenium so it just sets the webDriver. The getAllButOpera() method returns a collection of browser types that contain Internet Explorer, Firefox, and Chrome. These parameters are used to run the same test on firefox, ie, and chrome concurrently. I would like to run the two tests in the class at the same time which is what I am having trouble with.

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Collection;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized.Parameters;
import org.openqa.selenium.WebDriver;


/**
 * The Class SampleSuite1.
 * 
 * @author Reid McPherson
 */
@RunWith(Parallelized.class)
public class SampleSuite1 {
    WebDriver driver;
    /**
     * Data.
     * 
     * @return the collection
     */
    @Parameters
    public static Collection<Object[]> data(){
          List<Object[]> browsers = new ArrayList<Object[]>();
    browsers.add(new String[]{"Firefox"});
    browsers.add(new String[]{"Chrome"});
    browsers.add(new String[]{"IE"});
    return browsers;
    }

    /**
     * Instantiates a new sample suite1.
     * 
     * @param type
     *            the type
     */
    public SampleSuite1(String type){
        switch (type) {
    case "FIREFOX":
        driver = new FirefoxDriver();
        break;
    case "IE":
        driver = new InternetExplorerDriver();
        break;
    case "CHROME":
        System.setProperty("webdriver.chrome.driver", PATHTOCHROMEEXE);
        driver = new ChromeDriver();
        break;
    case "OPERA":
        driver = new OperaDriver();
        break;
    default:
        throw new RuntimeException("Browser type unsupported");
    }
    // Set the timeout.
    driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
    }

    /**
     * Sets the up.
     */
    @Before
    public void setUp() {
        driver.get("http://www.google.com");
    }

    /**
     * Test navigation succeeded.
     */
    @Test
    @TestDescription("Navigation Test")
    public void navigationShouldSucceed() {
        String pageSource = driver.getPageSource();
        assertTrue(pageSource.contains("Google"));
    }

    /**
     * Test title.
     */
    @Test
    @TestDescription("This method tests the web page title.")
    public void titleShouldBeGoogle() {
        assertEquals(driver.getTitle(), "Google");
    }

    @After
    public void finished(){
    driver.close();
    }


}

回答1:


As I told the question is in implementation of JUnit.

You can see that:

Parallelized extends Parametrized extends Suite extends ParentRunner

on the other hand:

ConcurrentTestRunner extends BlockJUnit4ClassRunner extends ParentRunner

hence they are from different hierarchies of inheritance.

And now what you have to look at is implementation of the:

org.junit.runners.ParentRunner#getChildren

method. For the org.junit.runners.BlockJUnit4ClassRunner it is:

protected List<FrameworkMethod> computeTestMethods() {
    return getTestClass().getAnnotatedMethods(Test.class);
}

which generates all methods with annotations. But for org.junit.runners.Parameterized it is:

for (int i= 0; i < parametersList.size(); i++)
  runners.add(newtestClassRunnerForParameters(getTestClass().getJavaClass(),
                parametersList, i));

And the last one gives only classes.

Proposal: override your Parallelized class with definition of org.junit.runners.ParentRunner#getChildren from BlockJUnit4ClassRunner.




回答2:


Thanks for the help, I ended up using code from here in addition to running concurrent suites and it gave me the ability to run the tests simultaneously, but it will not run the same test at the same time.




回答3:


I am also using the code from Jeeunit... however even the version 1.0 has a bug.

In the ConcurrentRunnerScheduler the finished method must be implemented.

So I just pulled the code and implemented it like the suiteFinished() method:

@Override
    public void finished() {
        try {
        while (!tasks.isEmpty())
            tasks.remove(completionService.take());
    }
    catch (InterruptedException e) {
        System.out.println("suite fin");
        Thread.currentThread().interrupt();
    }
    finally {
        while (!tasks.isEmpty())
            tasks.poll().cancel(true);
        executorService.shutdownNow();
    }

}



回答4:


This is what I have tried, and it works really well for me.

public class ParallelTests {
   static ExecutorService eService ;
   public static void main(String[] args) {
      testA() ;
      testB() ;
      testC() ;
   }
   public static void testA() {
      eService = Executors.newCachedThreadPool() ;
      for (int i = 0 ; i < 10 ; i++) {
         TestA testA = new TestA() ;
         eService.execute(testA) ;
      }
      eService.shutdown() ;
      while(!eService.isShutDown()) {
      }
   }
//same for testB and testC
}

public class TestA implements Runnable {
    public TestA() {
    }
    @Test
    public myTest throws Throwable {
    }
}


来源:https://stackoverflow.com/questions/10141648/concurrent-junit-tests-with-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!