Segmented random practice - simulating online traffic

Posted by SZero on Tue, 25 Jan 2022 04:30:21 +0100

In daily performance testing, traffic playback is a very excellent way. It can not only quickly build test cases and be infinitely close to the preset scenarios, but also greatly reduce the test threshold and save time and cost with the help of many excellent playback frameworks such as goreplay. This method is very suitable for rapid performance troubleshooting, and can quickly find and solve problems with limited resources.

Another way is to rebuild the request of the test scenario. Common single interface test, multi interface hybrid test, link test, full link test and so on are based on this method. Single phase traffic playback is more flexible than the scenarios that can be realized, the control of the test process is more precise, and it is easier to integrate CI/CD and performance patrol. However, the biggest problem faced by such test cases is how to be closer to the real traffic. In terms of a single interface, it is the parameter distribution when the user requests. In terms of service chain, the user operates link bifurcation. If it is a use case for some specific scenarios, these factors need to be considered less, but in the case of full load test in the outward expansion direction and fine performance test in the inward contraction direction, it is somewhat stretched, and the complexity will soar.

In the previous article, (add me qq: 3177181324) mentioned that all interfaces are encapsulated into methods, and the function and performance test objects are transformed into the test of this method. By constructing parameters, requesting methods and processing return values, the whole process of executing test cases is implemented in Java or Groovy scripts. In this way, the complexity of test cases is reduced, the readability is increased, and the expansibility of the test framework is greatly improved.

In practice, there is a small stone that must be taken: piecewise random, which is to analyze a traffic model under a preset scenario according to the online traffic. The main information is the proportion of interface requests and interface parameters. Then send different requests according to this ratio and carry different parameters to make the pressure measurement flow closer to the real flow.

Function realization

Here I write two methods. The first half of the idea coincides as follows:

  • First, divide the map into two corresponding list s, one to save the key and the other to save the value

The second half is different:

First:

  1. Convert values into the form that item i is the sum of the previous items of the old list
  2. The random function takes an integer number from the last item of 1~values (that is, the sum of all items in the old list)
  3. The loop judges that the value falls between the values of two index subscripts, takes out the key in the keys and returns it
    /**
     * Randomly select an object according to different probabilities
     * More CPU consumption
     *
     * @param count
     * @param <F>
     * @return
     */
    public static <F> F randomCpu(Map<F, Integer> count) {
        List<F> keys = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        count.entrySet().forEach(f -> {
            keys.add(f.getKey());
            values.add(f.getValue());
        });
        int t = 0;
        for (int i = 0; i < values.size(); i++) {
            t = t + values.get(i);
            values.set(i, t);
        }
        int r = getRandomInt(values.get(values.size() - 1));
        for (int i = 1; i < values.size(); i++) {
            if (r <= values.get(i)) return keys.get(i);
        }
        return null;
    }

Second:

  1. Traverse the values, copy the key corresponding to the index value-1 times and put it back into the keys
  2. Return a random key from the new keys
    /**
     * Randomly select an object according to different probabilities
     * Consume more memory
     *
     * @param count
     * @param <F>
     * @return
     */
    public static <F> F randomMem(Map<F, Integer> count) {
        List<F> keys = new ArrayList<>();
        List<Integer> values = new ArrayList<>();
        count.entrySet().forEach(f -> {
            keys.add(f.getKey());
            values.add(f.getValue());
        });
        for (int i = 0; i < values.size(); i++) {
            for (int j = 0; j < values.get(i) - 1; j++) {
                keys.add(keys.get(i));
            }
        }
        return random(keys);
    }

test

Test script

Here, I set several strings and corresponding proportions, and then execute N times to count the results.

    public static void test0() {
        Map<String, Integer> map = new HashMap<>();
        map.put("a", 10);
        map.put("b", 20);
        map.put("c", 30);
        map.put("d", 1);
        map.put("e", 2);
        List<String> aa = new ArrayList<>();
        for (int i = 0; i < 1000000; i++) {
            String random = randomMem(map);
            aa.add(random);
        }
        CountUtil.count(aa);
    }

console output

INFO-> Current user: oker,Working directory:/Users/oker/IdeaProjects/funtester/,System coding format:UTF-8,system Mac OS X edition:10.16
INFO-> Element: a,Times: 159066
INFO-> Element: b,Times: 318615
INFO-> Element: c,Times: 474458
INFO-> Element: d,Times: 16196
INFO-> Element: e,Times: 31665

Process finished with exit code 0

Basically in line with the settings.

Project practice

Test item class

Here I virtual a function class of a project, and then there are three interfaces. Each interface has an int type parameter. The request proportion and parameter distribution proportion of the three interfaces are written in the code. The extra three list objects are for the convenience of verifying the actual results, and do not exist in the actual project.

package com.funtest.javatest;

import com.funtester.frame.SourceCode;
import com.funtester.utils.CountUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;

/**
 * FunTester Test piecewise random class
 */
public class R_FunTester extends SourceCode {

    private static final Logger logger = LogManager.getLogger(R_FunTester.class);

    public static List<Integer> ts1 = new ArrayList<>();

    public static List<Integer> ts2 = new ArrayList<>();

    public static List<Integer> ts3 = new ArrayList<>();

    /**
     * Method random value
     */
    public static Map<Integer, Integer> ms = new HashMap<Integer, Integer>() {{
        put(1, 10);
        put(2, 20);
        put(3, 40);
    }};

    /**
     * Parameter random value
     */
    public static Map<Integer, Integer> ps = new HashMap<Integer, Integer>() {{
        put(10, 10);
        put(20, 20);
        put(30, 40);
    }};

    public void test1(int a) {
        ts1.add(a);
    }

    public void test2(int a) {
        ts2.add(a);
    }

    public void test3(int a) {
        ts3.add(a);
    }

    public void online() {
        Integer m = randomMem(ms);
        switch (m) {
            case 1:
                test1(randomMem(ps));
                break;
            case 2:
                test2(randomMem(ps));
                break;
            case 3:
                test3(randomMem(ps));
                break;
            default:
                break;
        }
    }

}

Test script

Here, I count the execution times of the size method of the three lists, and verify the randomness of the method parameters through the statistics of the elements in the list.

    public static void main(String[] args) {
        R_FunTester driver = new R_FunTester();
        range(1000000).forEach(f -> driver.online());
        output(ts1.size() + TAB + ts2.size() + TAB + ts3.size());
        CountUtil.count(ts1);
        CountUtil.count(ts2);
        CountUtil.count(ts3);
        test0();
    }

console output

INFO-> Current user: oker,Working directory:/Users/oker/IdeaProjects/funtester/,System coding format:UTF-8,system Mac OS X edition:10.16
INFO-> 142168	286236	571596
INFO-> Element: 20, times: 40563
INFO-> Element: 10, times: 20468
INFO-> Element: 30, times: 81137
INFO-> Element: 20, times: 81508
INFO-> Element: 10, times: 40873
INFO-> Element: 30, times: 163855
INFO-> Element: 20, times: 163643
INFO-> Element: 10, times: 81117
INFO-> Element: 30, times: 326836

Process finished with exit code 0

It's all in line with expectations. Finish the work! Keep moving bricks!

Finally, Xiaobian sorted out some learning materials during the learning process, which can be shared with friends who are software test engineers to exchange and learn from each other, If necessary, you can join my learning exchange group 323432957 or add dingyu-002 to get the python automation test development and Java automation test development learning materials for free (including the architecture materials of multiple knowledge points such as function test, performance test, python automation, Java automation, test development, interface test, APP test, etc.)

Topics: Python Java Programming Big Data software testing