Distributed Performance Testing Framework: Jar Method Scenarios, Demo Implementation, and Execution
This article explains how to design and implement distributed performance testing cases using jar‑method invocations, demonstrates a Java demo with reflection‑based execution, discusses common pitfalls, and shows how to package, deploy, and run the test cases within a Docker‑enabled environment.
Continuing from the previous article on distributed performance testing framework ideas, this part focuses on more complex test cases that invoke jar class methods and will later be validated with Docker.
Part1 Based on jar class method load testing scenario
The performance test scripts use the FunTester framework; this section shares pre‑written test cases exposing parameters such as thread count, ramp‑up time, and termination conditions. These stable cases are suitable for baseline performance tests, performance inspections, and regular regression testing.
Unlike the single‑request and multi‑request modes described earlier, the scripts now support single‑link, multi‑link, and full‑link testing, making them ideal for interfaces that require signatures per request.
Note: Local shell command execution has been abandoned due to its complexity and lack of control.
Part2 Demo Implementation
A test class is provided that demonstrates reflection execution of four method types: no‑arg, primitive‑type parameter, String object parameter, and String array parameter. The demo relies on com.funtester.frame.execute.ExecuteSource to invoke methods inside a jar.
Below is the test class code:
public class Test3 extends SourceCode {
private static final Logger logger = LogManager.getLogger(Test3.class);
public static void main(String[] args) {
ExecuteSource.executeMethod("com.funtest.javatest.Test3.funtest");
ExecuteSource.executeMethod("com.funtest.javatest.Test3.funtest", "java.lang.Integer", "1");
ExecuteSource.executeMethod("com.funtest.javatest.Test3.funtester", "java.lang.Integer", "1");
ExecuteSource.executeMethod("com.funtest.javatest.Test3.funtester", "java.lang.String", "33,3234,43,24,23,4,22");
}
public static void funtest() {
output(Time.getDate());
}
public static void funtest(Integer i) {
output(i + TAB + Time.getDate());
}
public static void funtester(int i) {
output(i * 10 + TAB + Time.getDate());
}
public static void funtester(String[] i) {
output(i.length * 10 + TAB + Time.getDate());
}
public static void funtester(String i) {
funtester(i.split(COMMA));
}
}Console output example:
INFO-> 当前用户:oker,工作目录:/Users/oker/IdeaProjects/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO-> 2021-05-13 18:24:05
INFO-> 1 2021-05-13 18:24:05
WARN-> 方法属性处理错误!
INFO-> 10 2021-05-13 18:24:05
INFO-> 70 2021-05-13 18:24:05
Process finished with exit code 0A known issue is that Java reflection may fail to locate overloaded methods with primitive parameters (e.g., int ), while using wrapper types like java.lang.Integer works reliably.
Another pitfall is that passing a String[] to a reflected method often fails; the author suggests adding a generic main(String args) method that splits the argument string and delegates to the appropriate overload.
Part3 Test Case Creation
1 Single Interface
For simple cases, a standard template is provided:
public static void main(String[] args) {
ClientManage.init(60, 60, 0, "", 0);
ArgsUtil util = new ArgsUtil(args);
int thread = util.getIntOrdefault(0, 2);
int times = util.getIntOrdefault(1, 10);
Constant.RUNUP_TIME = util.getIntOrdefault(2, 10);
MySqlTest.LOG_KEY = false;
String url = "http://localhost:12345/test/qps";
JSONObject params = new JSONObject();
params.put("name", "FunTester");
params.put("password", "123456798");
Sign.sign(params);
HttpGet httpGet = getHttpGet(url, params);
RequestThreadTimes requestThreadTimes = new RequestThreadTimes(httpGet, times, null);
Concurrent funTester = new Concurrent(requestThreadTimes, thread, "FunTester测试反射执行");
funTester.start();
}The script uses com.funtester.frame.thread.RequestThreadTimes for multithreaded execution, which has been updated to a newer implementation compatible with the current project.
2 Multiple Interfaces and Link Testing
The author refers to a previous article on link‑level performance testing and provides a Groovy‑style script that builds a list of tasks, each represented by a FunTester thread, and runs them via a Concurrent executor.
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.funtester.base.bean.AbstractBean
import com.funtester.base.constaint.ThreadLimitTimesCount
import com.funtester.frame.execute.Concurrent
import com.funtester.httpclient.ClientManage
import com.funtester.utils.ArgsUtil
import com.okayqa.composer.base.OkayBase
import com.okayqa.composer.function.Mirro
import com.okayqa.composer.function.OKClass
class Login_collect_uncollect extends OkayBase {
public static void main(String[] args) {
ClientManage.init(10, 5, 0, "", 0)
def util = new ArgsUtil(args)
def thread = util.getIntOrdefault(0, 30)
def times = util.getIntOrdefault(1, 40)
def tasks = []
thread.times { tasks << new FunTester(it, times) }
new Concurrent(tasks, "资源库1.4登录>查询>收藏>取消收藏链路压测").start()
allOver()
}
// ... inner class definitions omitted for brevity ...
}Part4 Test Case Transmission
3 Upload Test Cases
After writing the test case, simply package, compile, and restart the service. The author mentions advanced topics such as Java hot‑update and custom ClassLoader usage.
4 Distribute Test Cases
Distribution follows the same approach as described in the first part of the series, differing only in the design of the task class objects.
Part5 Test Case Execution
The execution class ExecuteSource provides overloaded executeMethod utilities that accept parameter lists, resolve method signatures via reflection, and invoke the target methods, handling primitive‑type and JSON parameter conversions.
package com.funtester.frame.execute;
import com.alibaba.fastjson.JSON;
import com.funtester.base.exception.FailException;
import com.funtester.frame.SourceCode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
public class ExecuteSource extends SourceCode {
private static Logger logger = LogManager.getLogger(ExecuteSource.class);
// ... method implementations omitted for brevity ...
}Some unused methods have been removed; interested readers can explore the repository for the full source.
For more articles and resources, see the list of links at the end of the original post.
FunTester
10k followers, 1k articles | completely useless
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.