MuRS: Mutant Ranking and Suppression using Identifier Templates

Diff-based mutation testing is a mutation testing approach that only mutates lines affected by a code change under review. Google's mutation testing service integrates diff-based mutation testing into the code review process and continuously gathers developer feedback on mutants surfaced during code review. To enhance the developer experience, the mutation testing service implements a number of suppression rules, which target not-useful mutants-that is, mutants that have consistently received negative developer feedback. However, while effective, manually implementing suppression rules require significant engineering time. An automatic system to rank and suppress mutants would facilitate the maintenance of the mutation testing service. This paper proposes and evaluates MuRS, an automated approach that groups mutants by patterns in the source code under test and uses these patterns to rank and suppress future mutants based on historical developer feedback on mutants in the same group. To evaluate MuRS, we conducted an A/B testing study, comparing MuRS to the existing mutation testing service. Despite the strong baseline, which uses manually developed suppression rules, the results show a statistically significantly lower negative feedback ratio of 11.45% for MuRS versus 12.41% for the baseline. The results also show that MuRS is able to recover existing suppression rules implemented in the baseline. Finally, the results show that statement-deletion mutant groups received both the most positive and negative developer feedback, suggesting a need for additional context that can distinguish between useful and not-useful mutants in these groups. Overall, MuRS has the potential to substantially reduce the development and maintenance cost for an effective mutation testing service by automatically learning suppression rules.


INTRODUCTION
Software testing is an essential part of software development that validates and verifies the software under test.A well tested program is an indication of a reliable program [12].But how do we assess whether a program is well tested?One way is to use mutation testing [1], which systematically introduces small changes into the program and checks whether the program's tests detect the changes.Mutation testing has been widely studied [7] and sees increasing adoption in industry [2,18].
Mutation testing systematically applies mutation operators that create program variants called mutants.Each mutant differs from the original program by a small change such as a changed literal, a changed operator, or a deleted statement.Even a small number of mutation operators, when systematically applied to an entire program, can generate vast numbers of mutants, and evaluating all of them is computationally expensive [22]-prohibitively so for an industry-level code base.To solve this problem, diff-based mutation testing [18] incrementally mutates, during code review, only source code lines that are affected by the code change under review.
Google has successfully deployed diff-based mutation testing for a code base that sees more than 40 000 code commits per day to more than a billion lines of code [18].The corresponding code-review tool offers an option for authors and reviewers to provide feedback for mutants surfaced during code review (see Figure 1).If a reviewer clicks the "Please fix" button, the code-review tool auto-generates a review comment, asking the author to resolve the mutant.Additionally, both authors and reviewers can click "Thumbs up" or "Thumbs down" to give positive or negative feedback to the surfaced mutants.The negative feedback ratio is regularly measured and serves as an indicator for effective false positives [21].To lower that ratio, the existing mutation testing service implements a number of static suppression rules that prevent mutants that are likely to received negative feedback from being surfaced, and it prioritizes mutation operators based on the historical effectiveness of the mutants they generate.Over the years, the manually developed suppression and prioritization rules have reduced the negative feedback ratio from over 80% to well below 15% [18].However, manually implementing rules is labor-intensive, the rules require regular maintenance, and prioritization based on mutation operators may be too coarsegrained.
This paper presents MuRS (Mutant Ranking & Suppression) that aims to tackle these problems and further reduce the negative feedback ratio.MuRS uses identifier templates-an abstraction over the unified diff between the mutant and the original program.Specifically, MuRS takes, for a given mutant, the unified diff and replaces (1) literals with their type names (e.g., int or String) and (2) identifiers with IDENTIFIER.MuRS optionally preserves the most common literals and identifiers, using a configurable vocabulary size.Similarly, the number of context lines in the unified diff considered when building identifier templates is another hyper-parameter.MuRS then groups all historical mutants and aggregates their developer feedback by identifier template.The aggregated feedback for each identifier template is then used to rank and suppress newly generated mutants.The intuition behind this approach is that mutants whose identifier templates have largely received positive feedback should be ranked highly, whereas mutants whose identifier templates have received negative feedback should be ranked lower or suppressed altogether.MuRS scales very well to a large code base: our analyses computed millions of identifier templates on a machine with commodity hardware and only 16 GB of RAM.
We conducted an A/B testing study to evaluate MuRS' performance, randomly assigning 50% of code reviews at Google during the evaluation period to the experiment group (MuRS) and all other code reviews to a control group (existing mutation testing service).During the evaluation period, a total of 666 143 mutants surfaced across the five languages supported by MuRS (Python, Java, C++, Go, and TypeScript).The key results are as follows: • The overall negative feedback ratio for the experiment group is 11.45%, which is statistically significantly lower than the negative feedback ratio of 12.41% for the control group.• The correlation coefficient (Kendall's Tau-b) between MuRS's ranking score and the ranked mutants' perceived usefulness (developer feedback) is 0.2615, which indicates a moderate correlation.Further, the top 50% of ranked mutants only contain 16.39% of mutants with negative feedback.This suggests that MuRS's ranking of mutants effectively decreases the likelihood of surfacing not-useful mutants.• Choosing a suppression threshold involves a trade-off: when applied to all surfaced mutants in the control group, MuRS would have suppressed 49% of mutants that received negative feedback, and it would have suppressed 12% of mutants that received positive feedback.The trade-off between correctly suppressing not-useful mutants, which waste engineers' time, and incorrectly suppressing useful mutants, which likely lead to additional tests, is a trade-off that one has to consider when deploying MuRS.• For all supported languages, the identifier templates that receive the most controversial feedback (i.e., the most positive and the most negative feedback) are all statement removal mutants.Prior research has found that statement removal mutants are coupled with real faults more often than other types of mutants [9].This finding suggests that although statement removal mutants are useful in general, further investigation is necessary to identify the specific subset of statement removal mutants that are not useful.
We additionally performed a retrospective analysis, investigating what identifier templates MuRS would have learned and scored at different points in the past six years.A manual analysis of the most common identifier templates that consistently received negative feedback showed that MuRS is able to recover suppression rules implemented in the existing mutation testing service.

