Code Defenders pits two teams against each other on a Java class. Attackers must create mutants in the code, whilst Defenders write unit tests to catch (kill) these changes to the code.
At the top of the page, there are two panels. On the left is the original Class Under Test (CUT), and on the right there is a panel to write a new test, along with a "Defend!" button which submits the test.
Below these panels are two more panels, which show existing mutants and tests. In the mutants panel, mutants can be claimed as being equivalent (which is covered at the end of this page). Existing mutants can also be seen by the icon present in the margin of the CUT panel.
We're going to submit a test to kill an alive mutant. Tests don't necessarily have to target alive mutants, and can simply be made to kill possible future mutants.
- No loops
- No calls to System.*
- No new methods or conditionals
- Only the configured number of assertions per test (default: 2)
If an error is made in your test and it does not compile, a full compiler error is shown at the top of the screen. In this case, I did not add the brackets at the end of a function call.
After re-submitting the test, we see that it compiled successfully and killed the mutant.
The actual changes made in killed mutants can be viewed by clicking the "View Diff" button on the killed tab of the mutants panel.
The attack page only has two panels, existing mutants, and a panel containing the CUT, which can be modified to create mutants. Green lines are covered by existing tests, with darker green showing more coverage.
Similarly to tests, mutants are limited by rules, which come in three strictness levels:
- No calls to System.*,Random.*
- No mutants with only changes to comments or formatting
- No changes to comments
- No additional logical operators (&&, ||)
- No ternary operators
- No new control structures (switch, if, for, ...)
- No reflection
- No bitwise operators (bitshifts and logical)
- No signature changes
Here I have created a mutant by changing the > comparator to <. Return values, variables, etc. can also be changed.
After submitting our mutant by pressing the "Attack!" button, we see that it survived two existing tests. Similarly to submitting a test, an error will be displayed if the mutated class did not compile.
It is possible to create a mutant which is identical in functionality to the CUT, so no test can pass on the CUT and fail on the mutated class.
For example, the following functions are identical in behaviour, they are equivalent:
If a Defender believes that an Attacker's mutant is equivalent, they can click the "Claim Equivalent" button on the mutant.
After this, the Attacker will see that their mutant was marked as equivalent. If the mutant is equivalent, they should accept it as equivalent.
However, if the mutant isn't equivalent, the Attacker can prove that it isn't by writing a test which kills it.
For every test a mutant passes where the test executes the mutated line, the mutant gains a point.
Mutants also gain one point for being created and surviving.
For every mutant a test kills, the test gains points equal to the score of the mutant.
A test gains a point for killing a previously untouched mutant.
A test is also given an additional point for killing a newly created mutant.
If an Attacker proves a mutant is not equivalent, they keep the mutant's points and gain an additional point.
If the Attacker accepts the mutant is equivalent, or the game expires, they lose the points of that mutant, and the Defender who claimed that it is equivalent gains a point.
Code Editor Keyboard Shortcuts
|Ctrl + Space
|Cmd + Space
|Ctrl + F
|Cmd + F
|Ctrl + G
|Cmd + G
|Ctrl + Shift + G
|Cmd + Shift + G
|Search and Replace
|Ctrl + Shift + F
|Cmd + Shift + F
|Search and Replace All
|Ctrl + Shift + R
|Cmd + Shift + R
|Jump to Line
|Alt + R
|Alt + R