public class RunGroovy {
@Setter
private SpringContainer springContainer;
public void run(RunEngineRequest runEngineRequest, RunStepCallback callback) {
TestStep testStep = runEngineRequest.getTestStep();
RuntimeContext runtimeContext =runEngineRequest.getRuntimeContext();
TestData testData = runEngineRequest.getTestData();
try {
final GroovyClassLoader classLoader = new GroovyClassLoader();
Class groovy = classLoader.parseClass(testStep.getActionScript());
ScriptMeta scriptMeta = parse(groovy);
GroovyObject groovyObj = (GroovyObject) groovy.newInstance();
//Step 1: 注入输入参数
injectIn(scriptMeta, groovyObj, runtimeContext, testData);
//Step 2: 注入服务
injectService(scriptMeta, groovyObj);
//Step 3: 执行prepare --> action --> cleanup
executeScript(scriptMeta, groovyObj);
//Step 4: 如果执行过程中没有抛出异常则将输出参数填充到上下文中
fillRuntimeContext(scriptMeta, groovyObj, runtimeContext);
callback.onSuccess(testStep, testData, runtimeContext,null);
} catch (Exception | VariableNotDefineException e) {
callback.onException(testStep, testData, runtimeContext, e.getMessage());
}
}
private void injectService(ScriptMeta scriptMeta, GroovyObject groovyObj) throws ServiceNotFoundException {
for (String service : scriptMeta.serviceList) {
Object serviceRef = springContainer.getBeanByName(service);
if (null == serviceRef) {
throw new ServiceNotFoundException("服务:" + service + "没有找到!请确认服务已在配置文件中配置.");
}
groovyObj.setProperty(service, serviceRef);
}
}
/**
* 解析出out的变量以及对应的值,设置到运行的上下文中
*
* @param scriptMeta
* @param groovyObj
* @param runtimeContext
*/
private void fillRuntimeContext(ScriptMeta scriptMeta, GroovyObject groovyObj,
RuntimeContext runtimeContext) {
scriptMeta.outList.forEach((v) -> {
Object o = groovyObj.getProperty(v);
runtimeContext.put(v, o);
});
}
/**
* 执行prepare --> action --> cleanup
*
* @param scriptMeta
* @param groovyObj
*/
private void executeScript(ScriptMeta scriptMeta, GroovyObject groovyObj) {
if (scriptMeta.containPrepare) {
groovyObj.invokeMethod("prepare", new Object[] {});
}
groovyObj.invokeMethod("action", new Object[] {});
if (scriptMeta.containCleanup) {
groovyObj.invokeMethod("cleanup", new Object[] {});
}
}
/**
* //——注入输入值.优先从上下文中,如果上下文中未到找到,会到测试数据中再查找变量的值
* 测试数据来源于3部分,本地默认数据、页面配置数据,执行上下文
* @param scriptMeta 脚本的元数据配置
* @param groovyObj
* @param runtimeContext
* @param testData
*/
/**
* 注入输入值.优先从上下文中,如果上下文中未到找到,会到测试数据中再查找变量的值
*
* @param scriptMeta 脚本的元数据配置
* @param groovyObj
* @param runtimeContext
* @param testData
*/
private void injectIn(ScriptMeta scriptMeta, GroovyObject groovyObj,
RuntimeContext runtimeContext, TestData testData) throws VariableNotDefineException {
List<String> notFoundVar = Lists.newArrayList();
scriptMeta.inMap.forEach((k, v) -> {
//优先从上下文中查找,其它是测试数据中
if (runtimeContext.containsKey(k)) {
groovyObj.setProperty(k, runtimeContext.get(k));
} else {
if (testData.contain(k)) {
groovyObj.setProperty(k, testData.getValue(k));
} else {
if (!v) {
notFoundVar.add(k);
}
}
}
});
if (!notFoundVar.isEmpty()) {
throw new VariableNotDefineException(notFoundVar);
}
}
/**
* 解析groovy的class上的in和out注解
*
* @param groovy
*/
private ScriptMeta parse(Class groovy) {
ScriptMeta scriptMeta = new ScriptMeta();
//读取脚本上的注解
Field[] fields = groovy.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
In in = field.getAnnotation(In.class);
if (in != null) {
scriptMeta.inMap.put(field.getName(), in.continueWhenNotFound());
}
Out out = field.getAnnotation(Out.class);
if (out != null) {
scriptMeta.outList.add(field.getName());
}
Service service = field.getAnnotation(Service.class);
if (service != null) {
scriptMeta.serviceList.add(field.getName());
}
}
//prepare和cleanup是可选的
Method[] methods = groovy.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals("prepare")) {
scriptMeta.containPrepare = true;
}
if (method.getName().equals("cleanup")) {
scriptMeta.containCleanup = true;
}
}
return scriptMeta;
}
private class ScriptMeta {
/**
* key是字段的名称,value是当变量未找到时是否继续.true表示继续,false表示不继续
*/
Map<String, Boolean> inMap = Maps.newHashMap();
List<String> outList = Lists.newArrayList();
List<String> serviceList = Lists.newArrayList();
boolean containPrepare;
boolean containCleanup;
}
groovy脚本
于 2021-01-15 16:45:05 首次发布