TERMINOLOGY
This section defines the terminology used throughout the paper: • Changelist: A set of changes made to the code base, which are submitted for review (similar to a merge request).• Snapshot: A specific point in time, capturing the state of a changelist as it evolves during the code review process.Each changelist has one or more snapshots.• Generated mutants: All mutants generated by the mutation testing service.• Surviving mutants: Mutants that are not detected by any of the existing tests-a subset of all generated mutants.• Surfaced mutants: Mutants displayed in the code review tool-a subset of surviving mutants.The number of surfaced mutants is limited to avoid overwhelming developers.• Positive feedback: A surfaced mutant receives positive feedback when the "Please Fix" or "Thumbs Up" button is clicked in Figure 1; we deem such mutants useful.• Negative feedback: A surfaced mutant receives negative feedback when the "Thumbs Down" button is clicked in Figure 1; we deem such mutants not useful.

MUTATION TESTING AT GOOGLE
Integrating mutation testing into a large code base, like Google's, poses significant challenges related to scalability and workflow integration.Generating and testing all possible mutants is computationally infeasible, and reporting all surviving mutants to developers would be overwhelming.To overcome these challenges, Google's mutation testing service implements diff-based mutation testing: it only generates mutants for the lines of code that have been changed in a given changelist.It also implements arid node detection and probabilistic mutation-operator selection to surface mutants that developers mostly consider useful in practice [18].In Figure 2, "Mutation Testing Service" illustrates the entire process, from submitting a changelist for code review to surfacing mutants as findings in the code review tool.For a more comprehensive view of mutation testing at Google, we refer the reader to [18].This section focuses on a higher-level description and only details the steps that are relevant to our approach: (1) A developer submits a changelist for code review.
(2) The mutation testing service identifies all changed lines that are covered by at least one test.
(3) The mutation testing service builds the abstract syntax tree of each affected file and marks arid nodes that are not eligible for mutation.Mutating arid nodes produces nonactionable mutants, such as String mutations in logging statements, for which developers justifiably would not write tests.(4) The mutation testing service uses probabilistic mutationoperator selection that prioritizes mutation operators based on their historical performance until at most one mutant is generated for each affected line.The historical performance is computed for each mutation operator and programming language, which is relatively coarse grained.(5) The mutation testing service identifies surviving mutants by executing the existing tests against each generated mutant.(6) The mutation testing service surfaces a random sample of surviving mutants in the code review tool, based on per file and per changelist thresholds.
MuRS aims to address two limitations of the current mutation testing service, related to the implementation of arid nodes (step 3) and the probabilistic mutation-operator selection (step 4).While arid-node detection is effective, it currently requires human effort to identify and implement a static rule for suppressing a certain group of mutants.This implementation is specific to each programming language and must be manually maintained as the code base evolves.As for probabilistic mutation-operator selection, the problem is that the selection is coarse-grained and context-agnostic.Currently, the mutation testing service implements five mutation operators: AOR (Arithmetic operator replacement), LCR (Logical connector replacement), ROR (Relational operator replacement), UOI (Unary operator insertion), and SBR (Statement block removal).However each mutation operator corresponds to a number of possible mutations, such as replacing addition with subtraction, division, or multiplication.In contrast, MuRS considers the actual mutation and the code before and after as additional context.

