JUnit4 多线程执行测试用例 (下)
本帖最后由 八戒你干嘛 于 2017-8-8 11:19 编辑由于字数限制,此贴分为两贴,此贴为下贴。
上贴地址⬇️
JUnit4 多线程执行测试用例 (上)
只要在单个测试类前,加上注解:@RunWith(MultiThreadRunner.class),就可以并发的执行用例。
如下图:
http://img.blog.csdn.net/20150507083518280
(三)自定义聚合多个类进行多线程执行的Runner有时我们需要聚合同一个模块的测试类,如果使用@RunWith(Suite.class)@SuiteClasses({A.class,B.class}),当类较多时,需要一一列举,效率不高;可以使用ClasspathSuite,支持过滤,将类名符合一定规则的类聚合,官方文档。
实现代码如下:
package com.weibo.concurrent;
import org.junit.experimental.categories.Categories;
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
import org.junit.runner.Runner;
import org.junit.runners.ParentRunner;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
import org.junit.runners.model.RunnerScheduler;
import com.weibo.common.MbLogger;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author hugang
*
**/
public final class ConcurrentSuite extends ClasspathSuite {
public static Runner MulThread(Runner runner) {
if (runner instanceof ParentRunner) {
// setScheduler(RunnerScheduler scheduler):Sets a scheduler that
// determines the order and parallelization of children
// RunnerScheduler:Represents a strategy for scheduling when
// individual test methods should be run (in serial or parallel)
((ParentRunner) runner).setScheduler(new RunnerScheduler() {
private final ExecutorService fService = Executors
.newCachedThreadPool();
// private final ExecutorService fService =
// Executors.newFixedThreadPool(10);
// Schedule a child statement to run
public void schedule(Runnable childStatement) {
this.fService.submit(childStatement);
}
// Override to implement any behavior that must occur after all
// children have been scheduled
public void finished() {
try {
this.fService.shutdown();
this.fService.awaitTermination(9223372036854775807L,
TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
});
}
return runner;
}
public ConcurrentSuite(final Class<?> klass) throws InitializationError {
// 调用父类ClasspathSuite构造函数
// AllDefaultPossibilitiesBuilder根据不同的测试类定义(@RunWith的信息)返回Runner,使用职责链模式
super(klass, new AllDefaultPossibilitiesBuilder(true) {
@Override
public Runner runnerForClass(Class<?> testClass) throws Throwable {
List<RunnerBuilder> builders = Arrays
.asList(new RunnerBuilder[] { ignoredBuilder(),
annotatedBuilder(), suiteMethodBuilder(),
junit3Builder(), junit4Builder() });
for (RunnerBuilder each : builders) {
// 根据不同的测试类定义(@RunWith的信息)返回Runner
Runner runner = each.safeRunnerForClass(testClass);
if (runner != null)
// 方法级别,多线程执行
return MulThread(runner);
}
return null;
}
});
// 类级别,多线程执行
setScheduler(new RunnerScheduler() {
private final ExecutorService fService = Executors
.newCachedThreadPool();
@Override
public void schedule(Runnable paramRunnable) {
// TODO Auto-generated method stub
fService.submit(paramRunnable);
}
@Override
public void finished() {
// TODO Auto-generated method stub
try {
fService.shutdown();
fService.awaitTermination(Long.MAX_VALUE,
TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
});
}
}
新建一个聚合的IntegrationBeijingOneTests.java文件:
@RunWith(ConcurrentSuite.class)
@ClassnameFilters({"com.weibo.cases.xuelian.*Test", "!.*RemindTest","com.weibo.cases.maincase.*Xuelian"})
@Concurrent
public interface IntegrationBeijingOneTests {
}
再建一个suite文件,XuelianTestSuite.java:
package com.weibo.cases.suite;
import org.junit.experimental.categories.Categories;
import org.junit.runner.RunWith;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Categories.class)
@SuiteClasses( IntegrationBeijingOneTests.class )
public class XuelianTestSuite {
}
直接运行XuelianTestSuite.java即可,执行过程如下:
http://img.blog.csdn.net/20150507083511288
写在最后:设计测试用例时需考虑线程安全。
建议(本组内用例):
1.账号的使用,同一个测试类中每个测试方法之间需使用不同测试账号(之前未考虑并发,串行执行时方法间使用同样账号,没有影响),咱们组V4的用例共1516个,假设每个用例使用3个账号,则同时执行用例时,则需4548个账号,现库里有1617个账号,可能需要增加用户(空间换时间); 当然也可以控制并发执行测试方法的数量,来减少用户的使用,比如可以指定同时5个(可调)测试方法并发执行,当然,执行时间上就会相应的增加。
2.非final的全局变量,全改写到测试方法内定义,变成局部变量。
@Concurrent,我这为什么不识别
页:
[1]