Load Testing and Validation Rules for Phone Number Login API
This article details the challenges, validation rules, solution, test plan, and sample Groovy/Java code for performing a large‑scale load test of a phone‑number‑based login API, including configurable constraints and script examples for simulating thousands of users.
These past two days I faced a demanding load‑testing requirement for phone‑number login, which was tricky because I had never worked on this project before and the data volume was large, requiring coordination with developers to verify rules.
Business Logic:
Request the verification‑code API; a successful request (for a bound phone number and a valid user state) returns a login parameter traceNo.
Use traceNo, the SMS verification code, and the phone number to call the login API.
Basic Validation Rules:
Phone number validation: exclude non‑existent prefixes, ensure an 11‑digit numeric string.
Do not allow a second SMS within a 60‑second interval; the SMS validity period follows the same interval.
Do not allow more than ten SMS messages in a natural day.
The random verification code and traceNo must be obtained from the send‑code interface.
Solution:
All constraints are configurable and can be changed at any time; a service restart applies the new settings.
Select the 14 prefix, setting the user’s phone number to 14+uid.
Fix the verification code in the test environment.
Test Plan:
Combine the send‑code and SMS‑login interfaces in a single load test, requiring a batch of test users.
Bind one thread to one user and continuously send verification codes and log in with them.
Add base‑class attributes phone and module‑class attribute lastTraceNo to pass parameters.
Load Test Script:
The threadmark marks the task; the module method returns a token to uniquely identify each user’s login request, facilitating log tracing for developers.
/**
* 100 users send SMS and then log in with the verification code
*/
class LoginByTel extends OkayBase {
public static void main(String[] args) {
def argsUtil = new ArgsUtil(args)
def thread = argsUtil.getIntOrdefault(0, 100)
def times = argsUtil.getIntOrdefault(1, 50)
ClientManage.init(10000, 5000, 0)
def threads = []
thread.times {
def base = getBase(it)
def info = new UserInfo(base)
threads << new LoginTel(info, times)
}
new Concurrent(threads, "学生留存1.2.3手机验证码登录").start()
FanLibrary.testOver()
}
static class LoginTel extends ThreadLimitTimesCount<UserInfo> {
public LoginTel(UserInfo info, int times) {
super(info, times, null)
}
@Override
protected void doing() throws Exception {
threadmark = t.loginByTel()
}
}
}Module Method:
/**
* Phone number login
*/
public String loginByTel() {
sendCodeOffline(2, phone);
String url = Profile.LOGIN;
JSONObject params = getParams();
params.put("login_mode", 2);
params.put("params", getJson("code=" + Profile.LOGIN_CODE, "phone=" + phone));
JSONObject response = getPostResponse(url, params);
if (isRight(response)) {
token = response.getJSONObject("data").getString("token");
super.token = token;
logger.info("账号 {} 登录成功", account);
} else {
output(response);
logger.warn("账号 {} 登录失败", account);
fail();
}
return token;
}Disclaimer: “FunTester” is the original release; please follow, discuss, and do not repost without permission.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