MURS: MUTANT RANKING & SUPPRESSION
A key goal of MuRS is to reduce the negative feedback ratio of surfaced mutants.The negative feedback ratio is defined as the number of surfaced mutants with negative feedback divided by the total number of surfaced mutants with positive or negative feedback.MuRS implements a template-based approach for five languages (C++, Java, Go, Python and TypeScript) that ranks and suppresses mutants based on historical developer feedback.It consist of two phases, as shown in the upper part of Figure 2: (1) Template Generation: During this phase, MuRS generates identifier templates from all past mutants, associating each identifier template with a list of metrics such as number and type of received feedback, and number of times it was generated and killed.This phase is intended to run periodically to collect identifier templates with all statistics until that point of time and store them in a database.The time interval for template re-computation can be chosen based on the needs and resource constraints of the users, balancing the importance of the data freshness with the acceptable resource consumption.In our case, this phase run every two months.(2) Ranking & Suppression: During this phase, MuRS uses the latest identifier templates stored in a database to rank and suppress mutants in production.Specifically, it uses the list of metrics to represent the past performance associated with each identifier template to rank and suppress surviving mutants that match an identifier template.There are different ways to generate the identifier templates and to rank and suppress mutants.Sections 4.1 and 4.2 discuss these configuration options in detail, and section 4.3 describes the configuration that we chose based on a preliminary evaluation.All of MuRS' identifier templates can be stored in a lookup table in memory, using less than 16GB of RAM.

Template Generation
Template Generation consists of three stages, as shown in Figure 2: (I) Data Collection: Gather all previously generated mutants along with their associated attributes (see Table 1).

The changelist ID Filename
The name of the mutated file Diff The unified diff with all surrounding lines as context between the original file and the mutant PosFeedList A list of type boolean (one per snapshot) indicating whether a mutant received a positive feedback at that snapshot NegFeedList A list of type boolean (one per snapshot) indicating whether a mutant received a negative feedback at that snapshot KilledList A list of type boolean (one per snapshot) indicating whether a mutant was killed at that snapshot  We define an abstraction over the unified diff between the mutated and the original code at the line level, which we refer to as an identifier template.The abstraction removes comments from the code before considering the diff, including context lines (where applicable).We chose this abstraction because it is relatively fast to compute and allows for quick inference, even in the presence of millions of mutants.To generate identifier templates, we can control the template's specificity using different abstraction levels and various parameters, which we subsequently explain using the mutant in Listing 1 as a running example.
Abstraction levels that we explored are: • Original code template: Use each changed line as is.
− return x % + return x % All identifiers with their corresponding counters are then stored in a database, shown in (IV) of Template Generation in Figure 2.These identifier templates are then used to populate a lookup table and efficiently rank and suppress mutants in the Ranking & Suppression phase.

Ranking & Suppression
Ranking & Suppression consumes the pre-computed identifier templates and their associated counters, as derived from the Template Generation phase.The intuition is that we can use these counters to rank and suppress mutants.For example, identifier templates with high PU counts may be considered more useful than those with low PU counts, hence should be ranked higher.While identifier templates with high PNU counts may be considered highly not useful and hence, can be suppressed.Ranking and suppression are two independent procedures, as the former only gives a relative ordering between mutants, so the highest ranked mutants may still not be worth surfacing to the developer.The following sections describe how we rank and suppress mutants.We explored two definitions for the developer-feedback score: • Usefulness score: This score is the ratio of PU over PU+PNU.
It is calculated as Compared to Usefulness score, this score accounts for noise when  +  is low, i.e. when there is not enough feedback from developers.We also explored two definitions for killed score: • Kill-ratio score: It is defined as   , representing the percentage of times that this type of mutant is killed.
• Kill-counter score: It is a tuple with (AK, EK, MK, NK) counters.The ordering between the counters is based on their correlation with the developer feedback.Since there are 2 developer-feedback scores and 2 killed scores, there are 4 different combinations of usefulness scores.

