feat(测试计划): 测试计划批量执行方法优化

This commit is contained in:
Jianguo-Genius 2024-06-11 19:30:35 +08:00 committed by 刘瑞斌
parent f46c2a15b5
commit 69f466e071
2 changed files with 113 additions and 44 deletions

View File

@ -31,5 +31,5 @@ public class TestPlanExecutionQueue {
//预生成报告ID //预生成报告ID
private String prepareReportId; private String prepareReportId;
private boolean isLastNode; private boolean lastFinished = false;
} }

View File

@ -21,11 +21,13 @@ import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -42,12 +44,15 @@ public class TestPlanExecuteService {
@Resource @Resource
private RedisTemplate<String, String> redisTemplate; private RedisTemplate<String, String> redisTemplate;
@Resource
private StringRedisTemplate stringRedisTemplate;
public static final String QUEUE_PREFIX_TEST_PLAN_BATCH = "test-plan-batch-execute:";
public static final String QUEUE_PREFIX_TEST_PLAN_GROUP = "test-plan-group-execute:"; public static final String QUEUE_PREFIX_TEST_PLAN_GROUP = "test-plan-group-execute:";
public static final String QUEUE_PREFIX_TEST_PLAN = "test-plan-execute:";
public static final String QUEUE_PREFIX_TEST_PLAN_CASE_TYPE = "test-plan-case-type:";
public static final String QUEUE_PREFIX_TEST_PLAN_COLLECTION = "test-plan-collection-execute:"; public static final String QUEUE_PREFIX_TEST_PLAN_COLLECTION = "test-plan-collection-execute:";
public static final String QUEUE_PREFIX_TEST_CASE = "test-plan-collection-execute:";
public static final String LAST_QUEUE_PREFIX = "last-queue:";
//单独执行测试计划 //单独执行测试计划
/** /**
* 单个执行测试计划 * 单个执行测试计划
@ -62,13 +67,13 @@ public class TestPlanExecuteService {
return executeTestPlanOrGroup(executionQueue); return executeTestPlanOrGroup(executionQueue);
} }
//批量执行测试计划 //批量执行测试计划
public void batchExecuteTestPlan(TestPlanBatchExecuteRequest request, String userId) { public void batchExecuteTestPlan(TestPlanBatchExecuteRequest request, String userId) {
List<String> rightfulIds = testPlanService.selectRightfulIds(request.getExecuteIds()); List<String> rightfulIds = testPlanService.selectRightfulIds(request.getExecuteIds());
if (CollectionUtils.isNotEmpty(rightfulIds)) { if (CollectionUtils.isNotEmpty(rightfulIds)) {
String runMode = request.getRunMode(); String runMode = request.getRunMode();
String queueId = IDGenerator.nextStr(); String queueId = IDGenerator.nextStr();
String queueType = QUEUE_PREFIX_TEST_PLAN_BATCH; String queueType = QUEUE_PREFIX_TEST_PLAN_GROUP;
long pos = 0; long pos = 0;
List<TestPlanExecutionQueue> testPlanExecutionQueues = new ArrayList<>(); List<TestPlanExecutionQueue> testPlanExecutionQueues = new ArrayList<>();
@ -87,8 +92,7 @@ public class TestPlanExecuteService {
testPlanId, testPlanId,
runMode, runMode,
request.getExecutionSource(), request.getExecutionSource(),
IDGenerator.nextStr(), IDGenerator.nextStr(), false
false
) )
); );
} }
@ -120,7 +124,7 @@ public class TestPlanExecuteService {
long pos = 0; long pos = 0;
List<TestPlanExecutionQueue> childrenQueue = new ArrayList<>(); List<TestPlanExecutionQueue> childrenQueue = new ArrayList<>();
String queueId = IDGenerator.nextStr(); String queueId = IDGenerator.nextStr();
String queueType = QUEUE_PREFIX_TEST_PLAN_GROUP; String queueType = QUEUE_PREFIX_TEST_PLAN;
for (TestPlan child : children) { for (TestPlan child : children) {
childrenQueue.add( childrenQueue.add(
new TestPlanExecutionQueue( new TestPlanExecutionQueue(
@ -134,8 +138,7 @@ public class TestPlanExecuteService {
child.getId(), child.getId(),
executionQueue.getRunMode(), executionQueue.getRunMode(),
executionQueue.getExecutionSource(), executionQueue.getExecutionSource(),
IDGenerator.nextStr(), IDGenerator.nextStr(), false
false
) )
); );
} }
@ -145,11 +148,11 @@ public class TestPlanExecuteService {
if (StringUtils.equalsIgnoreCase(executionQueue.getRunMode(), ApiBatchRunMode.SERIAL.name())) { if (StringUtils.equalsIgnoreCase(executionQueue.getRunMode(), ApiBatchRunMode.SERIAL.name())) {
//串行 //串行
TestPlanExecutionQueue nextQueue = this.getNextQueue(queueId, queueType); TestPlanExecutionQueue nextQueue = this.getNextQueue(queueId, queueType);
executeTestPlan(nextQueue); executeTestPlanOrGroup(nextQueue);
} else { } else {
//并行 //并行
childrenQueue.forEach(childQueue -> { childrenQueue.forEach(childQueue -> {
executeTestPlan(childQueue); executeTestPlanOrGroup(childQueue);
}); });
} }
return executionQueue.getPrepareReportId(); return executionQueue.getPrepareReportId();
@ -158,7 +161,7 @@ public class TestPlanExecuteService {
} }
} }
//执行测试计划 //执行测试计划里不同类型的用例 回调caseTypeExecuteQueueFinish
public String executeTestPlan(TestPlanExecutionQueue executionQueue) { public String executeTestPlan(TestPlanExecutionQueue executionQueue) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(executionQueue.getSourceID()); TestPlan testPlan = testPlanMapper.selectByPrimaryKey(executionQueue.getSourceID());
TestPlanCollectionExample testPlanCollectionExample = new TestPlanCollectionExample(); TestPlanCollectionExample testPlanCollectionExample = new TestPlanCollectionExample();
@ -174,7 +177,7 @@ public class TestPlanExecuteService {
String runMode = StringUtils.isBlank(testPlanConfig.getCaseRunMode()) ? ApiBatchRunMode.SERIAL.name() : testPlanConfig.getCaseRunMode(); String runMode = StringUtils.isBlank(testPlanConfig.getCaseRunMode()) ? ApiBatchRunMode.SERIAL.name() : testPlanConfig.getCaseRunMode();
String queueId = IDGenerator.nextStr(); String queueId = IDGenerator.nextStr();
String queueType = QUEUE_PREFIX_TEST_PLAN_COLLECTION; String queueType = QUEUE_PREFIX_TEST_PLAN_CASE_TYPE;
List<TestPlanExecutionQueue> childrenQueue = new ArrayList<>(); List<TestPlanExecutionQueue> childrenQueue = new ArrayList<>();
for (TestPlanCollection collection : testPlanCollectionList) { for (TestPlanCollection collection : testPlanCollectionList) {
childrenQueue.add( childrenQueue.add(
@ -189,8 +192,7 @@ public class TestPlanExecuteService {
collection.getId(), collection.getId(),
executionQueue.getRunMode(), executionQueue.getRunMode(),
executionQueue.getExecutionSource(), executionQueue.getExecutionSource(),
IDGenerator.nextStr(), IDGenerator.nextStr(), false)
false)
); );
} }
childrenQueue.forEach(childQueue -> { childrenQueue.forEach(childQueue -> {
@ -213,7 +215,7 @@ public class TestPlanExecuteService {
return executionQueue.getPrepareReportId(); return executionQueue.getPrepareReportId();
} }
//执行测试集 //执行测试集 -- 回调collectionExecuteQueueFinish
private void executeByTestPlanCollection(TestPlanExecutionQueue executionQueue) { private void executeByTestPlanCollection(TestPlanExecutionQueue executionQueue) {
TestPlanCollection parentCollection = testPlanCollectionMapper.selectByPrimaryKey(executionQueue.getParentQueueId()); TestPlanCollection parentCollection = testPlanCollectionMapper.selectByPrimaryKey(executionQueue.getParentQueueId());
TestPlanCollectionExample example = new TestPlanCollectionExample(); TestPlanCollectionExample example = new TestPlanCollectionExample();
@ -224,7 +226,7 @@ public class TestPlanExecuteService {
List<TestPlanExecutionQueue> childrenQueue = new ArrayList<>(); List<TestPlanExecutionQueue> childrenQueue = new ArrayList<>();
String queueId = IDGenerator.nextStr(); String queueId = IDGenerator.nextStr();
String queueType = QUEUE_PREFIX_TEST_CASE; String queueType = QUEUE_PREFIX_TEST_PLAN_COLLECTION;
for (TestPlanCollection collection : childrenList) { for (TestPlanCollection collection : childrenList) {
childrenQueue.add( childrenQueue.add(
new TestPlanExecutionQueue( new TestPlanExecutionQueue(
@ -238,8 +240,7 @@ public class TestPlanExecuteService {
collection.getId(), collection.getId(),
executionQueue.getRunMode(), executionQueue.getRunMode(),
executionQueue.getExecutionSource(), executionQueue.getExecutionSource(),
IDGenerator.nextStr(), IDGenerator.nextStr(), false)
false)
); );
} }
childrenQueue.forEach(childQueue -> { childrenQueue.forEach(childQueue -> {
@ -259,56 +260,116 @@ public class TestPlanExecuteService {
// todo @Chen jianxing 执行用例 // todo @Chen jianxing 执行用例
private void executeCase(TestPlanExecutionQueue testPlanExecutionQueue) { private void executeCase(TestPlanExecutionQueue testPlanExecutionQueue) {
String queueId = testPlanExecutionQueue.getQueueId();
String queueType = testPlanExecutionQueue.getQueueType();
TestPlanCollection collection = testPlanCollectionMapper.selectByPrimaryKey(testPlanExecutionQueue.getSourceID());
String runMode = collection.getExecuteMethod();
String environmentId = collection.getEnvironmentId();
if (StringUtils.equalsIgnoreCase(collection.getType(), CaseType.API_CASE.getKey())) {
// todo 执行API用例
} else if (StringUtils.equalsIgnoreCase(collection.getType(), CaseType.SCENARIO_CASE.getKey())) {
// todo 执行场景用例
}
//执行完成之后需要回调 collectionExecuteQueueFinish
} }
//todo 测试用例执行完成中的某一条 //测试集执行完成
private void TestCaseExecuteQueueFinish(String queueID, String queueType) { public void collectionExecuteQueueFinish(String queueID, String queueType) {
/**
* 当队列全部执行完时nextQueue将不会再查到
* 此时如何调用父类队列的执行方式
*/
TestPlanExecutionQueue nextQueue = getNextQueue(queueID, queueType); TestPlanExecutionQueue nextQueue = getNextQueue(queueID, queueType);
if (nextQueue != null) { if (StringUtils.isNotBlank(nextQueue.getQueueId())) {
if (!nextQueue.isLastFinished()) {
try { try {
executeCase(nextQueue); this.executeNextNode(nextQueue);
} catch (Exception e) { } catch (Exception e) {
this.testPlanCollectionExecuteQueueFinish(nextQueue.getParentQueueId(), nextQueue.getParentQueueType()); this.collectionExecuteQueueFinish(nextQueue.getQueueId(), nextQueue.getQueueType());
} }
} else { } else {
// testPlanCollectionExecuteQueueFinish(queueID, queueType); //当前测试集执行完毕
this.caseTypeExecuteQueueFinish(nextQueue.getParentQueueId(), nextQueue.getParentQueueType());
}
} }
} }
//todo 测试集执行完成中的某一条 //测试计划中当前用例类型的全部执行完成
private void testPlanCollectionExecuteQueueFinish(String queueID, String queueType) { private void caseTypeExecuteQueueFinish(String queueID, String queueType) {
TestPlanExecutionQueue nextQueue = getNextQueue(queueID, queueType);
if (StringUtils.isNotBlank(nextQueue.getQueueId())) {
if (!nextQueue.isLastFinished()) {
try {
this.executeNextNode(nextQueue);
} catch (Exception e) {
this.caseTypeExecuteQueueFinish(nextQueue.getQueueId(), nextQueue.getQueueType());
}
} else {
//当前测试计划执行完毕
this.testPlanExecuteQueueFinish(nextQueue.getParentQueueId(), nextQueue.getParentQueueType());
}
}
} }
//todo 测试计划执行完成中的某一条 //测试计划执行完成
private void TestPlanGroupExecuteQueueFinish(String queueID, String queueType) { private void testPlanExecuteQueueFinish(String queueID, String queueType) {
TestPlanExecutionQueue nextQueue = getNextQueue(queueID, queueType);
if (StringUtils.isNotBlank(nextQueue.getQueueId())) {
if (!nextQueue.isLastFinished()) {
try {
this.executeNextNode(nextQueue);
} catch (Exception e) {
this.testPlanExecuteQueueFinish(nextQueue.getQueueId(), nextQueue.getQueueType());
}
} else {
this.testPlanGroupQueueFinish(nextQueue.getParentQueueId(), nextQueue.getParentQueueType());
}
}
} }
//测试计划批量执行队列节点执行完成 //测试计划批量执行队列节点执行完成
private void batchTestPlanExecuteQueueFinish(String queueId, String queueType) { private void testPlanGroupQueueFinish(String queueId, String queueType) {
TestPlanExecutionQueue nextQueue = getNextQueue(queueId, queueType); TestPlanExecutionQueue nextQueue = getNextQueue(queueId, queueType);
if (nextQueue != null) { if (nextQueue != null) {
try { try {
executeTestPlanOrGroup(nextQueue); this.executeNextNode(nextQueue);
} catch (Exception e) { } catch (Exception e) {
this.batchTestPlanExecuteQueueFinish(queueId, queueType); this.testPlanGroupQueueFinish(queueId, queueType);
} }
} }
} }
private void executeNextNode(TestPlanExecutionQueue queue) {
if (StringUtils.equalsIgnoreCase(queue.getQueueType(), QUEUE_PREFIX_TEST_PLAN_GROUP)) {
this.executeTestPlanOrGroup(queue);
} else if (StringUtils.equalsIgnoreCase(queue.getQueueType(), QUEUE_PREFIX_TEST_PLAN)) {
this.executeTestPlan(queue);
} else if (StringUtils.equalsIgnoreCase(queue.getQueueType(), QUEUE_PREFIX_TEST_PLAN_CASE_TYPE)) {
this.executeByTestPlanCollection(queue);
} else if (StringUtils.equalsIgnoreCase(queue.getQueueType(), QUEUE_PREFIX_TEST_PLAN_COLLECTION)) {
this.executeCase(queue);
}
}
private void queueExecuteFinish(TestPlanExecutionQueue queue) {
if (StringUtils.equalsIgnoreCase(queue.getParentQueueType(), QUEUE_PREFIX_TEST_PLAN_GROUP)) {
this.testPlanGroupQueueFinish(queue.getParentQueueId(), queue.getParentQueueType());
} else if (StringUtils.equalsIgnoreCase(queue.getParentQueueType(), QUEUE_PREFIX_TEST_PLAN)) {
this.testPlanExecuteQueueFinish(queue.getParentQueueId(), queue.getParentQueueType());
} else if (StringUtils.equalsIgnoreCase(queue.getParentQueueType(), QUEUE_PREFIX_TEST_PLAN_CASE_TYPE)) {
this.caseTypeExecuteQueueFinish(queue.getParentQueueId(), queue.getParentQueueType());
}
}
/** /**
* 获取下一个队列节点 * 获取下一个队列节点
*/ */
private TestPlanExecutionQueue getNextQueue(String queueId, String queueType) { private TestPlanExecutionQueue getNextQueue(String queueId, String queueType) {
if (StringUtils.isAnyBlank(queueId, queueType)) {
return null;
}
String queueKey = this.genQueueKey(queueId, queueType); String queueKey = this.genQueueKey(queueId, queueType);
ListOperations<String, String> listOps = redisTemplate.opsForList(); ListOperations<String, String> listOps = redisTemplate.opsForList();
String queueDetail = listOps.leftPop(queueKey); String queueDetail = listOps.leftPop(queueKey);
if (StringUtils.isBlank(queueDetail)) { if (StringUtils.isBlank(queueDetail)) {
// 重试3次获取 // 重试3次获取
@ -328,11 +389,18 @@ public class TestPlanExecuteService {
TestPlanExecutionQueue returnQueue = JSON.parseObject(queueDetail, TestPlanExecutionQueue.class); TestPlanExecutionQueue returnQueue = JSON.parseObject(queueDetail, TestPlanExecutionQueue.class);
Long size = getQueueSize(queueId); Long size = getQueueSize(queueId);
if (size == null || size == 0) { if (size == null || size == 0) {
returnQueue.setLastNode(true);
// 最后一个节点清理队列 // 最后一个节点清理队列
deleteQueue(queueKey); deleteQueue(queueKey);
redisTemplate.opsForValue().setIfAbsent(genQueueKey(LAST_QUEUE_PREFIX, queueKey), JSON.toJSONString(returnQueue), 1, TimeUnit.DAYS);
} }
return returnQueue; return returnQueue;
} else {
String lastQueueJson = redisTemplate.opsForValue().getAndDelete(genQueueKey(LAST_QUEUE_PREFIX, queueKey));
if (StringUtils.isNotBlank(lastQueueJson)) {
TestPlanExecutionQueue nextQueue = JSON.parseObject(lastQueueJson, TestPlanExecutionQueue.class);
nextQueue.setLastFinished(true);
return nextQueue;
}
} }
// 整体获取完清理队列 // 整体获取完清理队列
@ -340,6 +408,7 @@ public class TestPlanExecuteService {
return null; return null;
} }
private void deleteQueue(String queueKey) { private void deleteQueue(String queueKey) {
redisTemplate.delete(queueKey); redisTemplate.delete(queueKey);
} }