{'fraction_non_alphanumeric': 0.024741182663625197, 'fraction_numerical': 0.006843305843130374, 'mean_word_length': 4.615106732348112, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 0, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Continuous and Resource Managed Regression Testing: An Industrial Use Case

Regression testing is an important part of quality control in both software and embedded products, where hardware is involved. It is also one of the most expensive and time consuming part of the product cycle. To improve the cost effectiveness of the development cycle and the regression testing, we use test case prioritisation and selection techniques to run more important test cases earlier in the testing process. In this paper, we consider a functional test case prioritisation with an access only to the version control of the codebase and regression history. Prioritisation is used to aid our test case selection, where we have chosen 5-25 (0.4%-2.0% of 1254) test cases to validate our method. The selection technique together with other prioritisation methods allows us to shape the current static, retest-all regression testing into a more resource managed regression testing framework. This framework will serve the agile way of working better and will allow us to allocate testing resources more wisely. This is a joint work with a large international Finnish company in an embedded industrial domain.


Introduction
In industries, regression testing is an important part of quality control and it is also used to ensure that the functionality of the system is not affected by modifications to the software. In practice, regression testing is in a constant change as there will be new test cases and old ones are modified or deprecated. Thus, widely used coverage based prioritisation methods are not optimal [6].
In agile software development with frequent release cycles, the system under test (SUT) is changing. Therefore, test selection techniques based on code change history and regression testing [1]  techniques that rely on static code analysis [9]. An in-depth analysis of different regression test selection techniques can be found in a systematic review article [3], and a survey on regression testing minimisation, selection, and prioritisation methods is given in [11].
Regression testing is usually done by retesting all test cases at regular intervals. The intervals can be daily or weekly, depending on the size of the test suites. In our use case, running all the functional test cases takes more than one week. Thus, in practice, the whole regression test set is divided into daily and weekend regression subsets. The verdict of these regressions forms the baselines of the SUT. This testing practice is both expensive and time consuming [2], because, in the end, the majority of the functional test cases have passed through the entire collected regression history. On the other hand, even daily regression testing takes a long time for developers working in an agile environment, where changes to the software are made every day. Therefore, testing done during office hours should be more than just running build verification tests.
In this paper, we propose a resource managed regression testing framework as an improvement to traditional retest-all regression testing. The framework is enabled by the algorithm proposed by Ekelund and Engström [1], which we have validated in our client's systems. In our work, we have extended the original algorithm to take into account noise and memory handling, which Ekelund and Engström mentioned as downsides of their algorithm. Based on the extensions, we propose a way to utilise the method closer to the build verification testing phase by running a selection of few functional test cases several times during a day.
Our use case study is only a part of the whole system in terms of regression history. In this particular subsystem, we have a total of 176 builds, 6720 modified files, and 1254 functional test cases in the regression history. The files can be divided into actual code and test files. However, in this study, we have not distinguished them from each other. Furthermore, we have considered only functional test cases that have their verdict flipped at least once during the regression history. In this context, a flipped test case means that the verdict of the test case has been changed from passed to fail or vice versa as defined in [1]. Out of 176 builds we have 132 builds that have predictable test cases, i.e., test cases which have been flipped at least twice in the collected regression history.
The rest of the paper is organized as follows: Section 2 outlines related works. Our extension to the test selection algorithm, proposed in [1], is described in Section 3. Metrics and results of the algorithm are given in Section 4 and 5, respectively. In Section 6, we will discuss our resource managed regression testing framework, which combines sensitivity, history-based, and similarity-based prioritisation methods to improve the regression testing flow and to better accommodate testing resources. Finally, conclusions are given in Section 7 along with future works.

Related Works
In this section, we review different prioritisation and selection techniques related to our idea of shaping the regression testing. The methods below, with the exception of clustering methods, can be applied to situation with little to no prior data. In these kinds of situations the initial cost of applying the methods is low.
In agile software development one wants to select test cases based on code changes and regression testing [1] to catch the flipping test cases and to decrease the feedback loop time. These methods alone are not enough, because they do not catch test cases that keep on failing. Therefore, we need, e.g., a history-based test case prioritisation (HBTP) technique as well, where test cases are prioritised based on their failure rate in the regression history. Basically, if a given test case has failed then it will most likely fail again. One technique [5] gives weight to test cases depending on how many builds there have been since their last failure.
On the other hand, we want to execute test cases from different parts of the system in order to a have high system level coverage. This can be achieved by computing a string distant measure [4,8] to measure how dissimilar test cases are. The dissimilarity prioritisation methods are useful, in particular, when test cases have always passed in the regression history. The selected test cases can be further prioritised with the distance measure as well, because similar test cases may test similar components of the system and thus detect the same fault.
Another history-based method is to cluster test cases based on regression history alone or on codebase changes. For example, one can build a co-change matrix of the modified files and compute a singular value decomposition to cluster the files. Then combining the clusters with the information on test cases, the method yields a list of prioritised test cases [10]. Using clustering methods, one may gain in-depth knowledge on how test cases behave, e.g., which test cases have passed and failed as a group even when that is not apparent by looking at the data alone. Downsides of clustering methods are, e.g., the required prior data and running the clustering algorithm in regular intervals to keep clusters up to date, which may become expensive in the long run.

Sensitivity Matrix and Prioritisation
The prioritisation method is based on collecting lists of the modified files from the version control and verdicts of the regression history, see Figure 1 and Figure 2.
In industrial scale, both information are usually available, but the link between a specific regression history run and the SUT may not be available. Without the knowledge of the link, we cannot determine the modified files from the version control between two builds and their regression verdicts.  For each build, we construct a sensitivity matrix B k as follows where function d is an increasing function with respect to |fc k |, fc k is a set of files that have been modified between two consecutive builds, and flipped k is the set of flipped test cases. The function d acts as a confidence on a direct correlation between files and test cases. In this particular use case, we have chosen d = |fc k |.
We define the sensitivity prioritisation matrix as follows Equation (2) is called as an exponential moving average (EMA), where the coefficient α is a weighting factor for the new observation and a decaying factor for the older observation as suggested by Kim and Porter in [7]. To prioritise the test cases in the build k, we slice the sensitivity prioritisation matrixB k−1 by taking the rows corresponding to the modified files in fc k and we call itB slice k−1 . The column sum ofB slice k−1 gives us the sensitivity of test cases over the file changes. In other words, a higher sum means that the test case is more likely to flip its verdict. To prioritise test cases one can use the maximum element of the columns as well instead of the column sum. It should be noted that (2) with d ≡ 1 and without the coefficients α and 1 − α is exactly the method proposed in [1].  The sensitivity prioritisation matrix can be used in analysing the behaviour of the system by computing the heat map. One may reveal the flakiness of a test case by looking at the heat map. Let us assume that a test case tests a certain feature of the system and that the feature is affected by a handful of files. If a test case has sensitivity towards the majority of the files and the sensitivity itself is relatively small, then the test case itself is sensitive to modifications. Some of these sensivity test cases are flaky or bad.
For another example, we assume that a HBTP method flags test cases that should be run based on their recent failure rate. We can look up the corresponding column of the test cases fromB and the rows (files) of the largest elements. These files have had the greatest impact on flipping the test case during the regression history and developers should take a closer look at them.

Metrics
To measure our techniques we use the framework and definitions given in [9]. In this sense, we measure the predictability of the test cases. A test case is defined as predictable in the build B k if it has its verdict flipped between the builds B k−1 and B k , and if it has flipped at least once in the history before. A natural choice for measurement is to compute precision and recall, which are defined as follows where the set of selected test cases is the top prioritised test cases from the sliced sensitivity prioritisation matrixB slice k−1 . The range for both, precision and recall, is [0, 1] and they can be combined into a single metric (5) F-measure = 2 precision · recall precision + recall , which can be used to compare different techniques.
Let us assume {predictable} ⊂ {selected}, in which case selecting more test cases decreases precision, while the recall remains unchanged and equals 1. Thus, the F-measure will perform worse than if one had selected fewer test cases.

Results
We compared our sensitivity prioritisation method to the method given in [1] and to selecting random test cases by computing the averages of precision, recall, and the F-measure for different sizes of selected test cases. We also counted how many times the methods returned zero results, i.e., the builds where we have {selected} ∩ {predictable} = ∅. In this study, we chose to select 5-25 (0.4%-2%) test cases, which is in line with our goal to run a small number of selected test cases several times a day.
From 132 builds, we had 41 (31%) builds with 5 or fewer predictable test cases and 76 (58%) builds with more than 25 predictable test cases. The hyperparameter α is chosen by minimising the zero results over the regression history. In our use case, the optimal value turned out to be α = 0.80 for our EMA sensitivity prioritisation method. For our randomised test case selection, we chose to select test cases randomly from all the 1254 test cases. For each selection size, we took an average of over 100 runs. Note that, a short term improvement to the randomised selection can be achieved by selecting test cases that have been flipped up to the corresponding build.
The results from our algorithm and [1] are collected into Table 1 along with the minimal, maximal, and average improvements we have achieved. The number of times the algorithm gives zero correct predictable test cases depends heavily on the number of selected test cases. Thus, the first interesting point in the results is how randomised selection yielded surprisingly a comparable result on percentage of zero cases to the algorithm given in [1]. As for the rest of the metrics, randomisation does a poor job compared to [1] and our method. On the other hand, our version of the algorithm gave on average 35% zero result on predictable test cases, which is 25% fewer zero results compared to [1]. The result is a significant improvement to the amount of selected test cases considered.
Our method shows a minor improvement in precision compared to [1], but both results seem to be capped. The reason for that may have to do with the number of builds with fewer predictable test cases than the selected test cases as well as with the definition of precision. In recall metric, see Fig. 5, our algorithm shows on an average 97% better result than [1], which is a significant improvement as well. The result in recall is carried to the F-measure, see Fig. 6, as well.

Resource Managed Regression Testing
Our vision is to move from retest-all regression testing to an on-demand resource managed regression testing framework, where we allocate testing resources based on, e.g., the time of the day, the software modification, test history, and similarity  of the test cases themselves. The framework, in general, contains the following steps: • Select test cases based on code changes using (2).
• Prioritise test cases that fail regularly based on their historical verdicts.
• Run more stable test cases based on their dissimilarity measures.
During office hours, the first two bullet points are looped to gain faster feedback on features under development. More stable test cases are run after office hours similarly to daily regression. Instead of running static regression, we prioritise test cases based on their similarity measure and select dissimilar test cases to gain a higher system level coverage.  In order to update the sensitivity prioritisation matrix using this workflow, we need to keep track of modified files for each test case since the last time it has been executed. The update to the sensitivity prioritisation matrix will occur when the test cases are run the next time and the update is done test case wise. The development of particular features is more likely to flip certain test cases, and a rapid execution of these test cases may cause bias. Each time the verdict of the test case does not flip, the update procedure will decrease the sensitivity values exponentially and will thus reduce the bias. Situations where some test cases have not been executed for a long time cause real concerns with regards to prioritising and executing more stable test cases. These concerns can be addressed with high level test strategy, which can be, e.g., round robin or minimisation of a cost function. In a round robin strategy, one can give a specific time frame in which all the stable test cases must be executed at least once.
A cost function strategy may look as follows. Let s i be the number of days since the ith test case has been last executed. Then we define a cost function as which we want to minimise. The cost function will add another constraint to the prioritisation of the stable test cases.
Lastly, by controlling test strategies, we can accommodate upcoming releases by allocating more resources to test the release candidate or any part of the system, that needs more focus and resources.

Conclusions
We have demonstrated a viable algorithm to select a small number of functional test cases with minimal prior data. These selected test cases can be run closer to the build verification testing phase to give developers faster feedbacks. Our algorithm also shows a significant improvement compared to the original algorithm given in [1]. The usage and results of our algorithm suggested that it can be combined with other prioritisation methods to shape the regression testing into a more resource managed regression testing.
However, there are improvements to be made to our algorithm and ideas. One may consider modified functions instead of modified files to have a better correlation between the functions and test cases. In cases where no prior data is available, we need a procedure to optimise the hyperparameter α as we gather data from the SUT and test runs. From other experiences with our client, we believe that α will vary a lot based on the pace of testing and the SUT itself.
In the future, we are planning to apply the sensitivity prioritisation method with other clients in different industrial domains as well as to implement the resource managed regression testing framework.