refactor(接口测试): 重构接口测试控制台日志,隔离平台日志和Jmeter日志。

This commit is contained in:
fit2-zhao 2021-06-22 10:53:26 +08:00 committed by fit2-zhao
parent 7a1e44353a
commit cb8db6fcf7
6 changed files with 73 additions and 26 deletions

View File

@ -29,11 +29,10 @@ import org.apache.jmeter.visualizers.backend.AbstractBackendListenerClient;
import org.apache.jmeter.visualizers.backend.BackendListenerContext;
import org.springframework.http.HttpMethod;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* JMeter BackendListener扩展, jmx脚本中使用
@ -77,22 +76,8 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
private String debugReportId;
//获得控制台内容
private PrintStream oldPrintStream = System.out;
private ByteArrayOutputStream bos = new ByteArrayOutputStream();
private void setConsole() {
System.setOut(new PrintStream(bos)); //设置新的out
}
private String getConsole() {
System.setOut(oldPrintStream);
return bos.toString();
}
@Override
public void setupTest(BackendListenerContext context) throws Exception {
setConsole();
setParam(context);
apiTestService = CommonBeanFactory.getBean(APITestService.class);
if (apiTestService == null) {
@ -133,16 +118,29 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
LogUtil.error("testPlanApiCaseService is required");
}
apiEnvironmentRunningParamService = CommonBeanFactory.getBean(ApiEnvironmentRunningParamService.class);
if(apiEnvironmentRunningParamService == null){
if (apiEnvironmentRunningParamService == null) {
LogUtil.error("apiEnvironmentRunningParamService is required");
}
testPlanTestCaseService = CommonBeanFactory.getBean(TestPlanTestCaseService.class);
if(testPlanTestCaseService == null){
if (testPlanTestCaseService == null) {
LogUtil.error("testPlanTestCaseService is required");
}
super.setupTest(context);
}
private String getJmeterLogger(String testId) {
Long startTime = FixedTask.tasks.get(testId);
Long endTime = System.currentTimeMillis();
String logMessage = JmeterLoggerAppender.logger.entrySet().stream()
.filter(map -> map.getKey() > startTime && map.getKey() < endTime)
.map(map -> map.getValue())
.collect(Collectors.joining());
FixedTask.tasks.remove(testId);
if (FixedTask.tasks.isEmpty()) {
JmeterLoggerAppender.logger.clear();
}
return logMessage;
}
@Override
public void handleSampleResults(List<SampleResult> sampleResults, BackendListenerContext context) {
@ -153,16 +151,16 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
public void teardownTest(BackendListenerContext context) throws Exception {
TestResult testResult = new TestResult();
testResult.setTestId(testId);
testResult.setConsole(getConsole());
testResult.setConsole(getJmeterLogger(testId));
testResult.setTotal(0);
// 一个脚本里可能包含多个场景(ThreadGroup)所以要区分开key: 场景Id
final Map<String, ScenarioResult> scenarios = new LinkedHashMap<>();
queue.forEach(result -> {
// 线程名称: <场景名> <场景Index>-<请求Index>, 例如Scenario 2-1
if(StringUtils.equals(result.getSampleLabel(), RunningParamKeys.RUNNING_DEBUG_SAMPLER_NAME)){
if (StringUtils.equals(result.getSampleLabel(), RunningParamKeys.RUNNING_DEBUG_SAMPLER_NAME)) {
String evnStr = result.getResponseDataAsString();
apiEnvironmentRunningParamService.parseEvn(evnStr);
}else {
} else {
String scenarioName = StringUtils.substringBeforeLast(result.getThreadName(), THREAD_SPLIT);
String index = StringUtils.substringAfterLast(result.getThreadName(), THREAD_SPLIT);
String scenarioId = StringUtils.substringBefore(index, ID_SPLIT);
@ -194,7 +192,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
testResult.addPassAssertions(requestResult.getPassAssertions());
testResult.addTotalAssertions(requestResult.getTotalAssertions());
testResult.setTotal(testResult.getTotal()+1);
testResult.setTotal(testResult.getTotal() + 1);
scenarioResult.addPassAssertions(requestResult.getPassAssertions());
scenarioResult.addTotalAssertions(requestResult.getTotalAssertions());
}
@ -375,6 +373,7 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
/**
* 更新测试计划关联接口测试的功能用例的状态
*
* @param testResult
*/
private void updateTestCaseStates(TestResult testResult, String testPlanScenarioId) {

View File

@ -5,8 +5,13 @@ import io.metersphere.commons.utils.CommonBeanFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class FixedTask {
public static Map<String,Long> tasks = new HashMap<>();
@Scheduled(cron = "*/3 * * * * ?")
public void execute() {
ApiScenarioReportService scenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class);

View File

@ -112,6 +112,7 @@ public class JMeterService {
public void runLocal(String testId, HashTree testPlan, String debugReportId, String runMode) {
init();
FixedTask.tasks.put(testId,System.currentTimeMillis());
addBackendListener(testId, debugReportId, runMode, testPlan);
LocalRunner runner = new LocalRunner(testPlan);
runner.run();

View File

@ -0,0 +1,36 @@
package io.metersphere.api.jmeter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.UnsynchronizedAppenderBase;
import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.LogUtil;
import java.util.LinkedHashMap;
import java.util.Map;
public class JmeterLoggerAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
public static Map<Long, StringBuffer> logger;
@Override
public void append(ILoggingEvent event) {
try {
if (logger == null) {
logger = new LinkedHashMap<>();
}
if (event.getLevel().levelStr.equals(LogUtil.INFO)) {
StringBuffer message = new StringBuffer();
message.append(DateUtils.getTimeStr(event.getTimeStamp())).append(" ")
.append(event.getLevel()).append(" ")
.append(event.getThreadName()).append(" ")
.append(event.getFormattedMessage()).append("\n");
if (logger.containsKey(event.getTimeStamp())) {
logger.get(event.getTimeStamp()).append(message);
} else {
logger.put(event.getTimeStamp(), message);
}
}
} catch (Exception e) {
LogUtil.error(e);
}
}
}

View File

@ -11,10 +11,10 @@ public class LogUtil {
//日志工具类
// public static final Log Logger = LogFactory.getLog(LogUtil.class);
private static final String DEBUG = "DEBUG";
private static final String INFO = "INFO";
private static final String WARN = "WARN";
private static final String ERROR = "ERROR";
public static final String DEBUG = "DEBUG";
public static final String INFO = "INFO";
public static final String WARN = "WARN";
public static final String ERROR = "ERROR";
/**
* 初始化日志

View File

@ -140,11 +140,17 @@
<includeCallerData>true</includeCallerData>
<appender-ref ref="warnAppender" />
</appender>
<!-- 自定义JMETER输出日志 -->
<appender name="JMETER_LOG" class="io.metersphere.api.jmeter.JmeterLoggerAppender"/>
<root level="INFO">
<appender-ref ref="infoAsyncAppender" />
<appender-ref ref="console"/>
</root>
<!--将JMETER日志单独输出的包路径-->
<logger name="org.apache.jmeter" additivity="false" level="${logger.level:INFO}">
<appender-ref ref="JMETER_LOG"/>
</logger>
<logger name="io.metersphere" additivity="false">
<level value="${logger.level:INFO}"/>