refactor: add resource pool node check and return map

This commit is contained in:
guoyuqi 2023-07-17 19:47:04 +08:00 committed by 刘瑞斌
parent 14355b0562
commit c979e9ee7f
9 changed files with 225 additions and 28 deletions

View File

@ -0,0 +1,13 @@
package io.metersphere.sdk.dto;
import io.metersphere.system.domain.TestResourcePool;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class TestResourcePoolReturnDTO extends TestResourcePool {
private TestResourceReturnDTO testResourceReturnDTO;
@Schema(title = "资源池是否在使用中")
private Boolean inUsed;
}

View File

@ -0,0 +1,89 @@
package io.metersphere.sdk.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Map;
/**
*用来返回TestResourceBlob的结构
*/
@Getter
@Setter
public class TestResourceReturnDTO {
/**
* type为 node时, 性能测试的镜像
*/
@Schema(title = "type为node时, 性能测试的镜像")
private String loadTestImage;
/**
* type为 node时, 性能测试jvm配置
*/
@Schema(title = "type为node时, 性能测试jvm配置")
private String loadTestHeap;
/**
* type为 node时, 接口测试 性能测试 node 节点配置
*/
@Schema(title = "type为node时, 接口测试,性能测试node节点配置")
private List<TestResourceNodeDTO> nodesList;
/**
* type为 k8s 接口测试性能测试的ip
*/
@Schema(title = "type为k8s时接口测试性能测试的ip")
private String ip;
/**
* type为 k8s 接口测试性能测试的token
*/
@Schema(title = "type为k8s时接口测试性能测试的token")
private String token;
/**
* type为 k8s 接口测试性能测试的命名空间
*/
@Schema(title = "type为k8s时接口测试性能测试的命名空间")
private String nameSpaces;
/**
* type为 k8s 接口测试性能测试UI测试的最大并发数
*/
@Schema(title = "type为k8s时接口测试性能测试UI测试的最大并发数")
private Integer concurrentNumber;
/**
* type为 k8s 接口测试性能测试的单pod 最大线程数
*/
@Schema(title = "type为k8s时接口测试性能测试的单pod最大线程数")
private Integer podThreads;
/**
* type为 k8s 性能测试自定义JOB模版 string
*/
@Schema(title = " type为k8s时性能测试自定义JOB模版string")
private String jobDefinition;
/**
* type为 k8s 接口测试镜像
*/
@Schema(title = "type为k8s时接口测试镜像")
private String apiTestImage;
/**
* type为 k8s 接口测试deployName
*/
@Schema(title = "type为k8s时接口测试deployName")
private String deployName;
/**
* UI测试的grid配置
*/
@Schema(title = "UI测试的grid配置")
private String uiGrid;
/**
* 关联的组织id集合
*/
@Schema(title = "关联的组织id和名称map")
private Map<String,String> orgIdNameMap;
}

View File

