Weapon regeX mutates regular expressions for use in mutation testing. It has been designed from the ground up to support Stryker Mutator. Weapon regeX is available for both JavaScript and Scala and is used in Stryker4s and StrykerJS flavors of Stryker. The JavaScript version of the library is generated from Scala using Scala.js. The generated mutant regular expressions cover human errors, such as edge cases and typos. A list of provided mutators is given below. For an introduction to mutation testing, see Stryker's website.
The current supported versions for Scala are: 2.12
, 2.13
and 3
.
In case you want to incorporate Weapon-regeX into your project.
Add Weapon regeX to
your build.sbt
:
libraryDependencies += "io.stryker-mutator" %% "weapon-regex" % weaponRegexVersion
Mutate!
import weaponregex.WeaponRegeX
WeaponRegeX.mutate("^abc(d+|[xyz])$") match {
case Right(mutants) => mutants map (_.pattern)
case Left(e) => throw new RuntimeException(e)
}
// res0: Seq[String] = List(
// "abc(d+|[xyz])$",
// "^abc(d+|[xyz])",
// "\\Aabc(d+|[xyz])$",
// "^abc(?:d+|[xyz])$",
// "^abc(d|[xyz])$",
// "^abc(d{0,}|[xyz])$",
// "^abc(d{2,}|[xyz])$",
// "^abc(d{1}|[xyz])$",
// "^abc(d+?|[xyz])$",
// "^abc(d+|[^xyz])$",
// "^abc(d+|[yz])$",
// "^abc(d+|[xz])$",
// "^abc(d+|[xy])$",
// "^abc(d+|[\\w\\W])$",
// "^abc(d+|[xyz])\\z"
// )
Install Weapon regeX with npm
.
npm install weapon-regex
Mutate!
import wrx from 'weapon-regex';
let mutants = wrx.mutate('^abc(d+|[xyz])$');
mutants.forEach((mutant) => {
console.log(mutant.pattern);
});
Note: as of 1.0.0 weapon-regex uses ES Modules.
The mutate
function has the following signature:
import weaponregex.model.mutation._
import weaponregex.mutator.BuiltinMutators
import weaponregex.parser.{ParserFlavor, ParserFlavorJVM}
def mutate(
pattern : String,
mutators : Seq[TokenMutator] = BuiltinMutators.all,
mutationLevels: Seq[Int] = null,
flavor : ParserFlavor = ParserFlavorJVM
): Either[String, Seq[Mutant]] = ???
With the mutators
argument you can give a select list of mutators that should be used in
the mutation process. If omitted, all built-in mutators will be used. This list will be filtered
depending on the mutationLevels
argument.
A list of mutationLevels
can also be passed to the function. The mutators will be filtered
based on the levels in the list. If omitted, no filtering takes place.
The flavor
argument allows setting the parser flavor that will be used to parse the pattern.
Currently, we support a ParserFlavorJVM
and ParserFlavorJS
. By default in Scala the JVM flavor is used.
This function will return a Right
with Seq[Mutant]
if it can be parsed, or a Left
with the error message
otherwise.
The mutate
function can be called with regular expression flags and an options object to control which mutators and
which parser flavor should be used in the mutation process:
import wrx from 'weapon-regex';
let mutants = wrx.mutate('^abc(d+|[xyz])$', 'u', {
mutators: Array.from(wrx.mutators.values()),
mutationLevels: [1, 2, 3],
flavor: wrx.ParserFlavorJS,
});
Both options can be omitted, and have the same functionality as the options described in the Scala
API section. By default in JS the JS parser flavor is used. You can get a map of mutators from the mutators
attribute
of the library. It is
a Map<string, Mutator>
from string (mutator name) to a mutator object.
This function will return a JavaScript Array of Mutant
if it can be parsed, or throw an exception otherwise.
All the supported mutators and at which mutation level they appear are shown in the table below.
Name | 1 | 2 | 3 |
---|---|---|---|
BOLRemoval | ✅ | ✅ | ✅ |
EOLRemoval | ✅ | ✅ | ✅ |
BOL2BOI | ✅ | ✅ | |
EOL2EOI | ✅ | ✅ | |
CharClassNegation | ✅ | ||
CharClassChildRemoval | ✅ | ✅ | |
CharClassAnyChar | ✅ | ✅ | |
CharClassRangeModification | ✅ | ||
PredefCharClassNegation | ✅ | ||
PredefCharClassNullification | ✅ | ✅ | |
PredefCharClassAnyChar | ✅ | ✅ | |
UnicodeCharClassNegation | ✅ | ||
QuantifierRemoval | ✅ | ||
QuantifierNChange | ✅ | ✅ | |
QuantifierNOrMoreModification | ✅ | ✅ | |
QuantifierNOrMoreChange | ✅ | ✅ | |
QuantifierNMModification | ✅ | ✅ | |
QuantifierShortModification | ✅ | ✅ | |
QuantifierShortChange | ✅ | ✅ | |
QuantifierReluctantAddition | ✅ | ||
GroupToNCGroup | ✅ | ✅ | |
LookaroundNegation | ✅ | ✅ | ✅ |
Remove the beginning of line character ^
.
Original | Mutated |
---|---|
^abc |
abc |
Remove the end of line character $
.
Original | Mutated |
---|---|
abc$ |
abc |
Change the beginning of line character ^
to a beginning of input character \A
.
Original | Mutated |
---|---|
^abc |
\Aabc |
Change the end of line character ^
to a end of input character \z
.
Original | Mutated |
---|---|
abc$ |
abc\z |
Flips the sign of a character class.
Original | Mutated |
---|---|
[abc] |
[^abc] |
[^abc] |
[abc] |
Remove a child of a character class.
Original | Mutated |
---|---|
[abc] |
[bc] |
[abc] |
[ac] |
[abc] |
[ab] |
Change a character class to a character class which matches any character.
Original | Mutated |
---|---|
[abc] |
[\w\W] |
Change the high and low of a range by one in both directions if possible.
Original | Mutated |
---|---|
[b-y] |
[a-y] |
[b-y] |
[c-y] |
[b-y] |
[b-z] |
[b-y] |
[b-x] |
Flips the sign of a predefined character class. All the predefined character classes are shown in the table below.
Original | Mutated |
---|---|
\d |
\D |
\D |
\d |
\s |
\S |
\S |
\s |
\w |
\W |
\W |
\w |
Remove the backslash from a predefined character class such as \w
.
Original | Mutated |
---|---|
\d |
d |
\D |
D |
\s |
s |
\S |
S |
\w |
w |
\W |
W |
Change a predefined character class to a character class containing the predefined one and its negation.
Original | Mutated |
---|---|
\d |
[\d\D] |
\D |
[\D\d] |
\s |
[\s\S] |
\S |
[\S\s] |
\w |
[\w\W] |
\W |
[\W\w] |
Flips the sign of a Unicode character class.
Original | Mutated |
---|---|
\p{Alpha} |
\P{Alpha} |
\P{Alpha} |
\p{Alpha} |
Remove a quantifier. This is done for all possible quantifiers, even ranges, and the reluctant and possessive variants.
Original | Mutated |
---|---|
abc? |
abc |
abc* |
abc |
abc+ |
abc |
abc{1,3} |
abc |
abc?? |
abc |
abc*? |
abc |
abc+? |
abc |
abc{1,3}? |
abc |
abc?+ |
abc |
abc*+ |
abc |
abc++ |
abc |
abc{1,3}+ |
abc |
Change the fixed amount quantifier to a couple of range variants.
Original | Mutated |
---|---|
abc{9} |
abc{0,9} |
abc{9} |
abc{9,} |
Change the n
to infinity range quantifier to a couple of variants where the low of the range is
incremented and decremented by one.
Original | Mutated |
---|---|
abc{9,} |
abc{8,} |
abc{9,} |
abc{10,} |
Turn an n
or more range quantifier into a fixed number quantifier.
Original | Mutated |
---|---|
abc{9,} |
abc{9} |
Alter the n
to m
range quantifier by decrementing or incrementing the high and low of the
range by one.
Original | Mutated |
---|---|
abc{3,9} |
abc{2,9} |
abc{3,9} |
abc{4,9} |
abc{3,9} |
abc{3,8} |
abc{3,9} |
abc{3,10} |
Treat the shorthand quantifiers (?
, *
, +
) as their corresponding range quantifier
variant ({0,1}
, {0,}
, {1,}
), and applies the same mutations as mentioned in the mutators
above.
Original | Mutated |
---|---|
abc? |
abc{1,1} |
abc? |
abc{0,0} |
abc? |
abc{0,2} |
abc* |
abc{1,} |
abc+ |
abc{0,} |
abc+ |
abc{2,} |
Change the shorthand quantifiers *
and +
to their fixed range quantifier variant.
Original | Mutated |
---|---|
abc* |
abc{0} |
abc+ |
abc{1} |
Change greedy quantifiers to reluctant quantifiers.
Original | Mutated |
---|---|
abc? |
abc?? |
abc* |
abc*? |
abc+ |
abc+? |
abc{9} |
abc{9}? |
abc{9,} |
abc{9,}? |
abc{9,13} |
abc{9,13}? |
Change a normal group to a non-capturing group.
Original | Mutated |
---|---|
(abc) |
(?:abc) |
Flips the sign of a lookaround (lookahead, lookbehind) construct.
Original | Mutated |
---|---|
(?=abc) |
(?!abc) |
(?!abc) |
(?=abc) |
(?<=abc) |
(?<!abc) |
(?<!abc) |
(?<=abc) |