Compare commits

...

7 Commits

13 changed files with 268 additions and 38 deletions

View File

@@ -5,6 +5,7 @@ import com.test.common.core.controller.BaseController;
import com.test.common.core.domain.AjaxResult; import com.test.common.core.domain.AjaxResult;
import com.test.common.core.page.TableDataInfo; import com.test.common.core.page.TableDataInfo;
import com.test.common.enums.BusinessType; import com.test.common.enums.BusinessType;
import com.test.test.domain.TestReport;
import com.test.test.domain.qo.IDQO; import com.test.test.domain.qo.IDQO;
import com.test.test.domain.qo.TestReportAddQO; import com.test.test.domain.qo.TestReportAddQO;
import com.test.test.domain.vo.TestReportVo; import com.test.test.domain.vo.TestReportVo;
@@ -53,4 +54,36 @@ public class TestReportController extends BaseController {
public AjaxResult addTestReport(@RequestBody TestReportAddQO testReportAddQO) { public AjaxResult addTestReport(@RequestBody TestReportAddQO testReportAddQO) {
return toAjax(testReportService.addTestReport(testReportAddQO)); return toAjax(testReportService.addTestReport(testReportAddQO));
} }
/**
* 查询测试计划关联测试报告详情
*/
@PostMapping("/caseExecuteDetail")
public AjaxResult caseExecuteDetail(@RequestBody IDQO id) {
return success(testReportService.selectCaseTestReportById(id.getId()));
}
/**
* 删除测试报告
* @param id
* @return
*/
@Log(title = "测试报告", businessType = BusinessType.DELETE)
@PostMapping("/delExecuteCaseReport")
public AjaxResult delExecuteCaseReport(@RequestBody IDQO id) {
TestReport testReport = testReportService.selectCaseTestReportById(id.getId());
testReport.setDelFlag("1");
return toAjax(testReportService.updateExecuteCaseReport(testReport));
}
/**
* 修改测试计划关联测试报告
* @param testReport
*/
@Log(title = "测试报告", businessType = BusinessType.UPDATE)
@PostMapping("/updateExecuteCaseReport")
public AjaxResult updateExecuteCaseReport(@RequestBody TestReport testReport) {
return toAjax(testReportService.updateExecuteCaseReport(testReport));
}
} }

View File

@@ -9,6 +9,9 @@ public class TestReportVo extends BaseEntity {
private static final long serialVersionUID = -4331077290310280474L; private static final long serialVersionUID = -4331077290310280474L;
/** 测试报告id */
private Long id;
/** /**
* 测试报告名称 * 测试报告名称
*/ */

View File

@@ -20,4 +20,18 @@ public interface TestReportMapper {
* @return * @return
*/ */
int addTestReport(TestReport testReport); int addTestReport(TestReport testReport);
/**
* 查询用例执行测试报告详情
* @param id
* @return
*/
TestReport selectCaseTestReportById(Long id);
/**
* 修改用例执行测试报告
* @param testReport
* @return
*/
int updateExecuteCaseReport(TestReport testReport);
} }

View File

@@ -1,6 +1,5 @@
package com.test.test.service; package com.test.test.service;
import com.test.common.core.domain.AjaxResult;
import com.test.test.domain.TestReport; import com.test.test.domain.TestReport;
import com.test.test.domain.qo.TestReportAddQO; import com.test.test.domain.qo.TestReportAddQO;
import com.test.test.domain.vo.TestReportVo; import com.test.test.domain.vo.TestReportVo;
@@ -24,4 +23,18 @@ public interface ITestReportService {
* @return * @return
*/ */
public int addTestReport(TestReportAddQO testReportAddQO); public int addTestReport(TestReportAddQO testReportAddQO);
/**
* 更新执行用例测试报告
* @param testReport
* @return
*/
public int updateExecuteCaseReport(TestReport testReport);
/**
* 查询测试报告详情
* @param id
* @return
*/
public TestReport selectCaseTestReportById(Long id);
} }

View File

