Description
Description
Generated tests explicitly assign enum values to corresponding static fields, which is useless as the set of enum values is fixed, and no new instances can be created.
To Reproduce
Generate a test suite for the Coin.reverse()
method in the following code.
public enum Coin {
HEADS,
TAILS;
public Coin reverse() {
return this == HEADS ? TAILS : HEADS;
}
}
Expected behavior
Generated tests should not contain assignments of enum values to corresponding static fields.
Actual behavior
Generated tests explicitly assign enum values to corresponding static fields using reflection.
Note: this behavior depends on the enum support that is not in main
yet (PR #611). When checking on main
, the behavior may differ.
Visual proofs (screenshots, logs, images)
Generated tests:
///region SUCCESSFUL EXECUTIONS for method reverse()
/**
* <pre>
* Test executes conditions:
* {@code (this == HEADS): False }
* returns from: {@code return this == HEADS ? TAILS : HEADS; }
* </pre>
*/
@Test
//@org.junit.jupiter.api.DisplayName("reverse: this == HEADS : False -> return this == HEADS ? TAILS : HEADS")
public void testReverse_NotEqualsHEADS() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
Coin prevHEADS = Coin.HEADS;
try {
Coin heads = Coin.HEADS;
Class coinClazz = Class.forName("enums.Coin");
setStaticField(coinClazz, "HEADS", heads);
Coin coin = Coin.TAILS;
Coin actual = coin.reverse();
assertEquals(heads, actual);
} finally {
setStaticField(Coin.class, "HEADS", prevHEADS);
}
}
/**
* <pre>
* Test executes conditions:
* {@code (this == HEADS): True }
* returns from: {@code return this == HEADS ? TAILS : HEADS; }
* </pre>
*/
@Test
//@org.junit.jupiter.api.DisplayName("reverse: this == HEADS : True -> return this == HEADS ? TAILS : HEADS")
public void testReverse_EqualsHEADS() throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
Coin prevHEADS = Coin.HEADS;
Coin prevTAILS = Coin.TAILS;
try {
Coin heads = Coin.HEADS;
Class coinClazz = Class.forName("enums.Coin");
setStaticField(coinClazz, "HEADS", heads);
Coin tails = Coin.TAILS;
setStaticField(coinClazz, "TAILS", tails);
Coin actual = heads.reverse();
assertEquals(tails, actual);
} finally {
setStaticField(Coin.class, "HEADS", prevHEADS);
setStaticField(Coin.class, "TAILS", prevTAILS);
}
}
///endregion
Environment
This behavior does not depend on any specific test environment.
Additional context
Assignment of specific values to static fields (usually using reflection) and restoring old values after the test is a common trait of UTBot-generated tests. Generally this behavior is necessary as the codegen should guarantee that the initial state of each object matches the expected initial state induced by the symbolic engine. On the other hand, often these assignment are useless. For example, final static fields of JDK classes are correctly initialized by the JDK code, and there is no sensible way to assign something else to these fields without risking to break things. Unfortunately, it seems that the correct and non-redundant object initialization is hard.
Maybe it might be done for some special cases like enum value initialization, as we can be sure that each corresponding static field already has the correct value at the start of the test.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status