接口測試中Groovy可以作為上下游接口參數(shù)化傳遞的前置腳本和后置腳本使用,無縫銜接Java語法,groovy的引入對于動態(tài)參數(shù)化的設(shè)置方便很多。
其中核心部分就是接入groovy的引擎,下面介紹groovy引擎的實現(xiàn)邏輯。
- pom文件groovy核心依賴
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>3.0.7</version>
</dependency>
<dependency>
<groupId>org.kohsuke</groupId>
<artifactId>groovy-sandbox</artifactId>
<version>1.19</version>
</dependency>
1、Groovy引擎中添加常用的import
靜態(tài)代碼塊中引入
一些基礎(chǔ)的依賴,比如:JSONObject、JSONArray、JsonPath等工具類
static {
config = new CompilerConfiguration();
// 添加默認import
config.addCompilationCustomizers(new ImportCustomizer().addImports(
"com.taltools.script.exception.StepFailureException",
"com.jayway.jsonpath.JsonPath",
"com.alibaba.fastjson.JSONObject",
"com.alibaba.fastjson.JSONArray",
"groovy.json.JsonSlurper",
"org.apache.commons.codec.digest.DigestUtils",
"org.apache.commons.codec.digest.HmacUtils"));
// 添加線程中斷攔截器
config.addCompilationCustomizers(new ASTTransformationCustomizer(ThreadInterrupt.class));
// 添加線程中斷攔截器,可中斷超時線程,當前定義超時時間為30s
config.addCompilationCustomizers(new ASTTransformationCustomizer(Collections.singletonMap("value", INTERRUPT_TIME_OUT), TimedInterrupt.class));
// 沙盒環(huán)境
config.addCompilationCustomizers(new SandboxTransformer());
NO_RUNTIME_SANDBOX = new NoRuntimeSandbox();
NO_SYSTEM_HARM_SANDBOX = new NoSystemHarmSandbox();
}
- 設(shè)置緩存容量&過期時間
{
lruCache = CacheBuilder.newBuilder()
.maximumSize(1000) //最大容量
.expireAfterAccess(12, TimeUnit.HOURS) //緩存過期時長
.concurrencyLevel(Runtime.getRuntime().availableProcessors())// 設(shè)置并發(fā)級別為cpu核心數(shù)
.build();
}
2、Groovy核心實現(xiàn),上下文參數(shù)綁定
- 上下文參數(shù)變量名綁定
@Override
public ScriptContext runScript(String scriptContent, ScriptContext context) {
if (scriptContent == null || scriptContent.isEmpty()) {
throw new IllegalArgumentException("輸入的script內(nèi)容不能為空");
}
log.debug("執(zhí)行Groovy腳本: {}", scriptContent);
Binding binding = generateBinding(context);
parseScript(scriptContent, binding).run();
ScriptContext retContext = new ScriptContext();
retContext.setVariables(binding.getVariables());
return retContext;
}
public long getCacheCount() {
return lruCache.size();
}
protected Script parseScript(String scriptContent, Binding binding) {
String md5 = DigestUtils.md5Hex(scriptContent);
String sha1 = DigestUtils.sha1Hex(scriptContent);
String key = md5 + "-" + sha1;
Class<? extends Script> scriptClass = lruCache.getIfPresent(key);
if (scriptClass == null) {
registerSandbox();
GroovyShell shell = new GroovyShell(config);
Script script = shell.parse(scriptContent);
scriptClass = script.getClass();
lruCache.put(key, scriptClass);
log.debug("未命中腳本LRU緩存,創(chuàng)建腳步對象并存入緩存,當前緩存數(shù)量: {}", getCacheCount());
} else {
log.debug("命中腳本LRU緩存, key: {}, 當前緩存數(shù)量: {}", key, getCacheCount());
}
return InvokerHelper.createScript(scriptClass, binding);
}
3、調(diào)傭Groovy引擎設(shè)置參數(shù)名測試
- 在單元測試中測試接受groovy腳本的返回值
@Test
public void testGroovy(){
String req = " outParams['name'] = testGroovy();\n" +
" static String testGroovy(){\n" +
" def name = 'java'\n" +
" def greeting = \"Hello ${name}\"\n" +
" return greeting\n" +
" }";
GroovyEngine engine = new GroovyEngine();
ScriptContext context = new ScriptContext();
LinkedHashMap<String, Object> outParams = new LinkedHashMap<>();
context.setVariable("outParams",outParams);
ScriptContext ret = engine.runScript(req,context);
System.out.println(JsonUtils.obj2json(ret));
System.out.println(outParams);
}
- 控制臺打印結(jié)果
- 前端頁面效果
關(guān)于groovy在接口測試平臺中的落地后續(xù)不斷補充,歡迎關(guān)注!Coding測試