Suppression.
MuRS aims to suppress mutants that are likely to receive negative feedback.When designing the suppress function, we chose to implement the following two desired properties: (1) If an identifier template is not in the database (i.e. the mutant has not been encountered before), MuRS would not suppress it.This allows for gathering feedback for new identifier templates.(2) Only the PU and PNU counters are considered for suppressing mutants, as it is crucial not to over-suppress mutants.Suppressing an identifier template means that all mutants with the corresponding identifier template will not be surfaced, therefore we would like to be careful and only suppress mutants based on labels derived from the developer feedback, i.e.PU and PNU.We explored the following three suppression functions: • No suppression: Do not suppress any mutants.This is added to experiment if a suppression function is needed at all.• Average threshold: Suppress mutants whose Usefulness score is lower than the average Usefulness score across all identifier templates.• Probabilistic: Use the p-value of the z-test to suppress the mutants with a calculated probability, as the Usefulness score follows a normal distribution.For example if the z-score is −1, the corresponding p-value is 0.1587, then we have a 1 − 0.1587 = 0.8413 chance of suppressing this mutant.This suppress function is only applied when the Usefulness score is lower than the average Usefulness score across all identifier templates.At the end of the Ranking & Suppression phase, MuRS has ranked all generated mutants and suppressed mutants that are likely to receive negative feedback.At this point, the mutation testing service continues to surfacing the selected mutants as findings in the code review tool.
We conducted a preliminary evaluation of all possible hyperparameter combinations using historical mutants.Specifically, we used the mutants generated before July 2022 to generate identifier templates and computed the hypothetical negative feedback ratio for each hyperparameter setting on the mutants generated in July 2022.We then selected the setting with the lowest ratio.The example in Table 2 illustrates how the hypothetical negative feedback ratio is calculated.On the left we have mutants with their labels, note that we have the label because they have already been generated and shown to the developers.On the right is an example of how one combination might rank and suppress the mutants, where mutant C is suppressed.In this example, the original negative feedback ratio is 2 4 = 0.5, the hypothetical negative feedback ratio for MuRS is 1  3 ≈ 0.33.The best hyperparameters combination is the one that achieves the lowest hypothetical negative feedback ratio.
The hyperparameter tuning identified the following setting as the best: (1) Indexed type template, (2) vocabulary size = 0, (3) context size = 0 (4) Bayes usefulness score with kill-counter score, and (5) Probabilistic suppression function.We consistently used this hyperparameter setting to answer our research questions in section 5.

EVALUATION METHODOLOGY
To evaluate MuRS, we compared the current mutation testing service, which randomly selects  mutants and surfaces them as code findings in the code-review tool, to an enhanced variant, which surfaces the top- mutants after ranking and suppressing mutants with MuRS (see Figure 2).Note that both variants use existing optimizations, such as arid-node suppression and probabilistic mutationoperator selection [18].Moreover, the mutation testing service limits the number of surfaced mutants during code review to avoid overwhelming developers: it surfaces at most three mutants per file and at most ten mutants per changelist.We kept these thresholds constant for both variants.
We followed a standard A/B testing methodology for changelists subject to mutation by the mutation testing service: each changelist was randomly assigned to the experiment group with probability  = 0.5; all other changelists formed the control group.Regardless of group, each mutant that surfaced in the code review tool was subject to developer feedback (i.e., positive feedback, negative feedback, or no feedback at all).The A/B testing allowed us to answer the following two research questions: RQ1 Does MuRS decrease the overall negative feedback rate?
RQ2 Is MuRS's ranking associated with developer feedback?
The existing mutation testing service has been deployed for over seven years, with domain experts manually developing arid-node heuristics to suppress mutants that will likely receive negative feedback [18].The majority of these heuristics were implemented early during development and deployment, others were added over time in response to user feedback.Considering historical mutant data, we additionally answered the following research question: RQ3 Do MuRS's templates agree with suppression rules developed by domain experts?
At a high level: RQ1 uses an extrinsic evaluation and determines whether MuRS can improve mutant suppression over a manually tuned baseline; RQ2 uses an intrinsic evaluation and determines the degree to which MuRS's ranking of mutants is correlated with their perceived usefulness.RQ3 uses case studies and determines whether MuRS's templates and their statistics can be linked to manually developed suppression rules.

RQ1: Does MuRS decrease the overall negative feedback rate?
During the A/B testing evaluation period1 , 666 143 mutants surfaced across 84 827 changelists.For the control group, 365 542 mutants surfaced for 45 210 changelists.For the experiment group, 601 mutants surfaced for 39 618 changelists.For each group we computed the overall negative feedback ratio and compared the results.Additionally, we conducted a two-sample hypothesis test.Specifically, we used the chi-square test of independence [16], testing the null hypothesis that developer feedback is independent of group association (i.e., experiment vs. control group).We set the significance threshold to 0.05.

