当前位置: 首页 > 测试知识 > TestNG测网络延迟怎么做?完整脚本编写示例
TestNG测网络延迟怎么做?完整脚本编写示例
2026-04-27 作者cwb 浏览次数5

TestNG测网络延迟就是将网络操作用Java标准库或第三方库实现,用TestNG来组织测试步骤、控制执行次数、收集延迟数据并断言是不是满足阈值。


提供两个可直接运行的示例:

TCP 连接延迟测试 — 测量 TCP 三次握手所需时间。

HTTP 请求延迟测试 — 测量完整的 HTTP 往返时间。


准备工作 (Maven 依赖)


xml

<!-- 仅需 TestNG -->

<dependency>

    <groupId>org.testng</groupId>

    <artifactId>testng</artifactId>

    <version>7.10.2</version>

    <scope>test</scope>

</dependency>


TCP连接延迟测试

原理:记录new Socket() + connect(timeout) 的前后时间差,多次测试后输出统计值并断言。


java

import org.testng.annotations.*;

import java.net.InetSocketAddress;

import java.net.Socket;

import java.util.ArrayList;

import java.util.List;


public class TcpLatencyTest {


    // 被测主机和端口

    private static final String HOST = "www.zmtests.com";

    private static final int PORT = 80;          // HTTP 端口,也可换其他开放端口

    private static final int CONNECT_TIMEOUT = 3000; // 连接超时(ms)


    // 存储每次成功测试的延迟(ns)

    private final List<Long> latencies = new ArrayList<>();


    /**

     * 预热:运行几次不记录结果,让 JIT 优化、操作系统缓存稳定

     */

    @Test(invocationCount = 5, groups = "warmup")

    public void warmup() throws Exception {

        measureTcpConnect();

    }


    /**

     * 正式测试:重复执行 50 次,每次记录 TCP 连接延迟

     */

    @Test(invocationCount = 50, dependsOnGroups = "warmup")

    public void tcpConnectLatencyTest() throws Exception {

        long start = System.nanoTime();

        measureTcpConnect();           // 建连操作

        long latency = System.nanoTime() - start;

        latencies.add(latency);

        System.out.printf("TCP connect latency: %.2f ms%n", latency / 1_000_000.0);

    }


    /**

     * 建连:创建 Socket 并建立连接

     */

    private void measureTcpConnect() throws Exception {

        try (Socket socket = new Socket()) {

            socket.connect(new InetSocketAddress(HOST, PORT), CONNECT_TIMEOUT);

        }

    }


    /**

     * 测试结束后输出延迟统计,并断言平均延迟低于阈值

     */

    @AfterClass

    public void reportAndAssert() {

        if (latencies.isEmpty()) {

            return;

        }

        double avg = latencies.stream().mapToLong(Long::longValue).average().orElse(0);

        long min = latencies.stream().mapToLong(Long::longValue).min().orElse(0);

        long max = latencies.stream().mapToLong(Long::longValue).max().orElse(0);

        double p99 = percentile(latencies, 99);


        System.out.println("\n===== TCP Connect Latency Statistics =====");

        System.out.printf("Samples: %d%n", latencies.size());

        System.out.printf("Average: %.2f ms%n", avg / 1_000_000.0);

        System.out.printf("Min: %.2f ms%n", min / 1_000_000.0);

        System.out.printf("Max: %.2f ms%n", max / 1_000_000.0);

        System.out.printf("P99: %.2f ms%n", p99 / 1_000_000.0);


        // 断言:平均延迟应小于 500 ms(按实际环境调整)

        assert avg / 1_000_000.0 < 500 :

            "TCP connect average latency too high: " + avg / 1_000_000.0 + " ms";

    }


    // 简单百分位数计算

    private double percentile(List<Long> list, double percentile) {

        List<Long> sorted = new ArrayList<>(list);

        sorted.sort(Long::compareTo);

        int index = (int) Math.ceil(percentile / 100.0 * sorted.size()) - 1;

        return sorted.get(Math.max(index, 0));

    }

}


说明:

直接右键类名-Run As-TestNG Test。

可通过修改HOST和PORT测试其他服务(如数据库 3306、Redis 6379)。

HTTP请求延迟测试

用java.net.HttpURLConnection发送GET请求,测量从发起请求到读取完响应的总时间(TTLB / TTFB 可按需拆分)。