@@ -167,7 +167,7 @@ public class PerformanceTestCaseReportServiceImpl implements IPerformanceTestCas
JmeterRequest jmeterRequest = new JmeterRequest(); JmeterRequest jmeterRequest = new JmeterRequest();
jmeterRequest.setTestCaseName(testCaseStep.getName()); jmeterRequest.setTestCaseName(testCaseStep.getName());
jmeterRequest.setUrl(url); jmeterRequest.setUrl(url);
jmeterRequest.setPort(testCaseStep.getApiPort()); jmeterRequest.setPort(testCaseStep.getApiPort() == null ? 80 : testCaseStep.getApiPort());
jmeterRequest.setMethod(testCaseStep.getRequestMethod()); jmeterRequest.setMethod(testCaseStep.getRequestMethod());
jmeterRequest.setRequestBody(testCaseStep.getRequestBody()); jmeterRequest.setRequestBody(testCaseStep.getRequestBody());
jmeterRequest.setRequestParams(testCaseStep.getRequestParams()); jmeterRequest.setRequestParams(testCaseStep.getRequestParams());

View File

@@ -1,7 +1,6 @@
package com.test.test.service.impl; package com.test.test.service.impl;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.test.common.core.domain.AjaxResult;
import com.test.common.utils.DateUtils; import com.test.common.utils.DateUtils;
import com.test.common.utils.SecurityUtils; import com.test.common.utils.SecurityUtils;
import com.test.common.utils.StringUtils; import com.test.common.utils.StringUtils;
@@ -68,16 +67,22 @@ public class TestReportServiceImpl implements ITestReportService {
List<TestCaseResult> testCaseResults = testCaseResultMapper.selectTestCaseResultList(testCaseResult); List<TestCaseResult> testCaseResults = testCaseResultMapper.selectTestCaseResultList(testCaseResult);
int count = testCaseResults.size(); int count = testCaseResults.size();
int passNum = (int)testCaseResults.stream().filter(result -> "成功".equals(result.getStatus())).count(); int passNum = (int)testCaseResults.stream().filter(result -> "成功".equals(result.getStatus())).count();
if (count == passNum) {
testReportAddQO.setResult("1");
}
TestCaseReportVO testCaseReportVO = new TestCaseReportVO(); TestCaseReportVO testCaseReportVO = new TestCaseReportVO();
testCaseReportVO.setName(testReportAddQO.getName()); testCaseReportVO.setName(testReportAddQO.getName());
testCaseReportVO.setResult("success"); testCaseReportVO.setResult("0");
testCaseReportVO.setCaseNum(count); testCaseReportVO.setCaseNum(count);
testCaseReportVO.setPassNum(passNum); testCaseReportVO.setPassNum(passNum);
String reportJson = JSONObject.toJSONString(testCaseReportVO); String reportJson = JSONObject.toJSONString(testCaseReportVO);
TestReport testReport = new TestReport(); TestReport testReport = new TestReport();
if (count == passNum) {
testReport.setResult("1");
}
BeanUtils.copyProperties(testReportAddQO,testReport); BeanUtils.copyProperties(testReportAddQO,testReport);
testReport.setSerialNumber(generateSerialNumber()); testReport.setSerialNumber(generateSerialNumber());
testReport.setResult("1"); testReport.setResult("0");
testReport.setStatus("0"); testReport.setStatus("0");
testReport.setReport(reportJson); testReport.setReport(reportJson);
testReport.setCreateTime(DateUtils.getNowDate()); testReport.setCreateTime(DateUtils.getNowDate());
@@ -90,6 +95,27 @@ public class TestReportServiceImpl implements ITestReportService {
return testPlanReportMapper.insertTestPlanReport(testReportAddQO); return testPlanReportMapper.insertTestPlanReport(testReportAddQO);
} }
/**
* 更新执行用例报告
* @param testReport
* @return
*/
@Override
public int updateExecuteCaseReport(TestReport testReport) {
testReport.setUpdateTime(DateUtils.getNowDate());
return testReportMapper.updateExecuteCaseReport(testReport);
}
/**
* 根据id查询报告
* @param id
* @return
*/
@Override
public TestReport selectCaseTestReportById(Long id) {
return testReportMapper.selectCaseTestReportById(id);
}
/** /**
* 生成随机序列号 * 生成随机序列号
* @return * @return

View File

@@ -149,19 +149,23 @@
(SELECT COUNT(1) FROM test_plan_case tpc (SELECT COUNT(1) FROM test_plan_case tpc
WHERE tpc.plan_id = tp.id WHERE tpc.plan_id = tp.id
AND tpc.del_flag = '0' AND tpc.del_flag = '0'
AND tpc.type = '1') AS functionTestPassNum, AND tpc.type = '1'
AND tpc.execute_result = '1') AS functionTestPassNum,
(SELECT COUNT(1) FROM test_plan_case tpc (SELECT COUNT(1) FROM test_plan_case tpc
WHERE tpc.plan_id = tp.id WHERE tpc.plan_id = tp.id
AND tpc.del_flag = '0' AND tpc.del_flag = '0'
AND tpc.type = '2') AS regressionTestPassNum, AND tpc.type = '2'
AND tpc.execute_result = '1') AS regressionTestPassNum,
(SELECT COUNT(1) FROM test_plan_case tpc (SELECT COUNT(1) FROM test_plan_case tpc
WHERE tpc.plan_id = tp.id WHERE tpc.plan_id = tp.id
AND tpc.del_flag = '0' AND tpc.del_flag = '0'
AND tpc.type = '3') AS preProductionTestPassNum, AND tpc.type = '3'
AND tpc.execute_result = '1') AS preProductionTestPassNum,
(SELECT COUNT(1) FROM test_plan_case tpc (SELECT COUNT(1) FROM test_plan_case tpc
WHERE tpc.plan_id = tp.id WHERE tpc.plan_id = tp.id
AND tpc.del_flag = '0' AND tpc.del_flag = '0'
AND tpc.type = '4') AS productionTestPassNum, AND tpc.type = '4'
AND tpc.execute_result = '1') AS productionTestPassNum,
tp.version, tp.version,
( (
SELECT COUNT(1) FROM test_plan_defect tpd SELECT COUNT(1) FROM test_plan_defect tpd

View File

@@ -31,19 +31,72 @@
</trim> </trim>
</insert> </insert>
<resultMap type="TestReport" id="TestReportResult">
<result property="id" column="id"/>
<result property="serialNumber" column="serial_number"/>
<result property="name" column="name"/>
<result property="result" column="result"/>
<result property="status" column="status"/>
<result property="report" column="report"/>
<result property="updateBy" column="update_by"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="version" column="version"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
<sql id="selectTestReportVo">
SELECT id,
serial_number,
name,
result,
status,
report,
update_by,
create_time,
update_time,
version,
del_flag
FROM test_report
</sql>
<select id="selectTestReportList" parameterType="Long" resultType="TestReportVo"> <select id="selectTestReportList" parameterType="Long" resultType="TestReportVo">
SELECT SELECT tr.id AS id,
tr.name AS name, tr.name AS name,
tr.result AS result, tr.result AS result,
tr.report AS report, tr.report AS report,
tr.status AS status, tr.status AS status,
tpr.type AS type, tpr.type AS type,
tr.create_time AS createTime, tr.create_time AS createTime,
tr.update_by AS updateBy tr.update_by AS updateBy,
tr.update_time AS updateTime
FROM test_plan_report tpr FROM test_plan_report tpr
LEFT JOIN test_report tr ON tr.id = tpr.report_id LEFT JOIN test_report tr ON tr.id = tpr.report_id
WHERE tpr.plan_id = #{planId} WHERE tpr.plan_id = #{planId}
AND tpr.del_flag = '0' AND tpr.del_flag = '0'
AND tr.del_flag = '0'
ORDER BY tr.create_time DESC ORDER BY tr.create_time DESC
</select> </select>
<select id="selectCaseTestReportById" parameterType="Long" resultMap="TestReportResult">
<include refid="selectTestReportVo"/>
where id = #{id}
</select>
<update id="updateExecuteCaseReport" parameterType="testReport">
update test_report
<trim prefix="SET" suffixOverrides=",">
<if test="serialNumber != null">serial_number = #{serialNumber},</if>
<if test="name != null">name = #{name},</if>
<if test="result != null">result = #{result},</if>
<if test="status != null">status = #{status},</if>
<if test="report != null">report = #{report},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="version != null">version = #{version},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
</trim>
where id = #{id}
</update>
</mapper> </mapper>

View File

@@ -9,6 +9,8 @@ const api = {
testPlanProjectList: '/test/testPlanProject/list', testPlanProjectList: '/test/testPlanProject/list',
addTestReport: 'test/testReport/addTestReport', addTestReport: 'test/testReport/addTestReport',
getTestReportList: 'test/testReport/reportList', getTestReportList: 'test/testReport/reportList',
delExecuteCaseReport: 'test/testReport/delExecuteCaseReport',
updateExecuteCaseReport: 'test/testReport/updateExecuteCaseReport',
getPlanOverview:'test/testPlan/planOverview', getPlanOverview:'test/testPlan/planOverview',
getPlanCaseTrendData: 'test/testPlan/planCaseTrendData', getPlanCaseTrendData: 'test/testPlan/planCaseTrendData',
} }
@@ -77,6 +79,22 @@ export function getTestReportList(data) {
}) })
} }
export function delExecuteCaseReport(id) {
return request({
url: api.delExecuteCaseReport,
method: 'post',
data: {id}
})
}
export function updateExecuteCaseReport(data) {
return request({
url: api.updateExecuteCaseReport,
method: 'post',
data: data
})
}
export function getPlanOverview(id) { export function getPlanOverview(id) {
return request({ return request({
url: api.getPlanOverview, url: api.getPlanOverview,

View File

@@ -173,7 +173,7 @@ export const constantRoutes = [
] ]
}, },
{ {
path: '/performance/report/detail', path: '/performance/report/detail/:id',
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [

View File

@@ -65,7 +65,7 @@ export default {
methods: { methods: {
// 查看 // 查看
hadleClickDetail(val) { hadleClickDetail(val) {
this.$tab.openPage("报告详情", "/performance/report/detail", { id: val.id }); this.$tab.openPage(`报告详情_${val.id}`, `/performance/report/detail/${val.id}`, { id: val.id });
}, },
// 删除 // 删除
hadleClickDelete(val) { hadleClickDelete(val) {

View File

@@ -35,6 +35,11 @@
</el-table-column> </el-table-column>
<el-table-column prop="updateBy" label="最后更新人" align="center"/> <el-table-column prop="updateBy" label="最后更新人" align="center"/>
<el-table-column prop="updateTime" label="最后更新时间" align="center"/> <el-table-column prop="updateTime" label="最后更新时间" align="center"/>
<el-table-column label="操作" align="center">
<template #default="{ row }">
<el-button type="text" size="mini" @click.native.stop="handleDel(row.id)">删除</el-button>
</template>
</el-table-column>
</el-Table> </el-Table>
</el-tabs> </el-tabs>
<pagination <pagination
@@ -65,7 +70,7 @@
</template> </template>
<script> <script>
import SimpleOptions from "@/components/FormItem/option/SimpleOptions.vue"; import SimpleOptions from "@/components/FormItem/option/SimpleOptions.vue";
import {addTestReport, getTestReportList} from "@/api/test/testPlan"; import {addTestReport, delExecuteCaseReport, getTestReportList} from "@/api/test/testPlan";
export default { export default {
name: 'caseReport', name: 'caseReport',
@@ -101,20 +106,34 @@ export default {
} }
} }
}, },
activated() {
this.$nextTick(() => {
console.log('getlist')
this.getList()
})
},
mounted() { mounted() {
this.getList()
}, },
methods: { methods: {
handleRowClick(row){ handleRowClick(row){
this.$tab.openPage('平台报告', '/testplan/casereport/platformReport', this.$tab.openPage('平台报告', '/testplan/casereport/platformReport',
{id: row.id, {id: row.id,
name: row.name, name: row.name,
type: row.result, type: row.type,
planId: row.planId, planId: row.planId,
report: row.report report: row.report
} }
) )
}, },
handleDel(id) {
this.$modal.confirm('是否确认删除测试报告?').then(function () {
return delExecuteCaseReport(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
});
},
getList() { getList() {
this.loading = true this.loading = true
this.queryParams.id = Number(this.planId) this.queryParams.id = Number(this.planId)

View File

@@ -3,9 +3,9 @@
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="24" class="page-header"> <el-col :span="24" class="page-header">
<el-page-header :title="reportTitle" @back="goBack" ></el-page-header> <el-page-header :title="reportTitle" @back="goBack" ></el-page-header>
<div class="header-buttons"> <div class="header-buttons" v-if="isEdit">
<span>测试结果</span> <span>测试结果</span>
<el-select v-model="selectedResult" placeholder="请选择" clearable> <el-select v-model="selectedResult" placeholder="请选择">
<el-option <el-option
v-for="item in resultOptions" v-for="item in resultOptions"
:key="item.value" :key="item.value"
@@ -15,17 +15,29 @@
</el-select> </el-select>
<el-button type="primary" icon="el-icon-setting" @click="configureModule">配置模块</el-button> <el-button type="primary" icon="el-icon-setting" @click="configureModule">配置模块</el-button>
<el-button type="primary" size="medium" @click="saveReport">保存报告</el-button> <el-button type="primary" size="medium" @click="saveReport">保存报告</el-button>
<el-button type="danger" size="medium" @click="isEdit = false">取消编辑</el-button>
</div>
<div class="header-buttons" v-else>
<el-button type="primary" icon="el-icon-setting" @click="configureModule">下载报告</el-button>
<el-button type="primary" size="medium" @click="isEdit = true">编辑报告</el-button>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div class="report-container"> <div class="report-container" :class="testStatusClass">
<div class="report-header"> <div class="report-header">
<div class="report-title"> <div class="report-title" v-if="isEdit">
<span>{{ reportTitle }}</span> <el-input v-model="reportTitle" style="width: 300px" placeholder="请输入报告名称"/>
<div class="report-info">
<span>关联项目中移商业保理平台</span>
<span>测试阶段{{ reportType }}</span>
</div>
</div> </div>
<div class="report-info"> <div class="report-title" v-else>
<span>关联项目中移商业保理平台</span> <span>{{ reportTitle }}</span>
<span>测试阶段{{ reportType }}</span> <div class="report-info">
<span>关联项目中移商业保理平台</span>
<span>测试阶段{{ reportType }}</span>
</div>
</div> </div>
</div> </div>
@@ -73,6 +85,7 @@
<script> <script>
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import router from "@/router"; import router from "@/router";
import {updateExecuteCaseReport} from "@/api/test/testPlan";
export default { export default {
name: 'report', name: 'report',
@@ -85,14 +98,15 @@ export default {
}, },
data() { data() {
return { return {
isEdit: false,
reportId: '',
reportType: '', reportType: '',
reportTitle: '', reportTitle: '',
reportData: {}, reportData: {},
selectedResult: '', // 选择的测试结果 selectedResult: '', // 选择的测试结果
resultOptions: [ // 测试结果选项 resultOptions: [ // 测试结果选项
{ value: 'all', label: '全部' }, { value: '1', label: '通过' },
{ value: 'passed', label: '通过' }, { value: '0', label: '通过' }
{ value: 'failed', label: '失败' }
], ],
// 执行结果分布数据 // 执行结果分布数据
@@ -115,9 +129,11 @@ export default {
}; };
}, },
created() { created() {
this.reportId = this.$route.query.id;
this.reportTitle = this.$route.query.name; this.reportTitle = this.$route.query.name;
this.reportType = this.$route.query.type; this.reportType = this.$route.query.type;
this.reportData = JSON.parse(this.$route.query.report); this.reportData = JSON.parse(this.$route.query.report);
this.selectedResult = this.reportData.result;
// 更新饼图数据 // 更新饼图数据
this.resultDistributionData.series[0].value = this.reportData.passNum || 0; this.resultDistributionData.series[0].value = this.reportData.passNum || 0;
@@ -141,6 +157,9 @@ export default {
passRate() { passRate() {
if (this.reportData.caseNum === 0) return 0; if (this.reportData.caseNum === 0) return 0;
return (this.reportData.passNum / this.reportData.caseNum) * 100; return (this.reportData.passNum / this.reportData.caseNum) * 100;
},
testStatusClass() {
return this.selectedResult === '0' ? 'status-not-passed' : 'status-passed';
} }
}, },
mounted() { mounted() {
@@ -156,6 +175,7 @@ export default {
myChart.setOption({ myChart.setOption({
series: [{ series: [{
type: 'pie', type: 'pie',
radius: ['40%', '70%'],
data: this.resultDistributionData.series data: this.resultDistributionData.series
}] }]
}, true); // true 表示合并选项 }, true); // true 表示合并选项
@@ -248,9 +268,31 @@ export default {
}, },
saveReport() { saveReport() {
// 保存报告的逻辑 let reportData = {
console.log('Save report'); caseNum: this.reportData.caseNum,
} name: this.reportData.name,
passNum: this.reportData.passNum,
result: this.selectedResult // 使用外部的 result 值替换
};
// 构造要提交的数据对象
const reportDataToSave = {
id: this.reportId,
name: this.reportTitle,
result: this.selectedResult,
report: JSON.stringify(reportData)
};
updateExecuteCaseReport(reportDataToSave)
.then(response => {
this.$message.success('报告保存成功');
// 可选:更新页面状态为非编辑模式
this.isEdit = false;
})
.catch(error => {
this.$message.error('报告保存失败');
console.error('保存报告失败:', error);
});
},
}, },
} }
</script> </script>
@@ -259,7 +301,12 @@ export default {
.report-container { .report-container {
height: 300px; height: 300px;
margin-bottom: 20px; margin-bottom: 20px;
background: linear-gradient(90deg, #6fcdac, #9ed2bb); &.status-not-passed {
background: linear-gradient(180deg, #e7998b, #e8b1b0);
}
&.status-passed {
background: linear-gradient(180deg, #6fcdac, #9ed2bb);
}
.report-header { .report-header {
color: white; color: white;