我的开发日记(九)
昨天由于有个项目上线,所以通了个宵,今早起来比较晚,工作进度又落下来一截,心里更加慌慌了。这两天的主要任务还是搬砖了,只有一个地方值得记一下,就是异步执行测试用例,并收集结果。其中涉及到了线程池的创建,基本多线程对象的设计,多用例并行执行。这里面用到的多个用例如果同时使用同一个用户的登录凭证和用户登录凭证缓存。
我的基本方案如下:先用多线程把用例里面的使用到的用户凭证替换成真正的值,然后再去将处理好的用例信息丢给线程池去执行,然后等待所有的线程执行完,测试结果处理等等。
- 有好多TODO内容,过完端午节补上。
多线程类
package com.okay.family.common;import com.okay.family.common.basedata.OkayConstant;
import com.okay.family.common.bean.testcase.CaseRunRecord;
import com.okay.family.common.bean.testcase.request.CaseDataBean;
import com.okay.family.common.enums.RunResult;
import com.okay.family.common.exception.CommonException;
import com.okay.family.common.exception.UserStatusException;
import com.okay.family.utils.RunCaseUtil;
import java.util.concurrent.CountDownLatch;
public class CaseRunThread implements Runnable {
int runId;
CaseDataBean bean;
CaseRunRecord record;
CountDownLatch countDownLatch;
public CaseRunRecord getRecord() {
return record;
}
private CaseRunThread() {
}
public CaseRunThread(CaseDataBean bean, CountDownLatch countDownLatch, int runId) {
this.bean = bean;
this.countDownLatch = countDownLatch;
this.runId = runId;
this.record = new CaseRunRecord();
}
@Override
public void run() {
try {
record = RunCaseUtil.run(bean);
} catch (UserStatusException e) {
record.setResult(RunResult.USER_ERROR.getCode());
} catch (CommonException e) {
record.setResult(RunResult.UNRUN.getCode());
} catch (Exception e) {
record.setResult(RunResult.UNRUN.getCode());
} finally {
countDownLatch.countDown();
}
}
private void init() {
record.setMark(OkayConstant.RUN_MARK.getAndIncrement());
record.setRunId(runId);
record.setCaseId(bean.getId());
//todo:完成基本功能的初始化
}
}
线程池类
比较简单,具体功能还得后续完善。
package com.okay.family.common;import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class OkayThreadPool {
private static ThreadPoolExecutor executor = createPool();
public static void addSyncWork(Runnable runnable) {
executor.execute(runnable);
}
private static ThreadPoolExecutor createPool() {
return new ThreadPoolExecutor(5, 50, 10, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(1000));
}
}
执行用例集的具体方法
@Override public CollectionRunSimpleResutl runCollection(RunCollectionBean bean) {
List<CaseDataBean> cases = getCasesDeatil(bean);
CountDownLatch countDownLatch = new CountDownLatch(cases.size());
int andIncrement = OkayConstant.COLLECTION_MARK.getAndIncrement();
List<CaseRunThread> results = new ArrayList<>();
String start = Time.getDate();
cases.forEach(x -> {
CaseRunThread caseRunThread = new CaseRunThread(x, countDownLatch, andIncrement);
OkayThreadPool.addSyncWork(caseRunThread);
results.add(caseRunThread);
});
try {
countDownLatch.await();
} catch (InterruptedException e) {
CommonException.fail("执行用例集失败!");
}
String end = Time.getDate();
//todo:处理结果,记录结果,返回结果
results.forEach(x -> caseService.addRunRecord(x.getRecord()));
Map<Integer, List<Integer>> collect = results.stream().map(x -> x.getRecord().getResult()).collect(Collectors.groupingBy(x -> x));
CollectionRunSimpleResutl res = new CollectionRunSimpleResutl();
//todo:初始化res
return res;
}
处理用例中的用户凭证和参数的方法
@Override public List<CaseDataBean> getCasesDeatil(RunCollectionBean bean) {
ConcurrentHashMap<Integer, String> certificates = new ConcurrentHashMap<>();
List<CaseDataBean> cases = caseCollectionMapper.getCasesDeatil(bean);
CountDownLatch countDownLatch = new CountDownLatch(cases.size());
cases.forEach(x -> {
new Thread(() -> {
try {
caseService.handleParams(x, certificates);
}finally {
countDownLatch.countDown();
}
}).start();
});
try {
countDownLatch.await();
} catch (InterruptedException e) {
CommonException.fail("初始化用例信息失败!");
}
return cases;
}
下面是caseService.handleParams
方法内容,参数带map
的都是多线程用的
@Override public void handleParams(CaseDataBean bean) {
JSONObject params = bean.getParams();
JSONObject headers = bean.getHeaders();
handleParams(params);
handleParams(headers);
}
@Override
public void handleParams(CaseDataBean bean, ConcurrentHashMap<Integer, String> map) {
JSONObject params = bean.getParams();
JSONObject headers = bean.getHeaders();
handleParams(params, map);
handleParams(headers, map);
}
/**
* 处理参数中的表达式信息
*
* @param params
*/
public void handleParams(JSONObject params) {
params.keySet().stream().forEach(key ->
{
String value = params.getString(key);
if (value.startsWith(OkayConstant.USER_CERTIFICATE_KEY)) {
int id = SourceCode.changeStringToInt(value.substring(OkayConstant.USER_CERTIFICATE_KEY.length()));
TestUserCheckBean userCheckBean = testUserService.getCertificate(id);
params.put(key, userCheckBean.getCertificate());
} else if (value.startsWith(OkayConstant.RANDOM_KEY)) {
String replace = value.replace(OkayConstant.RANDOM_KEY, Constant.EMPTY);
String[] split = replace.split(",", 2);
params.put(key, SourceCode.getRandomIntRange(SourceCode.changeStringToInt(split[0]), SourceCode.changeStringToInt(split[1])));
}
});
}
/**
* 处理参数中的表达式信息
*
* @param params
*/
public void handleParams(JSONObject params, ConcurrentHashMap map) {
params.keySet().stream().forEach(key ->
{
String value = params.getString(key);
if (value.startsWith(OkayConstant.USER_CERTIFICATE_KEY)) {
int id = SourceCode.changeStringToInt(value.substring(OkayConstant.USER_CERTIFICATE_KEY.length()));
String certificate = testUserService.getCertificate(id, map);
params.put(key, certificate);
} else if (value.startsWith(OkayConstant.RANDOM_KEY)) {
String replace = value.replace(OkayConstant.RANDOM_KEY, Constant.EMPTY);
String[] split = replace.split(",", 2);
params.put(key, SourceCode.getRandomIntRange(SourceCode.changeStringToInt(split[0]), SourceCode.changeStringToInt(split[1])));
}
});
}
- 一般存储运行记录我都会用异步,所以基本上算下来,运行时间应该在10s以内,用例集的运行会很快。不用点击运行之后,还得等一会儿才能看到结果。
- 公众号FunTester首发,欢迎关注,禁止第三方擅自转载,合作请联系
Fhaohaizi@163.com
。
热文精选
- 接口功能测试专辑
- 性能测试专题
- 测开笔记
- 图解HTTP脑图
- 写给所有人的编程思维
- Selenium并行测试最佳实践
- 如何维护自动化测试
- 有关UI测试计划
- Selenium自动化测试技巧
以上是 我的开发日记(九) 的全部内容, 来源链接: utcz.com/z/517816.html