java

import org.testng.annotations.*;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;


public class HttpLatencyTest {


    private static final String REQUEST_URL = "https://www.zmtests.com";

    private static final int CONNECT_TIMEOUT = 3000;

    private static final int READ_TIMEOUT = 3000;


    private final List<Long> latencies = new ArrayList<>();


    @Test(invocationCount = 5, groups = "warmup")

    public void warmup() throws Exception {

        sendGetRequest();

    }


    @Test(invocationCount = 50, dependsOnGroups = "warmup")

    public void httpRequestLatencyTest() throws Exception {

        long start = System.nanoTime();

        int status = sendGetRequest();

        long latency = System.nanoTime() - start;


        // 仅记录成功请求(状态码 2xx 或 3xx)

        if (status >= 200 && status < 400) {

            latencies.add(latency);

            System.out.printf("HTTP latency: %.2f ms (status %d)%n", latency / 1_000_000.0, status);

        } else {

            System.err.printf("Non-success status %d%n", status);

        }

    }


    private int sendGetRequest() throws Exception {

        URL url = new URL(REQUEST_URL);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        conn.setRequestMethod("GET");

        conn.setConnectTimeout(CONNECT_TIMEOUT);

        conn.setReadTimeout(READ_TIMEOUT);

        conn.setInstanceFollowRedirects(true); // 跟随重定向


        int status = conn.getResponseCode();

        // 必须消耗完响应体,否则影响后续连接复用及时间测量

        byte[] buffer = new byte[4096];

        while (conn.getInputStream().read(buffer) != -1) { /* 读取完所有数据 */ }

        conn.disconnect();

        return status;

    }


    @AfterClass

    public void reportAndAssert() {

        if (latencies.isEmpty()) {

            System.err.println("No successful HTTP requests recorded.");

            return;

        }

        double avg = latencies.stream().mapToLong(Long::longValue).average().orElse(0);

        long min = latencies.stream().mapToLong(Long::longValue).min().orElse(0);

        long max = latencies.stream().mapToLong(Long::longValue).max().orElse(0);

        double p99 = percentile(latencies, 99);


        System.out.println("\n===== HTTP Request Latency Statistics =====");

        System.out.printf("Successful samples: %d%n", latencies.size());

        System.out.printf("Average: %.2f ms%n", avg / 1_000_000.0);

        System.out.printf("Min: %.2f ms%n", min / 1_000_000.0);

        System.out.printf("Max: %.2f ms%n", max / 1_000_000.0);

        System.out.printf("P99: %.2f ms%n", p99 / 1_000_000.0);


        // 断言:P99 延迟不得超过 2 秒

        assert p99 / 1_000_000.0 < 2000 :

            "HTTP P99 latency too high: " + p99 / 1_000_000.0 + " ms";

    }


    private double percentile(List<Long> list, double percentile) {

        List<Long> sorted = new ArrayList<>(list);

        sorted.sort(Long::compareTo);

        int index = (int) Math.ceil(percentile / 100.0 * sorted.size()) - 1;

        return sorted.get(Math.max(index, 0));

    }

}


说明:

预热:前几次测试可能受 JIT 编译、DNS 缓存等原因影响,先跑 3‑5 次不记录数据,结果更稳定。

纳秒计时:System.nanoTime() 精度高,适合测量毫秒级甚至微秒级延迟。

超时设置:避免因网络不通导致测试线程永久阻塞。

TestNG 的 invocationCount:轻松控制重复执行次数,无需手写循环。

统计数据和断言:在 @AfterClass 中计算平均值、P99,并利用assert自动决定延迟是不是达标(可集成到 CI 流水线)。


运行方式

IDE 中:右键测试类 - Run as TestNG。

命令行:通过 TestNG 的 testng.xml 批量执行,或集成到 Maven/Gradle。

自定义目的:可通过 System.getProperty("target.host", "default") 动态传入被测地址。


这两个脚本可以直接复制到项目中使用,只需修改 HOST、PORT 或 REQUEST_URL 即可开始测量。如果需要测试其他协议(如 MQTT、gRPC),只需替换中间的网络操作代码,TestNG 的测试架构完全不变。


文章标签: 软件测试 测试工具
咨询软件测试