RQ2: Is MuRS's ranking associated with developer feedback?
The mutation testing service may generated more surviving mutants than can be surfaced in the code-review tool.Thus, it is important to rank mutants that are likely to receive positive feedback higher.To determine to what extent MuRS succeeds in properly ranking mutants, we computed the rank of all surfaced mutants in the control group and correlated that rank with the mutants' received feedback.Specifically, we computed Kendall's Tau-b (accounting for expected ties in the dichotomous feedback variable) between MuRS's ranking score and developer feedback.We again set the significance threshold to 0.05.We repeated the same analysis for all mutants in the experiment group.Additionally, we computed the ratios of mutants that already received positive or negative feedback that would have been suppressed in the control group, investigating the trade-off between suppressing not-useful mutants while retaining useful ones.We wished to better understand whether MuRS's identifier templates are linked to arid nodes, for which the existing mutation testing service suppresses all mutants.However, not-useful mutants can no longer be observed once a suppression rule is implemented.Therefore, we resorted to historical mutant data to determine whether MuRS, if applied to not-useful mutants prior to suppression, would have identified said mutants.Specifically, We compiled a data set with all surfaced mutants generated since 2017.
For each mutant, we computed the corresponding identifier template and aggregated template data per month.We then performed a case study on a sample of templates that produced many mutants, consistently rated as not useful.

RQ1: Does MuRS decrease the overall negative feedback rate?
During the A/B testing evaluation period, a total of 23 766 mutants received developer feedback.Table 3 shows the distribution among the two groups and positive vs. negative feedback.The negative feedback ratio for mutants in the experiment group is 11.45% (1253 out of 10 941 mutants).In contrast, the negative feedback ratio for mutants in the control group is 12.41% (1592 out of 12 825 mutants).The Chi-squared test of independence for the two variables in Table 3 yields a p-value of 0.0242.Since this value is lower than our predefined significance threshold of 0.05, we can reject the null hypothesis.This means that the observed differences in feedback are not independent of the group-that is, the lower negative feedback ratio of 11.45% in the experiment group is statistically significant.

RQ2: Is MuRS's ranking associated with developer feedback?
As shown in Table 3, the control group had 12 825 mutants with feedback, and the experiment group had 10 941.For the control group, the rank correlation coefficient (Kendall Tau-b) between MuRS's usefulness score and the developer feedback is 0.2658 ( < 0.0001).For the experiment group the correlation coefficient is 0.2615 ( < 0.0001).These coefficients suggest a weak to moderate correlation and there is no significant difference between the control and experiment groups.
Figure 3 displays the cumulative number of mutants with negative feedback among the top x% ranked mutants in the control group.The top 50% of the ranked mutants only contains 16.39% (261 out of 1592) of all mutants that received negative feedback.The negative feedback ratio for the top x% mutants is shown in Figure 4.It reveals that the negative feedback ratio remains around 4% for the top half of the ranked mutants, but it steadily increases to 12% when including all mutants.Both figures suggest that higher ranked mutants are less likely to receive negative feedback.
Figure 4 shows a trade-off: while aggressive mutant suppression (e.g., the bottom 40% of ranked mutants) might lower the negative feedback ratio to about 6%, it would likely suppress useful mutants as well.We determined how many mutants with positive or negative feedback would have been suppressed in the control group.Since suppression is probabilistic, we computed the expected values: • 772.4159 out of 1592 mutants with negative feedback (49%) would have been suppressed.Since these mutants indeed received negative feedback, they are correctly suppressed.• 1338.1659out of 11 233 mutants with positive feedback (12%) would have been suppressed.Since these mutants received positive feedback, they are incorrectly suppressed.

