fix(测试跟踪): 测试计划报告功能用例增加阻塞和跳过用例

--story=1008184 --user=陈建星 测试计划优化 https://www.tapd.cn/55049933/s/1200949
This commit is contained in:
chenjianxing 2022-07-14 17:00:08 +08:00 committed by jianxing
parent 65d7bf5961
commit ca25efde6c
13 changed files with 231 additions and 120 deletions

View File

@ -57,7 +57,7 @@ public interface ExtTestPlanTestCaseMapper {
List<PlanReportCaseDTO> selectForPlanReport(String planId);
List<TestPlanCaseDTO> getCases(@Param("planId") String planId, @Param("status") String status);
List<TestPlanCaseDTO> getCasesByStatusList(@Param("planId") String planId, @Param("statusList") List<String> statusList);
List<String> selectPlanIds();

View File

@ -485,7 +485,7 @@
on tc.id = tptc.case_id and tc.status != 'Trash'
where tptc.plan_id = #{planId};
</select>
<select id="getCases" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
<select id="getCasesByStatusList" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
select tptc.id, tc.id as caseId, tc.name, tc.priority, tc.num, tc.custom_num, tc.project_id,
tc.node_id, tc.tags, tptc.actual_result,
tptc.update_time, tptc.create_time,
@ -493,11 +493,15 @@
tptc.plan_id, tptc.executor
from test_plan_test_case tptc
inner join test_case tc on tptc.case_id = tc.id
<if test="status != null">
and tptc.status = 'Failure'
</if>
where tptc.plan_id = #{planId}
<if test="statusList != null and statusList.size() > 0">
and tptc.status in
<foreach collection="statusList" open="(" close=")" item="status" separator=",">
#{status}
</foreach>
</if>
and (tc.status != 'Trash' or tc.status is null)
where tptc.plan_id = #{planId} order by tptc.`order` desc
order by tptc.`order` desc
</select>
<update id="updateTestCaseStates" parameterType="java.lang.String">
update test_plan_test_case

View File

@ -93,16 +93,11 @@ public class ShareController {
testPlanService.exportPlanReport(planId, lang, response);
}
@GetMapping("/test/plan/case/list/failure/{shareId}/{planId}")
public List<TestPlanCaseDTO> getFailureCases(@PathVariable String shareId, @PathVariable String planId) {
@PostMapping("/test/plan/case/list/all/{shareId}/{planId}")
public List<TestPlanCaseDTO> getAllCases(@PathVariable String shareId, @PathVariable String planId,
@RequestBody(required = false) List<String> statusList) {
shareInfoService.validate(shareId, planId);
return testPlanTestCaseService.getFailureCases(planId);
}
@GetMapping("/test/plan/case/list/all/{shareId}/{planId}")
public List<TestPlanCaseDTO> getAllCases(@PathVariable String shareId, @PathVariable String planId) {
shareInfoService.validate(shareId, planId);
return testPlanTestCaseService.getAllCases(planId);
return testPlanTestCaseService.getAllCasesByStatusList(planId, statusList);
}
@GetMapping("/test/plan/load/case/list/failure/{shareId}/{planId}")

View File

@ -135,9 +135,9 @@ public class TestPlanTestCaseController {
return testPlanTestCaseService.deleteTestCase(id);
}
@GetMapping("/list/failure/{planId}")
public List<TestPlanCaseDTO> getFailureCases(@PathVariable String planId) {
return testPlanTestCaseService.getFailureCases(planId);
@PostMapping("/list/all/{planId}")
public List<TestPlanCaseDTO> getFailureCases(@PathVariable String planId, @RequestBody(required = false) List<String> statusList) {
return testPlanTestCaseService.getAllCasesByStatusList(planId, statusList);
}
@GetMapping("/list/all/{planId}")

View File

@ -40,7 +40,6 @@ public class TestPlanSimpleReportDTO extends TestPlanReportContent {
private TestPlanApiResultReportDTO apiResult;
private TestPlanLoadResultReportDTO loadResult;
List<TestPlanCaseDTO> functionFailureCases;
List<TestPlanCaseDTO> functionAllCases;
List<IssuesDao> issueList;
List<TestPlanFailureApiDTO> apiFailureCases;

View File

@ -636,9 +636,6 @@ public class TestPlanReportService {
if (reportDTO.getFunctionAllCases() != null) {
testPlanReportContentWithBLOBs.setFunctionAllCases(JSONObject.toJSONString(reportDTO.getFunctionAllCases()));
}
if (reportDTO.getFunctionFailureCases() != null) {
testPlanReportContentWithBLOBs.setFunctionFailureCases(JSONObject.toJSONString(reportDTO.getFunctionFailureCases()));
}
if (reportDTO.getIssueList() != null) {
testPlanReportContentWithBLOBs.setIssueList(JSONObject.toJSONString(reportDTO.getIssueList()));
}
@ -699,7 +696,7 @@ public class TestPlanReportService {
if (reportDTO != null) {
status = TestPlanReportStatus.SUCCESS.name();
try {
if (CollectionUtils.isNotEmpty(reportDTO.getFunctionFailureCases())
if (hasFunctionFailedCases(reportDTO.getFunctionAllCases())
|| CollectionUtils.isNotEmpty(reportDTO.getApiFailureCases())
|| CollectionUtils.isNotEmpty(reportDTO.getScenarioFailureCases())
|| CollectionUtils.isNotEmpty(reportDTO.getLoadFailureCases())) {
@ -717,6 +714,18 @@ public class TestPlanReportService {
return status;
}
private boolean hasFunctionFailedCases(List<TestPlanCaseDTO> functionAllCases) {
if (functionAllCases == null) {
return false;
}
for (TestPlanCaseDTO functionAllCase : functionAllCases) {
if (StringUtils.equals(functionAllCase.getStatus(), TestPlanTestCaseStatus.Failure.name())) {
return true;
}
}
return false;
}
public TestPlanReport getTestPlanReport(String planId) {
return testPlanReportMapper.selectByPrimaryKey(planId);
}
@ -897,9 +906,6 @@ public class TestPlanReportService {
if (StringUtils.isNotBlank(testPlanReportContent.getFunctionAllCases())) {
testPlanReportDTO.setFunctionAllCases(JSONObject.parseArray(testPlanReportContent.getFunctionAllCases(), TestPlanCaseDTO.class));
}
if (StringUtils.isNotBlank(testPlanReportContent.getFunctionFailureCases())) {
testPlanReportDTO.setFunctionFailureCases(JSONObject.parseArray(testPlanReportContent.getFunctionFailureCases(), TestPlanCaseDTO.class));
}
if (StringUtils.isNotBlank(testPlanReportContent.getIssueList())) {
testPlanReportDTO.setIssueList(JSONObject.parseArray(testPlanReportContent.getIssueList(), IssuesDao.class));
}

View File

@ -1316,22 +1316,17 @@ public class TestPlanService {
public void buildFunctionalReport(TestPlanSimpleReportDTO report, JSONObject config, String planId) {
if (checkReportConfig(config, "functional")) {
List<TestPlanCaseDTO> allCases = null;
List<String> statusList = getFunctionalReportStatusList(config);
if (statusList != null) {
allCases = testPlanTestCaseService.getAllCasesByStatusList(planId, statusList);
report.setFunctionAllCases(allCases);
}
if (checkReportConfig(config, "functional", "all")) {
allCases = testPlanTestCaseService.getAllCases(planId);
report.setFunctionAllCases(allCases);
}
if (checkReportConfig(config, "functional", "failure")) {
List<TestPlanCaseDTO> failureCases = null;
if (!CollectionUtils.isEmpty(allCases)) {
failureCases = allCases.stream()
.filter(i -> StringUtils.isNotBlank(i.getStatus())
&& i.getStatus().equals("Failure"))
.collect(Collectors.toList());
} else {
failureCases = testPlanTestCaseService.getFailureCases(planId);
}
report.setFunctionFailureCases(failureCases);
}
if (checkReportConfig(config, "functional", "issue")) {
List<IssuesDao> issueList = issuesService.getIssuesByPlanId(planId);
report.setIssueList(issueList);
@ -1339,6 +1334,23 @@ public class TestPlanService {
}
}
public List<String> getFunctionalReportStatusList(JSONObject config) {
List<String> statusList = new ArrayList<>();
if (checkReportConfig(config, "functional", "all")) {
return statusList;
}
if (checkReportConfig(config, "functional", "failure")) {
statusList.add(TestPlanTestCaseStatus.Failure.name());
}
if (checkReportConfig(config, "functional", "blocking")) {
statusList.add(TestPlanTestCaseStatus.Blocking.name());
}
if (checkReportConfig(config, "functional", "skip")) {
statusList.add(TestPlanTestCaseStatus.Skip.name());
}
return statusList.size() > 0 ? statusList : null;
}
public void buildApiReport(TestPlanSimpleReportDTO report, JSONObject config, String planId, boolean saveResponse) {
if (checkReportConfig(config, "api")) {
List<TestPlanFailureApiDTO> apiAllCases = null;

View File

@ -480,14 +480,12 @@ public class TestPlanTestCaseService {
functionResult.setCaseData(statusResult);
}
public List<TestPlanCaseDTO> getFailureCases(String planId) {
List<TestPlanCaseDTO> allCases = extTestPlanTestCaseMapper.getCases(planId, "Failure");
return buildCaseInfo(allCases);
public List<TestPlanCaseDTO> getAllCasesByStatusList(String planId, List<String> statusList) {
return buildCaseInfo(extTestPlanTestCaseMapper.getCasesByStatusList(planId, statusList));
}
public List<TestPlanCaseDTO> getAllCases(String planId) {
List<TestPlanCaseDTO> allCases = extTestPlanTestCaseMapper.getCases(planId, null);
return buildCaseInfo(allCases);
return buildCaseInfo(this.getAllCasesByStatusList(planId, null));
}
public List<TestPlanCaseDTO> buildCaseInfo(List<TestPlanCaseDTO> cases) {

View File

@ -41,12 +41,7 @@ export default {
this.testCase.status = status;
},
saveCase() {
//
if (this.testCase.status === 'Failure' && this.originStatus !== 'Failure' && !this.testCase.comment) {
this.$refs.comment.inputLight();
} else {
this.$emit('saveCase');
}
this.$emit('saveCase');
}
}
}

View File

@ -4,23 +4,77 @@
<el-tab-pane v-if="resultEnable" :label="$t('test_track.report.test_result')" name="first">
<functional-result :function-result="report.functionResult"/>
</el-tab-pane>
<el-tab-pane v-if="failureEnable" name="second">
<template v-slot:label>
<tab-pane-count :title="$t('test_track.report.fail_case')" :count="failureSize"/>
</template>
<functional-cases :is-db="isDb" :share-id="shareId" :is-share="isShare" :is-template="isTemplate" :report="report" :plan-id="planId" @setSize="setFailureSize"/>
</el-tab-pane>
<el-tab-pane v-if="issueEnable && (isTemplate || hasPermission('PROJECT_TRACK_ISSUE:READ'))" name="third">
<el-tab-pane v-if="issueEnable && (isTemplate || hasPermission('PROJECT_TRACK_ISSUE:READ'))" name="second">
<template v-slot:label>
<tab-pane-count :title="$t('test_track.report.issue_list')" :count="issueSize"/>
</template>
<functional-issue-list :is-db="isDb" :share-id="shareId" :is-share="isShare" :is-template="isTemplate" :report="report" :plan-id="planId" @setSize="setIssueSize"/>
<functional-issue-list
:is-db="isDb"
:share-id="shareId"
:is-share="isShare"
:is-template="isTemplate"
:report="report"
:plan-id="planId"
@setSize="setIssueSize"/>
</el-tab-pane>
<el-tab-pane name="fourth" v-if="allEnable">
<el-tab-pane name="third" v-if="allEnable">
<template v-slot:label>
<tab-pane-count :title="$t('test_track.report.all_case')" :count="allSize"/>
</template>
<functional-cases :is-db="isDb" :is-all="true" :share-id="shareId" :is-share="isShare" :is-template="isTemplate" :report="report" :plan-id="planId" @setSize="setAllSize"/>
<functional-cases
:is-db="isDb"
:share-id="shareId"
:is-share="isShare"
:is-template="isTemplate"
:report="report"
:plan-id="planId"
:all-test-case="allTestCase"
@setSize="setAllSize"/>
</el-tab-pane>
<el-tab-pane v-if="failureEnable" name="fourth">
<template v-slot:label>
<tab-pane-count :title="$t('test_track.report.fail_case')" :count="failureSize"/>
</template>
<functional-cases
filter-status="Failure"
:is-db="isDb"
:share-id="shareId"
:is-share="isShare"
:is-template="isTemplate"
:report="report"
:plan-id="planId"
:all-test-case="allTestCase"
@setSize="setFailureSize"/>
</el-tab-pane>
<el-tab-pane v-if="blockingEnable" name="fifth">
<template v-slot:label>
<tab-pane-count :title="$t('test_track.plan_view.blocking') + $t('commons.track')" :count="blockingSize"/>
</template>
<functional-cases
filter-status="Blocking"
:is-db="isDb"
:share-id="shareId"
:is-share="isShare"
:is-template="isTemplate"
:report="report"
:plan-id="planId"
:all-test-case="allTestCase"
@setSize="setBlockingSize"/>
</el-tab-pane>
<el-tab-pane v-if="skipEnable" name="sixth">
<template v-slot:label>
<tab-pane-count :title="$t('test_track.plan_view.skip') + $t('commons.track')" :count="skipSize"/>
</template>
<functional-cases
filter-status="Skip"
:is-db="isDb"
:share-id="shareId"
:is-share="isShare"
:is-template="isTemplate"
:report="report"
:plan-id="planId"
:all-test-case="allTestCase"
@setSize="setSkipSize"/>
</el-tab-pane>
</el-tabs>
</test-plan-report-container>
@ -37,6 +91,10 @@ import TestPlanReportContainer
from "@/business/components/track/plan/view/comonents/report/detail/TestPlanReportContainer";
import TabPaneCount from "@/business/components/track/plan/view/comonents/report/detail/component/TabPaneCount";
import {hasPermission} from "@/common/js/utils";
import {
getPlanFunctionAllCase,
getSharePlanFunctionAllCase,
} from "@/network/test-plan";
export default {
name: "TestPlanFunctionalReport",
components: {
@ -47,7 +105,10 @@ export default {
activeName: 'first',
failureSize: 0,
issueSize: 0,
skipSize: 0,
blockingSize: 0,
allSize: 0,
allTestCase: []
};
},
props: [
@ -58,10 +119,6 @@ export default {
let disable = this.report.config && this.report.config.functional.children.result.enable === false;
return !disable;
},
failureEnable() {
let disable = this.report.config && this.report.config.functional.children.failure.enable === false;
return !disable;
},
issueEnable() {
let disable = this.report.config && this.report.config.functional.children.issue.enable === false;
return !disable;
@ -70,9 +127,22 @@ export default {
let disable = this.report.config && this.report.config.functional.children.all.enable === false;
return !disable;
},
failureEnable() {
let disable = this.report.config && this.report.config.functional.children.failure.enable === false;
return !disable;
},
blockingEnable() {
let disable = this.report.config && this.report.config.functional.children.blocking.enable === false;
return !disable;
},
skipEnable() {
let disable = this.report.config && this.report.config.functional.children.skip.enable === false;
return !disable;
},
},
mounted() {
this.initActiveName();
this.getAllFunctionalTestCase();
},
watch: {
resultEnable() {
@ -87,22 +157,35 @@ export default {
allEnable() {
this.initActiveName();
},
'report.config'() {
this.getAllFunctionalTestCase();
}
},
methods: {
initActiveName() {
if (this.resultEnable) {
this.activeName = 'first';
} else if (this.failureEnable) {
}else if (this.issueEnable) {
this.activeName = 'second';
} else if (this.issueEnable) {
this.activeName = 'third';
} else if (this.allEnable) {
this.activeName = 'third';
} else if (this.failureEnable) {
this.activeName = 'fourth';
} else if (this.blockingEnable) {
this.activeName = 'fifth';
} else if (this.skipEnable) {
this.activeName = 'sixth';
}
},
setFailureSize(size) {
this.failureSize = size;
},
setBlockingSize(size) {
this.blockingSize = size;
},
setSkipSize(size) {
this.skipSize = size;
},
setIssueSize(size) {
this.issueSize = size;
},
@ -112,8 +195,42 @@ export default {
handleClick(tab, event) {
},
hasPermission,
getAllFunctionalTestCase() {
if (this.isTemplate || this.isDb) {
this.allTestCase = this.report.functionAllCases ? this.report.functionAllCases : [];
} else if (this.isShare) {
let param = this.getStatusList();
if (param) {
getSharePlanFunctionAllCase(this.shareId, this.planId, param, (data) => {
this.allTestCase = data;
});
}
} else {
let param = this.getStatusList();
if (param) {
getPlanFunctionAllCase(this.planId, param, (data) => {
this.allTestCase = data;
});
}
}
},
getStatusList() {
let statusList = [];
if (this.allEnable) {
return statusList;
}
if (this.failureEnable) {
statusList.push('Failure');
}
if (this.blockingEnable) {
statusList.push('Blocking');
}
if (this.skipEnable) {
statusList.push('Skip');
}
return statusList.length > 0 ? statusList : null;
}
}
}
</script>

View File

@ -87,7 +87,7 @@ export default {
if (this.planReportTemplate) {
this.init();
}
}
},
},
created() {
this.getReport();
@ -181,10 +181,6 @@ export default {
enable: true,
name: this.$t('test_track.report.test_result'),
},
failure: {
enable: true,
name: this.$t('test_track.report.fail_case'),
},
issue: {
enable: true,
name: this.$t('test_track.report.issue_list'),
@ -192,7 +188,19 @@ export default {
all: {
enable: true,
name: this.$t('test_track.report.all_case'),
}
},
failure: {
enable: true,
name: this.$t('test_track.report.fail_case'),
},
blocking: {
enable: true,
name: this.$t('test_track.plan_view.blocking') + this.$t('commons.track'),
},
skip: {
enable: true,
name: this.$t('test_track.plan_view.skip') + this.$t('commons.track'),
},
}
},
api: {

View File

@ -25,12 +25,6 @@
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- prop="nodePath"-->
<!-- :label="$t('test_track.case.module')"-->
<!-- show-overflow-tooltip>-->
<!-- </el-table-column>-->
<el-table-column
prop="projectName"
:label="$t('test_track.case.project_name')"
@ -71,7 +65,6 @@ import MethodTableItem from "../../../../../../common/tableItems/planview/Method
import StatusTableItem from "../../../../../../common/tableItems/planview/StatusTableItem";
import {
getPlanFunctionAllCase,
getPlanFunctionFailureCase,
getSharePlanFunctionAllCase,
getSharePlanFunctionFailureCase
} from "@/network/test-plan";
@ -85,7 +78,14 @@ export default {
report: {},
shareId: String,
isAll: Boolean,
isDb: Boolean
isDb: Boolean,
filterStatus: String,
allTestCase: {
type: Array,
default() {
return [];
}
}
},
data() {
return {
@ -100,36 +100,22 @@ export default {
if (this.testCases) {
this.$emit('setSize', this.testCases.length);
}
},
allTestCase() {
this.getFunctionalTestCase();
}
},
methods: {
getFunctionalTestCase() {
if (this.isTemplate || this.isDb) {
if (this.isAll) {
this.testCases = this.report.functionAllCases ? this.report.functionAllCases : [];
} else {
this.testCases = this.report.functionFailureCases ? this.report.functionFailureCases : [];
}
} else if (this.isShare) {
if (this.isAll) {
getSharePlanFunctionAllCase(this.shareId, this.planId, (data) => {
this.testCases = data;
});
} else {
getSharePlanFunctionFailureCase(this.shareId, this.planId, (data) => {
this.testCases = data;
});
}
this.testCases = [];
if (this.filterStatus) {
this.allTestCase.forEach(item => {
if (item.status === this.filterStatus) {
this.testCases.push(item);
}
});
} else {
if (this.isAll) {
getPlanFunctionAllCase(this.planId, (data) => {
this.testCases = data;
});
} else {
getPlanFunctionFailureCase(this.planId, (data) => {
this.testCases = data;
});
}
this.testCases = this.allTestCase;
}
}
}

View File

@ -2,7 +2,7 @@ import {post, get} from "@/common/js/ajax";
import {success} from "@/common/js/message";
import i18n from "@/i18n/i18n";
import {baseGet, basePost} from "@/network/base-network";
import {getCurrentProjectID, getCurrentWorkspaceId} from "@/common/js/utils";
import {getCurrentProjectID} from "@/common/js/utils";
export function getTestPlanReport(planId, callback) {
if (planId) {
@ -55,21 +55,12 @@ export function getShareTestPlanReportContent(shareId, reportId, callback) {
return reportId ? baseGet('/share/test/plan/report/db/' + shareId + '/' + reportId, callback) : {};
}
export function getPlanFunctionFailureCase(planId, callback) {
return planId ? baseGet('/test/plan/case/list/failure/' + planId, callback) : {};
export function getPlanFunctionAllCase(planId, param, callback) {
return planId ? basePost('/test/plan/case/list/all/' + planId, param, callback) : {};
}
export function getPlanFunctionAllCase(planId, callback) {
return planId ? baseGet('/test/plan/case/list/all/' + planId, callback) : {};
}
export function getSharePlanFunctionFailureCase(shareId, planId, callback) {
return planId ? baseGet('/share/test/plan/case/list/failure/' + shareId + '/' + planId, callback) : {};
}
export function getSharePlanFunctionAllCase(shareId, planId, callback) {
return planId ? baseGet('/share/test/plan/case/list/all/' + shareId + '/' + planId, callback) : {};
export function getSharePlanFunctionAllCase(shareId, planId, param, callback) {
return planId ? basePost('/share/test/plan/case/list/all/' + shareId + '/' + planId, param, callback) : {};
}
export function getPlanScenarioFailureCase(planId, callback) {