@ -32,11 +32,29 @@ public class NodeResourcePoolService {
restTemplateWithTimeOut.setRequestFactory(httpRequestFactory); restTemplateWithTimeOut.setRequestFactory(httpRequestFactory);
} }
public boolean validate(TestResourceDTO testResourceDTO) { public boolean validate(TestResourceDTO testResourceDTO, Boolean usedApiType) {
List<TestResourceNodeDTO> nodesList = testResourceDTO.getNodesList(); List<TestResourceNodeDTO> nodesList = testResourceDTO.getNodesList();
if (CollectionUtils.isEmpty(nodesList)) { if (CollectionUtils.isEmpty(nodesList)) {
throw new MSException(Translator.get("no_nodes_message")); throw new MSException(Translator.get("no_nodes_message"));
} }
boolean isValid = true;
for (TestResourceNodeDTO testResourceNodeDTO : nodesList) {
if (StringUtils.isBlank(testResourceNodeDTO.getIp())) {
throw new MSException(Translator.get("ip_is_null"));
}
if (StringUtils.isBlank(testResourceNodeDTO.getPort())) {
throw new MSException(Translator.get("port_is_null"));
}
if (testResourceNodeDTO.getConcurrentNumber() == null) {
throw new MSException(Translator.get("concurrent_number_is_null"));
}
if (!usedApiType) {
if (StringUtils.isBlank(testResourceNodeDTO.getMonitor())) {
throw new MSException(Translator.get("monitor_number_is_null"));
}
}
isValid = validateNode(testResourceNodeDTO);
}
//校验节点 //校验节点
List<ImmutablePair<String, String>> ipPort = nodesList.stream() List<ImmutablePair<String, String>> ipPort = nodesList.stream()
.map(resource -> { .map(resource -> {
@ -47,10 +65,6 @@ public class NodeResourcePoolService {
if (ipPort.size() < nodesList.size()) { if (ipPort.size() < nodesList.size()) {
throw new MSException(Translator.get("duplicate_node_ip_port")); throw new MSException(Translator.get("duplicate_node_ip_port"));
} }
boolean isValid = true;
for (TestResourceNodeDTO testResourceNodeDTO : nodesList) {
isValid = validateNode(testResourceNodeDTO);
}
return isValid; return isValid;
} }

View File

@ -12,6 +12,7 @@ import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.*; import io.metersphere.system.domain.*;
import io.metersphere.system.mapper.OrganizationMapper;
import io.metersphere.system.mapper.TestResourcePoolBlobMapper; import io.metersphere.system.mapper.TestResourcePoolBlobMapper;
import io.metersphere.system.mapper.TestResourcePoolMapper; import io.metersphere.system.mapper.TestResourcePoolMapper;
import io.metersphere.system.mapper.TestResourcePoolOrganizationMapper; import io.metersphere.system.mapper.TestResourcePoolOrganizationMapper;
@ -25,9 +26,7 @@ import org.mybatis.spring.SqlSessionUtils;
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.*;
import java.util.List;
import java.util.UUID;
@Slf4j @Slf4j
@Service @Service
@ -117,7 +116,7 @@ public class TestResourcePoolService {
if (StringUtils.equalsIgnoreCase(type, ResourcePoolTypeEnum.NODE.name())) { if (StringUtils.equalsIgnoreCase(type, ResourcePoolTypeEnum.NODE.name())) {
NodeResourcePoolService resourcePoolService = CommonBeanFactory.getBean(NodeResourcePoolService.class); NodeResourcePoolService resourcePoolService = CommonBeanFactory.getBean(NodeResourcePoolService.class);
if (resourcePoolService != null) { if (resourcePoolService != null) {
return resourcePoolService.validate(testResourceDTO); return resourcePoolService.validate(testResourceDTO, usedApiType);
} else { } else {
return false; return false;
} }
@ -234,23 +233,39 @@ public class TestResourcePoolService {
} }
} }
public TestResourcePoolDTO getTestResourcePoolDetail(String testResourcePoolId) { public TestResourcePoolReturnDTO getTestResourcePoolDetail(String testResourcePoolId) {
TestResourcePoolDTO testResourcePoolDTO = new TestResourcePoolDTO(); TestResourcePoolReturnDTO testResourcePoolReturnDTO = new TestResourcePoolReturnDTO();
TestResourcePool testResourcePool = testResourcePoolMapper.selectByPrimaryKey(testResourcePoolId); TestResourcePool testResourcePool = testResourcePoolMapper.selectByPrimaryKey(testResourcePoolId);
if (testResourcePool == null) { if (testResourcePool == null) {
throw new MSException(Translator.get("test_resource_pool_not_exists")); throw new MSException(Translator.get("test_resource_pool_not_exists"));
} }
TestResourcePoolBlob testResourcePoolBlob = testResourcePoolBlobMapper.selectByPrimaryKey(testResourcePoolId); TestResourcePoolBlob testResourcePoolBlob = testResourcePoolBlobMapper.selectByPrimaryKey(testResourcePoolId);
if (testResourcePoolBlob == null) { if (testResourcePoolBlob == null) {
BeanUtils.copyBean(testResourcePoolDTO, testResourcePool); BeanUtils.copyBean(testResourcePoolReturnDTO, testResourcePool);
return testResourcePoolDTO; return testResourcePoolReturnDTO;
} }
byte[] configuration = testResourcePoolBlob.getConfiguration(); byte[] configuration = testResourcePoolBlob.getConfiguration();
String testResourceDTOStr = new String(configuration); String testResourceDTOStr = new String(configuration);
TestResourceDTO testResourceDTO = JSON.parseObject(testResourceDTOStr, TestResourceDTO.class); TestResourceDTO testResourceDTO = JSON.parseObject(testResourceDTOStr, TestResourceDTO.class);
BeanUtils.copyBean(testResourcePoolDTO, testResourcePool); TestResourceReturnDTO testResourceReturnDTO = new TestResourceReturnDTO();
testResourcePoolDTO.setTestResourceDTO(testResourceDTO); BeanUtils.copyBean(testResourceReturnDTO, testResourceDTO);
return testResourcePoolDTO; List<String> orgIds = testResourceDTO.getOrgIds();
Map<String,String> orgIdNameMap = new HashMap<>();
if (CollectionUtils.isNotEmpty(orgIds)) {
for (String orgId : orgIds) {
OrganizationMapper organizationMapper = CommonBeanFactory.getBean(OrganizationMapper.class);
Organization organization = organizationMapper.selectByPrimaryKey(orgId);
if (organization != null) {
orgIdNameMap.put(orgId,organization.getName());
} else {
orgIdNameMap.put(orgId,Translator.get("organization_not_exists"));
}
}
}
testResourceReturnDTO.setOrgIdNameMap(orgIdNameMap);
BeanUtils.copyBean(testResourcePoolReturnDTO, testResourcePool);
testResourcePoolReturnDTO.setTestResourceReturnDTO(testResourceReturnDTO);
return testResourcePoolReturnDTO;
} }
public LogDTO addLog(TestResourcePoolRequest request) { public LogDTO addLog(TestResourcePoolRequest request) {

View File

@ -79,6 +79,9 @@ test_resource_pool_not_exists=Test resource pool not exists
test_resource_pool_invalid=Test resource pool invalid test_resource_pool_invalid=Test resource pool invalid
selenium_grid_is_null=selenium_grid cannot be null selenium_grid_is_null=selenium_grid cannot be null
ip_is_null=ip address/domain name cannot be null ip_is_null=ip address/domain name cannot be null
port_is_null = Port cannot be null
concurrent_number_is_null = ConcurrentNumber cannot be null
monitor_is_null = Monitor cannot be null
token_is_null = Token can not be null token_is_null = Token can not be null
namespace_is_null=Namespaces can not be null namespace_is_null=Namespaces can not be null
deploy_name_is_null=Deploy Name cannot be null deploy_name_is_null=Deploy Name cannot be null

View File

@ -62,7 +62,7 @@ startTime_must_be_less_than_endTime=开始日期必须小于结束日期
start_time_is_null=开始日期不能为空 start_time_is_null=开始日期不能为空
end_time_is_null=结束日期不能为空 end_time_is_null=结束日期不能为空
organization_not_exists=工作空间不存在 organization_not_exists=组织不存在
#test resource pool #test resource pool
test_resource_pool_id_is_null=资源池ID不能为空 test_resource_pool_id_is_null=资源池ID不能为空
test_resource_pool_name_is_null=资源池名称不能为空 test_resource_pool_name_is_null=资源池名称不能为空
@ -77,6 +77,9 @@ test_resource_pool_not_exists=测试资源池不存在
test_resource_pool_invalid=当前测试使用的资源池处于禁用状态 test_resource_pool_invalid=当前测试使用的资源池处于禁用状态
selenium_grid_is_null=selenium_grid不能为空 selenium_grid_is_null=selenium_grid不能为空
ip_is_null=ip 地址/域名不能为空 ip_is_null=ip 地址/域名不能为空
port_is_null = 节点端口不能为空
concurrent_number_is_null = 节点最大线程数不能为空
monitor_is_null = node节点监控器不能为空
token_is_null = Token 不能为空 token_is_null = Token 不能为空
namespace_is_null=命名空间不能为空 namespace_is_null=命名空间不能为空
deploy_name_is_null=Deploy Name 不能为空 deploy_name_is_null=Deploy Name 不能为空

View File

@ -63,7 +63,7 @@ start_time_is_null=開始日期不能為空
end_time_is_null=結束日期不能為空 end_time_is_null=結束日期不能為空
#organization #organization
organization_not_exists=工作空間不存在 organization_not_exists=組織不存在
#test resource pool #test resource pool
test_resource_pool_id_is_null=資源池ID不能為空 test_resource_pool_id_is_null=資源池ID不能為空
test_resource_pool_name_is_null=資源池名稱不能為空 test_resource_pool_name_is_null=資源池名稱不能為空
@ -79,6 +79,9 @@ test_resource_pool_not_exists=測試資源池不存在
test_resource_pool_invalid=當前測試使用的資源池處於禁用狀態 test_resource_pool_invalid=當前測試使用的資源池處於禁用狀態
selenium_grid_is_null=selenium_grid不能為空 selenium_grid_is_null=selenium_grid不能為空
ip_is_null=ip 地址/域名不能為空 ip_is_null=ip 地址/域名不能為空
port_is_null = 節點端口不能為空
concurrent_number_is_null = 節點最大線程數不能為空
monitor_is_null = node節點監控器不能為空
token_is_null = Token 不能為空 token_is_null = Token 不能為空
namespace_is_null=命名空間不能為空 namespace_is_null=命名空間不能為空
deploy_name_is_null=Deploy Name 不能為空 deploy_name_is_null=Deploy Name 不能為空

View File

@ -6,6 +6,7 @@ import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.dto.QueryResourcePoolRequest; import io.metersphere.sdk.dto.QueryResourcePoolRequest;
import io.metersphere.sdk.dto.TestResourcePoolDTO; import io.metersphere.sdk.dto.TestResourcePoolDTO;
import io.metersphere.sdk.dto.TestResourcePoolRequest; import io.metersphere.sdk.dto.TestResourcePoolRequest;
import io.metersphere.sdk.dto.TestResourcePoolReturnDTO;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.service.TestResourcePoolService; import io.metersphere.sdk.service.TestResourcePoolService;
@ -78,7 +79,7 @@ public class TestResourcePoolController {
@GetMapping("/detail/{poolId}") @GetMapping("/detail/{poolId}")
@Operation(summary = "查看资源池详细") @Operation(summary = "查看资源池详细")
@RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ) @RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ)
public TestResourcePoolDTO getTestResourcePoolDetail(@PathVariable(value = "poolId") String testResourcePoolId) { public TestResourcePoolReturnDTO getTestResourcePoolDetail(@PathVariable(value = "poolId") String testResourcePoolId) {
return testResourcePoolService.getTestResourcePoolDetail(testResourcePoolId); return testResourcePoolService.getTestResourcePoolDetail(testResourcePoolId);
} }

View File

@ -6,6 +6,7 @@ import io.metersphere.sdk.constants.ResourcePoolTypeEnum;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.controller.handler.ResultHolder; import io.metersphere.sdk.controller.handler.ResultHolder;
import io.metersphere.sdk.dto.TestResourceDTO; import io.metersphere.sdk.dto.TestResourceDTO;
import io.metersphere.sdk.dto.TestResourceNodeDTO;
import io.metersphere.sdk.dto.TestResourcePoolRequest; import io.metersphere.sdk.dto.TestResourcePoolRequest;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.dto.QueryResourcePoolRequest; import io.metersphere.sdk.dto.QueryResourcePoolRequest;
@ -28,6 +29,7 @@ import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
@ -69,6 +71,7 @@ class TestResourcePoolControllerTests extends BaseTest {
"\"deployName\":\"hello\",\n" + "\"deployName\":\"hello\",\n" +
"\"uiGrid\":\"localhost:4444\"\n" + "\"uiGrid\":\"localhost:4444\"\n" +
"}"; "}";
private static final String configuration = "{\n" + private static final String configuration = "{\n" +
" \"loadTestImage\": \"123\",\n" + " \"loadTestImage\": \"123\",\n" +
" \"loadTestHeap\": \"123\",\n" + " \"loadTestHeap\": \"123\",\n" +
@ -344,19 +347,43 @@ class TestResourcePoolControllerTests extends BaseTest {
url = TEST_RESOURCE_POOL_UPDATE; url = TEST_RESOURCE_POOL_UPDATE;
} }
TestResourcePoolRequest testResourcePoolRequest = generatorDto(true, false, false, false); TestResourcePoolRequest testResourcePoolRequest = generatorDto(true,true, false, false, false, false,false,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER); this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池类型为空 //资源池类型为空
testResourcePoolRequest = generatorDto(false, true, false, false); testResourcePoolRequest = generatorDto(true, false, true, false, false, false,false,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER); this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点集合为空 //api 类型 资源池节点集合为空
testResourcePoolRequest = generatorDto(false, false, true, false); testResourcePoolRequest = generatorDto(true, false, false, true, false, false,false,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点不为空但是内容为空 ip 为空
testResourcePoolRequest = generatorDto(true, false, false, true, false, true,false,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点不为空但是内容为空 port 为空
testResourcePoolRequest = generatorDto(true, false, false, true, false, false,true,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点不为空但是内容为空 最大线程数 为空
testResourcePoolRequest = generatorDto(true, false, false, true, false, false,false,false,true);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//性能测试类型 资源池节点集合为空
testResourcePoolRequest = generatorDto(false, false, false, true, false, false,false,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点不为空但是内容为空ip为空
testResourcePoolRequest = generatorDto(false, false, false, true, false, true,false,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点不为空但是内容为空 port 为空
testResourcePoolRequest = generatorDto(false, false, false, true, false, false,true,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点不为空但是内容为空 port 为空
testResourcePoolRequest = generatorDto(false, false, false, true, false, false,false,true,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//资源池节点不为空但是内容为空 最大线程数 为空
testResourcePoolRequest = generatorDto(false, false, false, true, false, false,false,false,true);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER); this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//应用组织 //应用组织
testResourcePoolRequest = generatorDto(false, false, false, true); testResourcePoolRequest = generatorDto(true,false, false, false, true, false,false,false,false);
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER); this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
//部分组织 //部分组织
testResourcePoolRequest = generatorDto(false, false, false, false); testResourcePoolRequest = generatorDto(true,false, false, false, false, false, false,false,false);
testResourcePoolRequest.setAllOrg(false); testResourcePoolRequest.setAllOrg(false);
testResourcePoolRequest.setTestResourceDTO(JSON.parseObject(configurationWidthOutOrgIds, TestResourceDTO.class)); testResourcePoolRequest.setTestResourceDTO(JSON.parseObject(configurationWidthOutOrgIds, TestResourceDTO.class));
this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER); this.requestPost(url, testResourcePoolRequest, ERROR_REQUEST_MATCHER);
@ -398,7 +425,7 @@ class TestResourcePoolControllerTests extends BaseTest {
.andExpect(content().contentType(MediaType.APPLICATION_JSON)); .andExpect(content().contentType(MediaType.APPLICATION_JSON));
} }
private TestResourcePoolRequest generatorDto(boolean noName, boolean noType, boolean noResources, boolean noAllOrg) { private TestResourcePoolRequest generatorDto(boolean useApiType, boolean noName, boolean noType, boolean noResources, boolean noAllOrg, boolean noIp, boolean noPort, boolean noMonitor, boolean noConcurrentNumber) {
TestResourcePoolRequest testResourcePoolDTO = new TestResourcePoolRequest(); TestResourcePoolRequest testResourcePoolDTO = new TestResourcePoolRequest();
//没名字 //没名字
if (!noName) { if (!noName) {
@ -413,9 +440,38 @@ class TestResourcePoolControllerTests extends BaseTest {
testResourcePoolDTO.setApiTest(true); testResourcePoolDTO.setApiTest(true);
setResources(testResourcePoolDTO,true); setResources(testResourcePoolDTO,true);
}else { }else {
testResourcePoolDTO.setApiTest(true); testResourcePoolDTO.setApiTest(useApiType);
testResourcePoolDTO.setLoadTest(!useApiType);
TestResourceDTO testResourceDTO = JSON.parseObject(configuration, TestResourceDTO.class); TestResourceDTO testResourceDTO = JSON.parseObject(configuration, TestResourceDTO.class);
//有资源池用途为API 或者 性能测试的校验 IP port monitor ConcurrentNumber 为空
TestResourceNodeDTO testResourceNodeDTO = new TestResourceNodeDTO();
if (noIp) {
testResourceNodeDTO.setIp("");
} else {
testResourceNodeDTO.setIp("172.2.130.1");
}
if (noPort) {
testResourceNodeDTO.setPort("");
} else {
testResourceNodeDTO.setPort("3306");
}
if (noMonitor) {
testResourceNodeDTO.setMonitor(" ");
} else {
testResourceNodeDTO.setMonitor("11");
}
if (noConcurrentNumber){
testResourceNodeDTO.setConcurrentNumber(null);
} else {
testResourceNodeDTO.setConcurrentNumber(1);
}
if (!noIp && !noPort && !noMonitor && ! noConcurrentNumber) {
testResourceDTO.setNodesList(null); testResourceDTO.setNodesList(null);
} else {
List<TestResourceNodeDTO>testResourceNodeDTOS = new ArrayList<>();
testResourceNodeDTOS.add(testResourceNodeDTO);
testResourceDTO.setNodesList(testResourceNodeDTOS);
}
testResourcePoolDTO.setTestResourceDTO(testResourceDTO); testResourcePoolDTO.setTestResourceDTO(testResourceDTO);
} }
//没选全部 //没选全部