RQ3: Do MuRS's templates agree with suppression rules developed by domain experts?
Figure 5 shows the results of applying MuRS retroactively to all mutants surfaced since mid 2017 and filtering templates that (1) correspond to at least 50 surfaced mutants per month on average and (2) consistently received negative feedback.Each row in this plot corresponds to a selected template and each dot corresponds to a month during which a template was observable.A line connects multiple months of the same template, indicating the overall time period a template was observable.We manually sampled ten templates for manual inspection across multiple languages and years.For most of them, we were able to identify a corresponding suppression rule in the existing mutation testing service.Below are two concrete examples.
The following GO template corresponds to a common errorhandling pattern: This template corresponds to statement removal mutants that delete if err != nil { return err }.Since these statements are ubiquitous but the mutants are not generally worth testing, the negative developer feedback provided a very strong signal for suppression.
The following Java template refers to mutants in annotations: −@JAVA_IDENTIFIER_0(JAVA_IDENTIFIER_1 = JAVA_IDENTIFIER_2.JAVA_IDENTIFIER_3, JAVA_IDENTIFIER_4 = true) +@JAVA_IDENTIFIER_0(JAVA_IDENTIFIER_1 = JAVA_IDENTIFIER_2. JAVA_IDENTIFIER_3, JAVA_IDENTIFIER_4 = !(true)) This template corresponds to mutants that change a boolean attribute of an annotation from true to !(true).Annotations in Java provide metadata or compiler directives, or are used for meta programming.Common examples include the @Override annotation, which indicates that a subclass method is overriding a parent class method, the @Deprecated annotation, which indicates that a method is deprecated, or the @Test annotation for JUnit tests.However, annotations are rarely, if ever, subject to (unit) testing.The clear negative sentiment of developers towards these mutants suggests that suppressing them is arguably the correct choice.Additionally, we also inspected templates with positive and mixed feedback.Below are two concrete examples.
Among the C++ templates, the mutants corresponding to the following template are considered useful by many developers: This template captures mutants that replace a relational operator in the condition of an else if statement with the constant value true.
The following Python template has both the highest total PU and PNU count: This template captures mutants that remove a function call with a single argument.Just et al. found that statement deletion mutants are often associated with real faults, more so than other types of mutants [9].Therefore, it is not surprising that many of these mutants are considered useful.At the same time, there are likely many function calls that match this pattern that are not worth testing.One very common class of function call that matches this pattern are telemetry statements, e.g.log(id).Developers typically do not consider these to be directly impacting user experience and are less interested in testing them specifically.Templates like this are the most controversial: By computing the controversy score for all identifier templates, we found that the most controversial templates for Python, Java, C++, Go, and TypeScript are all statement removal mutants.One of the reasons is that statement removal mutants represent 68% of all mutants [18], which makes them also more likely to receive more feedback.This observation calls for more research to understand the differences between useful statement removal mutants that are associated with real bugs and not-useful statement removal mutants.
For example, future research can inform additional context that should be considered to distinguish these.

Discussion
It is important to put the results in perspective when assessing their practical significance.First, we are comparing MuRS against a strong baseline, which employs many suppression heuristics that have lowered the negative feedback ratio from over 80%, during initial development, to well below 15% now.Second, the negative feedback ratio is a metric derived from developer feedback, which is subjective.A mutant can receive negative feedback for many reasons-some mutants represent infeasible test goals, others are simply not worth satisfying [15,19].While many not-useful mutants consistently receive negative feedback, others receive no or even inconclusive feedback.For example, the very same mutant can receive different feedback from the author and reviewers during a code review.As a result, the lower bound for the negative feedback ratio is very likely greater than zero.Since our baseline is already approaching a ratio in the single digits, it is important to keep in mind that the true lower bound, and thus the best possible result, could be anywhere between 0% and 10%.
MuRS suppresses about 50% mutants with negative feedback, at the cost of suppressing about 12% mutants with positive feedback.One of the reasons why MuRS does not suppress more not-useful mutants is that the corresponding identifier templates have not yet received enough negative feedback, and as a result the suppression function conservatively retains them.Indeed, we have observed that about 80% of all templates correspond to at most ten surfaced mutants-that is, the templates are too specific.At the same time, the current templates do not consider enough context to retain all useful mutants and to disambiguate mutants with mixed feedback-that is, the templates are too generic.We leave a deeper investigation and possible refinements for future work.
Suppressing mutants can also be achieved through the implementation of static rules that prevent mutants from being generated in the first place, e.g., mutations of logging statements.The existing mutation testing service already implements this using arid nodes, which are AST nodes that are identified through pattern matching and that are never mutated.While effective, MuRS offers several advantages over the arid node approach.It automatically creates an identifier template that is used to suppress a particular type of mutant, eliminating the need for manual implementation of static rules.In fact, we have discovered multiple identifier templates that correspond to our existing static rules, demonstrating that MuRS is able to recover these rules.Overall, the combination of using arid-node heuristics and MuRS provides an effective strategy for suppressing mutants in a mutation testing service.

RELATED WORK
The closest related work in terms of industry-scale mutation testing is Beller et al.'s study of mutation testing at Facebook.They also focused on diff-based mutation testing, but a key difference is that their approach uses semi-automatic learning on common Java bug patterns to create a small number of mutation operators that yield mostly useful mutants by design.In contrast, our approach uses a predefined set of mutation operators and suppresses not-useful mutants.The two approaches could potentially be combined for greater effect.

