Operations 7 min read

Automating Complex API Tests with Groovy: A Modular Script Framework

This article presents a Groovy‑based modular framework for automating complex, interrelated API tests, detailing how to structure test modules, manage user credentials and tokens, and execute concurrent requests using custom thread handling, with full source code examples for the main driver, UserCenter, and base classes.

FunTester
FunTester
FunTester
Automating Complex API Tests with Groovy: A Modular Script Framework

Overview

This article describes a Groovy‑based framework for testing multi‑step API workflows. It builds on existing Java testing libraries and uses script‑driven execution to simulate realistic user interactions such as login, token handling, and password modification.

Architecture

The framework is organized around three core classes:

OkayBase – provides common utilities (logging, user identity fields, token handling, request parameter construction, password encryption, and a generic isRight(JSONObject) method that validates the response meta code and data presence).

UserCenter – extends OkayBase and implements the password‑change API call. It builds the request parameters, encrypts the passwords with RSAUtils.getPassword(), sends a POST request, logs the response, and updates the stored token when the call succeeds.

T8 – the entry point that creates a configurable thread pool to execute the modifyPwd() operation concurrently.

Core Workflow

The password‑change scenario follows these steps:

Login using the User object's uname and pwd to obtain an initial token.

Call the modify‑pwd endpoint with three parameters: newpwd, oldpwd, and the current token.

If the response is successful, extract the new token from response.data.token and store it for subsequent requests.

Threaded Execution (class T8 )

The main method expects two command‑line arguments: args[0] – number of concurrent threads. args[1] – number of requests each thread should perform.

For each thread the following actions are performed:

Obtain a base instance via getBase(i) (provides user credentials).

Instantiate UserCenter with the base.

Execute a warm‑up call userCenter.modifyPwd().

Create an anonymous subclass of ThreadBase that overrides doing() to repeatedly invoke userCenter.modifyPwd().

Set the repeat count with threadBase.setTimes(times) and add the thread to a list.

After all thread objects are prepared, a Concurrent runner starts them in parallel, and allOver() is called to clean up resources.

class T8 extends OkayBase {
    public static void main(String[] args) {
        int thread = changeStringToInt(args[0]);
        int times = changeStringToInt(args[1]);
        List<ThreadBase> threads = new ArrayList<>();
        for (int i = 0; i < thread; i++) {
            OkayBase base = getBase(i);
            UserCenter userCenter = new UserCenter(base);
            userCenter.modifyPwd(); // warm‑up
            ThreadBase threadBase = new ThreadBase() {
                @Override
                protected void before() {}
                @Override
                protected void doing() throws Exception {
                    userCenter.modifyPwd();
                }
                @Override
                protected void after() {}
            };
            threadBase.setTimes(times);
            threads.add(threadBase);
        }
        new Concurrent(threads).start();
        allOver();
    }
}

Implementation of UserCenter

public class UserCenter extends OkayBase {
    private static Logger logger = LoggerFactory.getLogger(UserCenter.class);

    public UserCenter(OkayBase okayBase) {
        super(okayBase);
    }

    public JSONObject modifyPwd() {
        String url = UserApi.MODIFY_PWD;
        JSONObject params = getParams();
        params.put("newpwd", getPassword(this.getUname()));
        params.put("oldpwd", getPassword(this.getPwd()));
        JSONObject response = getPostResponse(url, params);
        output(response);
        if (isRight(response)) {
            String token = response.getJSONObject("data").getString("token");
            this.setToken(token);
        }
        return response;
    }
}

Implementation of OkayBase

public class OkayBase extends SourceCode implements IBase {
    private static Logger logger = LoggerFactory.getLogger(OkayBase.class);
    int uid;
    String token;
    String uname;
    String pwd;

    public OkayBase(String uname, String pwd) {
        this.uname = uname;
        this.pwd = pwd;
        login();
    }

    public String getPassword() {
        String s = uname.substring(uname.length() - 6);
        return getPassword(s);
    }

    public String getPassword(String pwd) {
        return RSAUtils.getPassword(pwd);
    }

    public JSONObject getParams() {
        JSONObject json = getJson("uid=" + uid, "token=" + token);
        json.put("imei", "isFake");
        json.put("serial", "W170500652");
        json.put("ua", "f_an_4..0");
        return json;
    }

    @Override
    public boolean isRight(JSONObject jsonObject) {
        int code = TEST_ERROR_CODE;
        try {
            code = jsonObject.getJSONObject("meta").getInt("ecode");
            JSONObject data = jsonObject.getJSONObject("data");
            return code == 0 && !data.isEmpty();
        } catch (Exception e) {
            return false;
        }
    }

    /** Test cleanup */
    public static void allOver() {
        FanLibrary.testOver();
    }
}

Key Points

State is carried between modules via a shared User object (username, password, token, etc.).

Passwords are encrypted on the client side using RSAUtils.getPassword() before being sent.

The framework’s modular design allows easy addition of new API groups while reusing common utilities from OkayBase.

Configurable thread count and request repetitions enable performance testing, regression verification, and complex scenario automation.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaAutomationconcurrencyScriptingGroovyAPI testing
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.