fix(测试跟踪): 修复接口调用没有关联可执行用例测试计划执行时没有提示的缺陷 (#16502)

--bug=1015449 --user=王孝刚
[测试计划]github#16371测试计划里只包含功能用例,在页面无法执行,但是调用API可以执行,且可正常生成报告,报告里无任何信息
https://www.tapd.cn/55049933/s/1214889

Co-authored-by: wxg0103 <727495428@qq.com>
This commit is contained in:
MeterSphere Bot 2022-08-01 09:47:03 +08:00 committed by GitHub
parent dc17466990
commit 08519bc6e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 440 additions and 353 deletions

View File

@ -45,5 +45,8 @@ public interface ExtTestPlanApiCaseMapper {
Long getPreOrder(@Param("planId") String planId, @Param("baseOrder") Long baseOrder);
Long getLastOrder(@Param("planId") String planId, @Param("baseOrder") Long baseOrder);
List<TestPlanApiCase> selectByIdsAndStatusIsNotTrash(@Param("ids") List<String> ids);
}

View File

@ -4,27 +4,45 @@
<insert id="insertIfNotExists" parameterType="io.metersphere.base.domain.TestPlanApiCase">
INSERT INTO test_plan_api_case(id, test_plan_id, api_case_id, environment_id, create_time, update_time, create_user, `order`)
SELECT #{request.id}, #{request.testPlanId}, #{request.apiCaseId}, #{request.environmentId}, #{request.createTime}, #{request.updateTime}, #{request.createUser}, #{request.order}
INSERT INTO test_plan_api_case(id, test_plan_id, api_case_id, environment_id, create_time, update_time,
create_user, `order`)
SELECT #{request.id},
#{request.testPlanId},
#{request.apiCaseId},
#{request.environmentId},
#{request.createTime},
#{request.updateTime},
#{request.createUser},
#{request.order}
FROM DUAL
WHERE NOT EXISTS(
SELECT id FROM
test_plan_api_case
WHERE test_plan_id = #{request.testPlanId} and api_case_id = #{request.apiCaseId}
SELECT id
FROM test_plan_api_case
WHERE test_plan_id = #{request.testPlanId}
and api_case_id = #{request.apiCaseId}
)
</insert>
<select id="getApiTestCaseById" resultType="io.metersphere.base.domain.ApiTestCaseWithBLOBs">
SELECT t.* FROM api_test_case t
SELECT t.*
FROM api_test_case t
INNER JOIN test_plan_api_case tpac ON t.id = tpac.api_case_id
WHERE tpac.id = #{0}
</select>
<select id="getApiTestCaseIdById" resultType="java.lang.String">
SELECT api_case_id FROM test_plan_api_case t WHERE id = #{0}
SELECT api_case_id
FROM test_plan_api_case t
WHERE id = #{0}
</select>
<select id="selectLegalDataByTestPlanId" resultType="io.metersphere.base.domain.TestPlanApiCase">
SELECT t.* FROM test_plan_api_case t WHERE t.test_plan_id = #{0}
SELECT t.*
FROM test_plan_api_case t
WHERE t.test_plan_id = #{0}
AND t.api_case_id IN (
SELECT id FROM api_test_case WHERE status IS NULL OR status != 'Trash'
SELECT id
FROM api_test_case
WHERE status IS NULL
OR status
!= 'Trash'
)
ORDER BY `order` DESC
</select>
@ -259,8 +277,7 @@
</select>
<select id="getExecResultByPlanId" resultType="java.lang.String">
select status
from
test_plan_api_case
from test_plan_api_case
where test_plan_id = #{planId}
AND api_case_id in (SELECT id FROM api_test_case WHERE (`status` is null or `status` != 'Trash'))
</select>
@ -285,11 +302,20 @@
where t.test_plan_id = #{planId}
</select>
<select id="getStatusByTestPlanId" resultType="java.lang.String">
SELECT `status` FROM test_plan_api_case WHERE test_plan_id = #{0}
SELECT `status`
FROM test_plan_api_case
WHERE test_plan_id = #{0}
</select>
<select id="selectForPlanReport" resultType="io.metersphere.track.dto.PlanReportCaseDTO">
select id,status from test_plan_api_case where test_plan_id = #{planId} and api_case_id IN (
SELECT id FROM api_test_case where status is null or status != 'Trash'
select id, status
from test_plan_api_case
where test_plan_id = #{planId}
and api_case_id IN (
SELECT id
FROM api_test_case
where status is null
or status
!= 'Trash'
)
</select>
<select id="getFailureList" resultType="io.metersphere.api.dto.automation.TestPlanFailureApiDTO">
@ -337,10 +363,14 @@
<select id="selectPlanIds" resultType="java.lang.String">
select DISTINCT test_plan_id from test_plan_api_case;
select DISTINCT test_plan_id
from test_plan_api_case;
</select>
<select id="getIdsOrderByUpdateTime" resultType="java.lang.String">
select id from test_plan_api_case where test_plan_id = #{planId} order by update_time ASC;
select id
from test_plan_api_case
where test_plan_id = #{planId}
order by update_time ASC;
</select>
<select id="getLastOrder" resultType="java.lang.Long">
@ -358,6 +388,18 @@
</if>
order by `order` desc limit 1;
</select>
<select id="selectByIdsAndStatusIsNotTrash" resultType="io.metersphere.base.domain.TestPlanApiCase">
SELECT
plan.*
FROM
test_plan_api_case plan
INNER JOIN api_test_case api ON plan.api_case_id = api.id
WHERE
(api.`status` is null OR api.`status` != 'Trash') AND plan.test_plan_id IN
<foreach collection="ids" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</select>
<sql id="queryVersionCondition">
<if test="request.versionId != null">

View File

@ -0,0 +1,12 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.base.domain.TestPlanApiScenario;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtTestPlanApiScenarioMapper {
List<TestPlanApiScenario> selectByIdsAndStatusIsNotTrash(@Param("ids") List<String> ids);
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.base.mapper.ext.ExtTestPlanApiScenarioMapper">
<select id="selectByIdsAndStatusIsNotTrash" resultType="io.metersphere.base.domain.TestPlanApiScenario">
SELECT
plan.*
FROM
test_plan_api_scenario plan
INNER JOIN api_scenario api ON plan.api_scenario_id = api.id
WHERE
(api.`status` is null OR api.`status` != 'Trash') AND plan.test_plan_id IN
<foreach collection="ids" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</select>
</mapper>

View File

@ -35,9 +35,9 @@ import io.metersphere.performance.service.MetricQueryService;
import io.metersphere.performance.service.PerformanceReportService;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.service.*;
import io.metersphere.track.factory.ReportComponentFactory;
import io.metersphere.track.domain.ReportComponent;
import io.metersphere.track.dto.*;
import io.metersphere.track.factory.ReportComponentFactory;
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.AddTestPlanRequest;
@ -184,6 +184,8 @@ public class TestPlanService {
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
@Resource
private ExtApiDefinitionExecResultMapper extApiDefinitionExecResultMapper;
@Resource
private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper;
public synchronized TestPlan addTestPlan(AddTestPlanRequest testPlan) {
if (getTestPlanByName(testPlan.getName()).size() > 0) {
@ -1924,6 +1926,10 @@ public class TestPlanService {
}
public String runPlan(TestplanRunRequest testplanRunRequest) {
//检查是否有可以执行的用例
if (!haveExecCase(testplanRunRequest.getTestPlanId())) {
MSException.throwException(Translator.get("plan_warning"));
}
String envType = testplanRunRequest.getEnvironmentType();
Map<String, String> envMap = testplanRunRequest.getEnvMap();
String environmentGroupId = testplanRunRequest.getEnvironmentGroupId();
@ -1999,16 +2005,14 @@ public class TestPlanService {
if (StringUtils.isBlank(id)) {
return false;
}
TestPlanApiCaseExample apiCaseExample = new TestPlanApiCaseExample();
apiCaseExample.createCriteria().andTestPlanIdEqualTo(id);
List<TestPlanApiCase> testPlanApiCases = testPlanApiCaseMapper.selectByExample(apiCaseExample);
List<String> ids = new ArrayList<>();
ids.add(id);
List<TestPlanApiCase> testPlanApiCases = extTestPlanApiCaseMapper.selectByIdsAndStatusIsNotTrash(ids);
if (!CollectionUtils.isEmpty(testPlanApiCases)) {
return true;
}
TestPlanApiScenarioExample apiScenarioExample = new TestPlanApiScenarioExample();
apiScenarioExample.createCriteria().andTestPlanIdEqualTo(id);
List<TestPlanApiScenario> testPlanApiScenarios = testPlanApiScenarioMapper.selectByExample(apiScenarioExample);
List<TestPlanApiScenario> testPlanApiScenarios = extTestPlanApiScenarioMapper.selectByIdsAndStatusIsNotTrash(ids);
if (!CollectionUtils.isEmpty(testPlanApiScenarios)) {
return true;
}
@ -2153,6 +2157,7 @@ public class TestPlanService {
Map<String, String> executeQueue = new LinkedHashMap<>();
StringBuilder stringBuilder = new StringBuilder();
StringBuilder haveExecCaseBuilder = new StringBuilder();
for (int i = 0; i < planList.size(); i++) {
if (StringUtils.isBlank(planList.get(i).getRunModeConfig())) {
StringBuilder append = stringBuilder.append("请保存[").append(planList.get(i).getName()).append("]的运行配置");
@ -2160,8 +2165,14 @@ public class TestPlanService {
append.append("/");
}
}
if (!haveExecCase(planList.get(i).getId())) {
haveExecCaseBuilder.append(planList.get(i).getName()).append("; ");
}
}
if (StringUtils.isNotEmpty(haveExecCaseBuilder)) {
MSException.throwException(Translator.get("track_test_plan") + ": " + haveExecCaseBuilder.toString() + " :" + Translator.get("plan_warning"));
}
if (StringUtils.isNotEmpty(stringBuilder)) {
MSException.throwException(stringBuilder.toString());
}

@ -1 +1 @@
Subproject commit 7f405105bf50af4ae2f1a240059c742f3ac7c729
Subproject commit 830bad0961b3ec2eaff21e9eac382d16f0521639

View File

@ -388,3 +388,4 @@ cmdExtractElement=element extraction
tcp_mock_not_unique=This tcp port is be used
no_tcp_mock_port=No idle tcp port, please contact administrators.
name_already_exists_in_module=Name already exists in same module
plan_warning=There is no associated executable use case under the test plan

View File

@ -387,3 +387,4 @@ cmdExtractElement=提取元素信息
tcp_mock_not_unique=该TCP端口号已被使用
no_tcp_mock_port=无可用的TCP端口号请联系管理员
name_already_exists_in_module=同层级下已经存在
plan_warning=测试计划下没有关联可以执行的用例

View File

@ -386,3 +386,4 @@ cmdExtractElement=提取元素信息
tcp_mock_not_unique=該TCP端口號已被使用
no_tcp_mock_port=無可用的TCP端口號請聯繫管理員
name_already_exists_in_module=同層級下已存在
plan_warning=測試計劃下沒有關聯可以執行的用例

@ -1 +1 @@
Subproject commit 20b5563776f552ecd1b84bed3bcf50e5cbcaa9b0
Subproject commit 12370ba86adfdf31b11a30d48a59c3715490b351