Mutant Selection and Prioritization
A number of studies have shown that a small percentage of mutants are sufficient, that there is substantial redundancy among generated mutants, and that many generated mutants are not useful [5,13,17].We refer the reader to the literature review by Pizzoleto et al. for more comprehensive related work, especially PG-1 (Reducing the number of mutants) and PG-5 (Avoiding the creation of certain mutants) mentioned in the paper for the closest related work regarding mutation selection or prioritization.
Gopinath et al. compared multiple strategies for reducing the number of mutants against random sampling [6].They found that none of the strategies yield an effective advantage larger than 5%, when compared with random sampling.Given the result, they warn against adopting mutant reduction techniques without adequate reason.In an industrial context, however, a 1% reduction in mutants with negative feedback could be worthwhile (it safes valuable developer time) as long as mutants with positive feedback are retained.
Brown et al. introduced an approach that extracts mutation operators from the revision history of software projects [3].The approach is based on the observation that if a commit corrects a bug, then its reversal is potentially introducing a bug, making it a viable mutation operator.Using this approach, they mined mutation operators from the revision history of the top-50 most forked C projects on GitHub.Their findings showed that mutants generated from the mined mutation operators were just as challenging to kill as mutants generated using traditional mutation operators.However, the mined mutation operators exhibited greater diversity in the types of changes than traditional mutation operators.

Mutant Usefulness
Just et al. studied the degree to which program context, defined over the abstract syntax tree, is correlated with a mutant's expected usefulness.In this work, usefulness was termed mutant utility and measured along three dimensions: equivalence, triviality, and dominance.The results showed that mutant utility is context-dependent: the same mutation may lead to a high-utility mutant in one context but not not necessarily in another.
Kaufman et al. proposed test completeness advancement probability (TCAP) as a measure to define how useful a mutant is [11].TCAP is a probability that if a mutant is presented as a test goal, it will elicit a test to improve the test completeness.Evaluated on 9 projects from the Defects4J benchmark [8], they concluded that TCAP can be predicted from program context and that TCAP-based mutant prioritization improves test completeness faster than the previous state-of-the-art, which is random prioritization.
MuRS and its evaluation differ from prior work in two key aspects.First, MuRS uses an abstraction over the unified diff, which encodes both the mutation and the surrounding context.Second, mutant usefulness is derived from developer feedback as opposed to test or mutant characteristics.

Diff-based Mutation Testing
Cachia et al. focused on industrial adoption of mutation testing, and suggested incremental mutation testing that limits the scope of mutation testing to the changed code [4].In their evaluation, they found that incremental mutation testing reduced the number of generated mutants and the execution time of mutation testing.Ma et al. studied the relationship between commit-aware mutation testing and traditional mutation testing [14].They found that the commit-aware mutation score and the traditional mutation score are only weakly correlated, and that mutants from traditional mutation testing have a 30% lower chance of revealing faults introduced by the commit.

CONCLUSIONS
This paper resents MuRS, an approach designed to enhance the user experience of mutation testing by reducing the negative feedback ratio of mutants surfaced during code review.MuRS ranks an suppresses newly generated mutants based on identifier templates that group similar mutants and aggregate historical developer feedback for said mutants.
Based on an A/B testing study, we found that the negative feedback ratio for MuRS (11.45%) is statically significantly lower, compared to manually tuned baseline.The results also show that mutants higher ranked by MuRS have a lower probability of receiving negative feedback.Additionally, we observe that MuRS would have suppressed about 50% of not-useful mutants but also 12% of useful mutants in the control group, highlighting a trade-off.Finally, we identified statement deletion mutants as the type of mutants whose identifier templates received both a high number of positive and a high number of negative feedback.Going forward, we aim to investigate what distinguishes useful statement deletion mutants from not-useful ones despite their similarities w.r.t.identifier templates.Furthermore, we would like to understand whether MuRS should apply different abstractions for the mutated lines vs. context lines.
One important result of MuRS in an industrial setting is its lower cost of development and maintenance, compared to manually implementing suppression rules.Our results provide evidence that MuRS produces identifier templates that correspond to static suppression rules implemented in the past, but future work should further evaluate to what extent MuRS can fully replace suppression rules or to what extent the two approaches are complementary.

Figure 1 :
Figure 1: A mutant surfaced in the code review tool.A reviewer can click "Please fix", indicating that the author should resolve the mutant.Both author and reviewers can click "Thumbs up" and "Thumbs down" to give feedback.

Figure 2 :
Figure 2: Mutation Testing Service (bottom) shows the end-to-end workflow from submitting a changelist for code review to surfacing mutants as code findings in the code review tool: (1) A changelist is submitted for review.Red and green dots indicate that a line is (not) covered by existing tests.A green, red, or black line indicates that it is added, removed, or unchanged, respectively.(2) Lines that are both changed and covered are identified.(3) Arid nodes, which are not eligible for mutation, are marked with 'A'.(4) Mutation operators are applied in order to generate at most one mutant per changed line.(5) Test cases are run and surviving mutants are identified.(6) A random subset of surviving mutants are surfaced as code findings.MuRS, is added between (5) and (6): it ranks and suppresses surviving mutants as opposed to randomly sampling from all surviving mutants.MuRS consists of two phases, Template Generation and Ranking & Suppression.Template Generation consists of three stages: (I) Historical mutants and their feedback are collected.(II) Identifier templates are generated for each mutant.(III) Mutants are grouped by identifier template and feedback scores are aggregated.(IV) The identifier templates are stored in a database.Ranking & Suppression consists of two stages: (V) The aggregated feedback score is retrieved from the database for each surviving mutant's identifier template.(VI) Surviving mutants are ranked and suppressed based on their feedback score.

4. 2 . 1
Ranking.MuRS ranks identifier templates and matching mutants based on a usefulness score, which comprises two distinct scores: (1) the developer-feedback score, derived from the Perceived feedback label, and (2) the killed score, derived from the Killed status label.MuRS ranks the identifier templates based on the developerfeedback score, and breaks ties based on the killed score.

Figure 3 :
Figure 3: Accumulated number of not-useful mutants among the top x % ranked mutants in the control group.

Figure 4 :
Figure 4: Negative feedback rate for top x % ranked mutants in the control group.

Figure 5 :
Figure 5: Sampled not-useful templates for which at least 50 live mutants surfaced per month on average.

Table 1 :
The attributes collected for each mutant in the Data Collection stage.The KilledList is a sequence of False, followed by a sequence of True, which means that a mutant survived up to a certain point in the code review process and was consistently killed afterwards.• Mixed killed: None of the above conditions are met.This can happen when the entries in KilledList alternate between False and True.
(II) Template Creation: Create identifier templates for all previously generated mutants.(III) Template Aggregation: Aggregate mutants with the same identifier templates.4.1.1Data Collection.In this stage, MuRS gathers mutants and their attributes from a database of all previously generated mutants.MuRS then collects various attributes (Table 1) for each mutant and assigns two kinds of labels to each mutant, based on said attributes: Perceived feedback and Killed status.Perceived feedback represents a mutant's usefulness as perceived by developers.It is derived from PosFeedList and NegFeedList: • Perceived useful: PosFeedList contains at least one True and NegFeedList is all False.• Perceived not-useful: PosFeedList is all False and NegFeedList contains at least one True.• Mixed feedback: Both PosFeedList and NegFeedList contain at least one True.• No feedback: Both PosFeedList and NegFeedList only contain False.Killed status is a label representing whether a mutant was killed (or not) throughout the code review.It is derived from KilledList: • Always killed: All entries in KilledList are True.• Never killed: All entries in KilledList are False.• Eventually killed: At the end of this stage, each mutant is assigned an appropriate Perceived feedback and Killed status label.4.1.2Template Creation.In this stage, MuRS generates identifier templates for all labeled mutants based on the Diff attribute.
of the vocabulary, mutants in the context of the identifier numpy can be ranked and suppressed differently than similar mutants in other contexts.The following identifier template corresponds to an Indexed typed template with a vocabulary containing x, but not containing 2 and 0. Template Aggregation.Similar mutants will generate the same identifier template depending on the abstraction level and identifier template parameters.In this stage, MuRS aggregates all labeled identifier template instances-counting the number of Perceived feedback and Killed status labels.PU, PNU, MF and NF counts perceived useful, perceived not-useful, mixed feedback and no feedback of the Perceived feedback label.AK, NK, EK and MK counts always killed, never killed, eventually killed and mixed killed of the Killed status label.
• Typed template: Replace all literals with their corresponding type name, and identifiers with IDENTIFIER.For instance, integer literals are replaced with INT.However, all keywords such as while, for and return are kept.−returnIDENTIFIER% + return IDENTIFIER %• Indexed typed template: Similar to Typed template, but index each type name.This means that each name is followed by a number, in order of appearance, to differentiate between identifiers of the same type.For example, the two integers, 2 and 0, are replaced with INT_0 and INT_1, respectively.•Vocabulary size: The number of the most common variable names and literals to keep without replacement.Larger vocabulary sizes lead to more specificity.For example, if numpy is part +  .• Bayes usefulness score: It uses the Usefulness score and the average Usefulness score for all identifier templates to calculate a bayesian weighted average.Let  be the average number of  +  per identifier template, and  be the average Usefulness score.The weight  is defined as  +   +  + .Using this weight, the Bayes usefulness score is defined as  * Usefulness score+ (1−) * .

Table 3 :
Mutants with feedback during A/B testing.