Commit 20d381eb by 吴博

feat: [none] ws_auto_test

parent 124f8e6f
...@@ -281,7 +281,40 @@ ...@@ -281,7 +281,40 @@
<version>3.1.1-RELEASE</version> <version>3.1.1-RELEASE</version>
</dependency> </dependency>
<dependency>
<groupId>CGLIB</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version> <!-- 确保版本适合您的项目 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.6.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>3.3.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.14</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.6.9</version> <!-- 使用正确定义的版本 -->
</dependency>
</dependencies> </dependencies>
......
...@@ -13,6 +13,7 @@ import com.lemon.utils.HttpUtils; ...@@ -13,6 +13,7 @@ import com.lemon.utils.HttpUtils;
import io.qameta.allure.Step; import io.qameta.allure.Step;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.AfterSuite; import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeSuite;
...@@ -227,9 +228,7 @@ public class BaseCase { ...@@ -227,9 +228,7 @@ public class BaseCase {
@Step("结束") @Step("结束")
public void finish() { public void finish() {
//所有的接口都执行完毕后再执行批量回写 //所有的接口都执行完毕后再执行批量回写
log.info("===================批量回写===================");
ExcelUtils.batchWrite();
log.info("===================项目结束===================");
} }
......
...@@ -3,24 +3,18 @@ package com.lemon.cases; ...@@ -3,24 +3,18 @@ package com.lemon.cases;
import cn.hutool.core.lang.UUID; import cn.hutool.core.lang.UUID;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.lemon.constants.Constants; import com.lemon.constants.Constants;
import com.lemon.pojo.API;
import com.lemon.pojo.Case; import com.lemon.pojo.Case;
import com.lemon.pojo.TestRecord; import com.lemon.pojo.TestRecord;
import com.lemon.testng.WebSocketManager; import com.lemon.testng.WebSocketManager;
import com.lemon.utils.ExcelUtils; import com.lemon.utils.ExcelUtils;
import com.lemon.utils.SqlUtils;
import com.pcloud.llm.cockpit.api.domain.dto.request.DifyRequestFile;
import com.pcloud.llm.cockpit.api.domain.dto.request.WorkflowRequestBody; import com.pcloud.llm.cockpit.api.domain.dto.request.WorkflowRequestBody;
import com.pcloud.llm.cockpit.api.domain.dto.response.CompletionResponse; import com.pcloud.llm.cockpit.api.domain.dto.response.CompletionResponse;
import com.pcloud.llm.cockpit.client.DifyClient;
import org.apache.http.client.utils.DateUtils; import org.apache.http.client.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.AfterClass; import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
...@@ -38,25 +32,28 @@ import java.util.concurrent.TimeUnit; ...@@ -38,25 +32,28 @@ import java.util.concurrent.TimeUnit;
import static com.lemon.utils.Robot.sendAlarm; import static com.lemon.utils.Robot.sendAlarm;
@Component
public class changjiangzuoyeserveCase extends BaseCase { public class changjiangzuoyeserveCase extends BaseCase {
private WebSocketManager webSocketManager; private WebSocketManager webSocketManager;
@Autowired
private DifyClient difyClient;
//excel用例路径 //excel用例路径
public static final String EXCEL_PATH = "src/test/resources/changjiangcase.xls"; public static final String EXCEL_PATH = "src/test/resources/changjiangcase.xls";
private static final String ramdonUserId = UUID.randomUUID().toString(); private static final String ramdonUserId = UUID.randomUUID().toString();
private String caseTraceId; private String caseTraceId;
@BeforeClass() @BeforeClass()
public void setup() throws URISyntaxException { public void setup() throws URISyntaxException {
webSocketManager = new WebSocketManager(); webSocketManager = new WebSocketManager();
webSocketManager.connect(); webSocketManager.connect();
// 清空所有共享变量
ExcelUtils.wbdList.clear();
ExcelUtils.caseList.clear();
ExcelUtils.parameterList.clear();
ExcelUtils.apiList.clear();
} }
...@@ -101,12 +98,10 @@ public class changjiangzuoyeserveCase extends BaseCase { ...@@ -101,12 +98,10 @@ public class changjiangzuoyeserveCase extends BaseCase {
Assert.assertTrue(event5Received, "未在规定时间内收到 event-5 响应"); Assert.assertTrue(event5Received, "未在规定时间内收到 event-5 响应");
// 验证 event-5 消息的内容 // 验证 event-5 消息的内容
log.info(caseTraceId + "event5 收到的消息是: " + JSONUtil.toJsonStr(webSocketManager.event5Messages)); log.info(caseTraceId + "event5 收到的消息是: " + JSONUtil.toJsonStr(webSocketManager.event5Messages));
/*
addWBD(Integer.parseInt(cas.getId()), Constants.ASSERT_RESULT_CELL_NUM, "");
*/
Assert.assertNotNull(webSocketManager.event5Messages, "event-5 消息不应为空"); Assert.assertNotNull(webSocketManager.event5Messages, "event-5 消息不应为空");
addWBD(Integer.parseInt(cas.getId()), 6, JSONUtil.toJsonStr(webSocketManager.event5Messages));
cas.setActualValue(JSONUtil.toJsonStr(webSocketManager.event5Messages)); cas.setActualValue(JSONUtil.toJsonStr(webSocketManager.event5Messages));
cas.setPassState(cas.getExpectValue().equals(cas.getActualValue()) ? 1 : 0); cas.setPass(cas.getExpectValue().equals(cas.getActualValue()) ? 1 : 0);
} catch (Exception e) { } catch (Exception e) {
log.info(caseTraceId + "testReceiveEvent5Responses,WebSocket出错: " + e.getMessage()); log.info(caseTraceId + "testReceiveEvent5Responses,WebSocket出错: " + e.getMessage());
} finally { } finally {
...@@ -118,14 +113,14 @@ public class changjiangzuoyeserveCase extends BaseCase { ...@@ -118,14 +113,14 @@ public class changjiangzuoyeserveCase extends BaseCase {
testRecord.setExpectContent(cas.getExpectValue()); testRecord.setExpectContent(cas.getExpectValue());
testRecord.setInputContent(cas.getParams()); testRecord.setInputContent(cas.getParams());
testRecord.setOutputContent(JSONUtil.toJsonStr(webSocketManager.event5Messages)); testRecord.setOutputContent(JSONUtil.toJsonStr(webSocketManager.event5Messages));
testRecord.setState(cas.getPassState()); testRecord.setState(cas.getPass());
testRecord.setTestVersion(DateUtils.formatDate(new Date(), "yyyyMMdd HH:mm")); testRecord.setTestVersion(DateUtils.formatDate(new Date(), "yyyyMMdd HH:mm"));
testRecord.setCreateTime(new Date()); testRecord.setCreateTime(new Date());
testRecord.setUpdateTime(new Date()); testRecord.setUpdateTime(new Date());
testRecord.setIsDelete(0); testRecord.setIsDelete(0);
// SqlUtils.insertTestRecord(testRecord); // SqlUtils.insertTestRecord(testRecord);
// 如果失败则发送消息提醒 // 如果失败则发送消息提醒
if (cas.getPassState() == null || cas.getPassState() == 0) if (cas.getPass() == null || cas.getPass() == 0)
sendAlarm(cas.getParams()); sendAlarm(cas.getParams());
} }
} }
...@@ -155,26 +150,23 @@ public class changjiangzuoyeserveCase extends BaseCase { ...@@ -155,26 +150,23 @@ public class changjiangzuoyeserveCase extends BaseCase {
inputs.put("inquery", jsonStr); inputs.put("inquery", jsonStr);
WorkflowRequestBody requestBody = WorkflowRequestBody.builder().user(ramdonUserId).inputs(inputs).build(); WorkflowRequestBody requestBody = WorkflowRequestBody.builder().user(ramdonUserId).inputs(inputs).build();
log.info(caseTraceId + "调用dify请求参数:" + JSONUtil.toJsonStr(requestBody)); log.info(caseTraceId + "调用dify请求参数:" + JSONUtil.toJsonStr(requestBody));
int count = 0;
String res = ""; String res = "";
try { try {
do { CompletionResponse aiTopicScience = webSocketManager.workflowsRunBlocking("ai_autotest", requestBody);
CompletionResponse aiTopicScience = difyClient.workflowsRunBlocking("ai_autotest", requestBody); Map<String, Object> outputs = aiTopicScience.getData().getOutputs();
Map<String, Object> outputs = aiTopicScience.getData().getOutputs(); res = (String) outputs.get("result");
res = (String) outputs.get("result"); res = res.replace("```json", "").replace("```", "");
if (count > 3) { List<Case> resultList = JSONUtil.toList(res,Case.class);
log.info(caseTraceId + "没有返回指定内容,dify调用开始重试" + com.alibaba.fastjson.JSONObject.toJSONString(requestBody)); for (Case item : resultList) {
break; addWBD(Integer.parseInt(item.getId()), 7, Optional.ofNullable(item.getPass()).map(String::valueOf).orElse(""));
} }
int finalCount = count;
ThreadUtil.safeSleep(1 + finalCount * 2L);
count++;
} while (!StrUtil.containsAny(res, "考查知识", "解题思路", "分步骤讲解"));
} catch (Exception e) { } catch (Exception e) {
log.warn("请求dify异常:{}" + e.getMessage()); log.warn("请求dify异常:{}" + e.getMessage());
} }
log.info(caseTraceId + "dify返回的内容======>{}" + res); log.info(caseTraceId + "dify返回的内容======>{}" + res);
log.info("===================批量回写===================");
ExcelUtils.batchWrite(EXCEL_PATH);
log.info("===================项目结束===================");
} }
@DataProvider(name = "data1") @DataProvider(name = "data1")
......
package com.lemon.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@ComponentScan({"com.lemon","com.pcloud"})
@EnableScheduling
public class AppContext {
}
package com.lemon.config;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
/**
* @description: 启动类
*
* @author: huwei
* @dateTime: 2023/5/24 14:12
*/
@SpringBootApplication
public class AskBooksApplication {
public static void main(String[] args) {
// 定义Nacos相关目录,即当前项目运行所在目录,会自动建nacos目录
System.setProperty("JM.LOG.PATH", ".");
System.setProperty("JM.SNAPSHOT.PATH", ".");
new SpringApplicationBuilder(AskBooksApplication.class).build(args).run(args);
}
}
package com.lemon.config;
import com.pcloud.llm.cockpit.client.DifyClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DifyClientConfig {
@Bean
public DifyClient difyClient() {
System.out.println("开始创建DifyClient");
// 在这里创建 DifyClient 的实例,并进行所需的配置
return new DifyClient(/* 参数配置 */);
}
}
\ No newline at end of file
...@@ -33,7 +33,7 @@ public class Case { ...@@ -33,7 +33,7 @@ public class Case {
@Excel(name = "消息条数") @Excel(name = "消息条数")
private Integer messageCount; private Integer messageCount;
@Excel(name = "是否验证通过") @Excel(name = "是否验证通过")
private Integer passState; private Integer pass;
@Excel(name = "实际响应数据") @Excel(name = "实际响应数据")
private String actualValue; private String actualValue;
...@@ -41,7 +41,7 @@ public class Case { ...@@ -41,7 +41,7 @@ public class Case {
} }
public Case(String id, String desc, String params, String apiID, String expectValue, String checkSQL, String aExpectValue, public Case(String id, String desc, String params, String apiID, String expectValue, String checkSQL, String aExpectValue,
String checkBSQL, String bExpectValue,Boolean stream, Integer messageCount,Integer passState,String actualValue) { String checkBSQL, String bExpectValue,Boolean stream, Integer messageCount,Integer pass,String actualValue) {
this.id = id; this.id = id;
this.desc = desc; this.desc = desc;
this.params = params; this.params = params;
...@@ -53,7 +53,7 @@ public class Case { ...@@ -53,7 +53,7 @@ public class Case {
this.bExpectValue = bExpectValue; this.bExpectValue = bExpectValue;
this.stream = stream; this.stream = stream;
this.messageCount = messageCount; this.messageCount = messageCount;
this.passState = passState; this.pass = pass;
this.actualValue = actualValue; this.actualValue = actualValue;
} }
...@@ -145,12 +145,12 @@ public class Case { ...@@ -145,12 +145,12 @@ public class Case {
this.messageCount = messageCount; this.messageCount = messageCount;
} }
public Integer getPassState() { public Integer getPass() {
return passState; return pass;
} }
public void setPassState(Integer passState) { public void setPass(Integer pass) {
this.passState = passState; this.pass = pass;
} }
public String getActualValue() { public String getActualValue() {
...@@ -175,7 +175,7 @@ public class Case { ...@@ -175,7 +175,7 @@ public class Case {
", bExpectValue='" + bExpectValue + '\'' + ", bExpectValue='" + bExpectValue + '\'' +
", stream=" + stream + ", stream=" + stream +
", messageCount=" + messageCount + ", messageCount=" + messageCount +
", passState=" + passState + ", pass=" + pass +
", actualValue='" + actualValue + '\'' + ", actualValue='" + actualValue + '\'' +
'}'; '}';
} }
......
package com.lemon.testng; package com.lemon.testng;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.lemon.utils.AuthorizationUtils; import com.lemon.utils.AuthorizationUtils;
import com.pcloud.llm.cockpit.api.constants.Constants;
import com.pcloud.llm.cockpit.api.domain.dto.request.WorkflowRequestBody;
import com.pcloud.llm.cockpit.api.domain.dto.response.CompletionResponse;
import com.pcloud.llm.cockpit.api.domain.dto.response.CompletionResponseData;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.java_websocket.client.WebSocketClient; import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake; import org.java_websocket.handshake.ServerHandshake;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestTemplate;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
...@@ -116,4 +129,34 @@ public class WebSocketManager { ...@@ -116,4 +129,34 @@ public class WebSocketManager {
public void close() { public void close() {
webSocketClient.close(); webSocketClient.close();
} }
/**
* 工作流同步接口
* @param callCode Dify调用code
* @param dto 参数
* @return 同步返回
*/
public CompletionResponse workflowsRunBlocking(String callCode, WorkflowRequestBody dto) {
dto.setResponse_mode(Constants.RESPONSE_MODE_BLOCKING);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
headers.add(Constants.CALL_CODE_HEADER, callCode);
try {
String server = "http://192.168.92.235:8313";
HttpRequest post= HttpUtil.createPost(server + "/v1/workflows/run");
post.addHeaders(headers.toSingleValueMap());
post.body(JSONUtil.toJsonStr(dto));
HttpResponse httpResponse = post.execute();
CompletionResponse result = JSONUtil.toBean(httpResponse.body(), CompletionResponse.class);
log.info("workflow:" + callCode + "->" + JSON.toJSONString(dto) + "=>" + JSON.toJSONString(result) + ",server=" + server);
return result;
} catch (Throwable t) {
log.error("workflow:" + callCode + "->" + JSON.toJSONString(dto), t);
CompletionResponse result = new CompletionResponse();
CompletionResponseData data = new CompletionResponseData();
data.setStatus("failed");
data.setError(t.getMessage());
return result;
}
}
} }
\ No newline at end of file
...@@ -54,7 +54,7 @@ public class ExcelUtils { ...@@ -54,7 +54,7 @@ public class ExcelUtils {
} finally { } finally {
close(fis); close(fis);
} }
return null; return new ArrayList<>();
} }
public static <E> List<E> read(String filePath,int startSheetIndex, Class<E> clazz) { public static <E> List<E> read(String filePath,int startSheetIndex, Class<E> clazz) {
...@@ -132,6 +132,38 @@ public class ExcelUtils { ...@@ -132,6 +132,38 @@ public class ExcelUtils {
} }
} }
// 不用传参,因为集合为静态方法,修改Excel需要用到原生的poi
public static void batchWrite(String filePath) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(filePath);
Workbook workbook = WorkbookFactory.create(fis);
Sheet sheet = workbook.getSheetAt(0);
//回写操作行和列
//1、遍历wbdList集合
for (WriteBackData wbd : wbdList) {
//2、获取行号,根据行号获取row对象
int rowNum = wbd.getRowNum();
Row row = sheet.getRow(rowNum);
//3、获取列号,根据列号获取cell对象
int cellNum = wbd.getCellNum();
Cell cell = row.getCell(cellNum, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
//4、获取回写内容,设置到cell中
cell.setCellType(CellType.STRING);
String content = wbd.getContent();
// 5、将数据设置到Excel对应行和列中
cell.setCellValue(content);
}
fos = new FileOutputStream(filePath);
workbook.write(fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
close(fis);
close(fos);
}
}
/* /*
* 从已经读取很多所有list<API>和所有list<Case> * 从已经读取很多所有list<API>和所有list<Case>
......
...@@ -20,8 +20,9 @@ ...@@ -20,8 +20,9 @@
<!-- </test>--> <!-- </test>-->
<test name="RAYS7服务"> <!-- 模块--> <test name="RAYS7服务"> <!-- 模块-->
<parameter name="excelPath" value="src/test/resources/changjiangcase.xls"/> <!-- 示例参数 -->
<classes> <classes>
<class name="com.lemon.cases.ServerCase"/> <!-- 测试类/用例类--> <class name="com.lemon.cases.changjiangzuoyeserveCase"/> <!-- 测试类/用例类-->
</classes> </classes>
</test> </test>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment