Bonjour. 2019 est presque terminée. Cet article est l'article du 25ème jour de Software Testing Advent Calendar 2019.
L'article de la veille a été écrit par mon collègue @ozhiro san, "Quel est votre but en faisant des tests automatisés? ](Https://qiita.com/ozhiro/items/5aa95c6360a8930df325). __être déplacé! __ En passant, j'ai examiné aujourd'hui l'état actuel de l'outil de création automatique de tests unitaires.
Les tests unitaires sont importants, n'est-ce pas? Le logiciel étant développé et modifié quotidiennement, le test unitaire est un outil de test qui garantit la qualité du logiciel développé. De plus, l'exécution des tests peut être automatisée, ce qui réduit l'effort de test.
Cependant, pour exécuter un test unitaire, il est nécessaire de développer un code de test, ce qui nécessite un certain effort de développement. Pour plus d'exhaustivité, cela peut prendre aussi longtemps que le développement du logiciel testé.
Dans un tel contexte, la situation est assez courante uniquement avec des tests manuels à la main sans créer de tests unitaires en raison d'une main-d'œuvre et d'un temps de développement insuffisants. (C'est différent maintenant, mais le projet du travail précédent et du travail précédent était comme ça.) De plus, j'ai déjà une énorme quantité de code source et je veux créer un test unitaire à partir de maintenant, mais par où puis-je commencer? Je pense qu'il y a de nombreuses situations où vous ne savez pas.
J'ai pensé là. Dans un tel monde où l'IA et la RPA (Robotic Process Automation) sont en plein essor, je pense que des outils qui analysent le code source et créent automatiquement des tests unitaires existent déjà dans ce monde. N'est-ce pas comme ça en 2020 ...? Quand.
Nous en 2020 (image):
Je vais immédiatement chercher sur Internet le type d'outils disponibles. La condition de recherche est "générer automatiquement un test unitaire", et comme je suis un ingénieur qui utilise principalement Java, j'ajoute également "Java" à la condition.
Étonnamment, il y a peu de résultats de recherche et d'anciens articles peuvent être vus ici et là, donc je me suis senti un peu mal à l'aise ... (´ ・ ω ・ `), mais j'en ai ramassé environ quatre bons.
Je ne savais pas comment l'utiliser simplement en regardant la vue d'ensemble, j'ai donc créé un code de test à partir du code source réel et l'ai évalué. Nous avons préparé les deux types de code source suivants.
Je voulais ajouter des branches à la méthode 1 et ajouter le taux de couverture des tests à l'évaluation. 2 est une classe avec des instances DI (Dependency Injection). Je voudrais que vous remplaciez l'instance DI par une maquette de Mockito sur le code de test. J'ai un ressenti.
Le code source spécifique a été préparé sur GitHub en tant que projet avec le code de test créé. Il existe des liens vers GitHub à certains endroits, veuillez donc les consulter pour plus de détails.
Maintenant, je voudrais présenter chaque outil et évaluer le code de test généré.
TestMe
Le code de test généré (partiel) est ci-dessous. L'instance DI est simulée à l'aide de Mockito. __Ça m'a l'air bien! __ Étant donné que le code de test n'est généré que selon le modèle, il n'y a pratiquement pas de taux de couverture et il est nécessaire de le développer séparément en fonction du code de test généré. Cependant, la vitesse de génération automatique n'est que de quelques secondes, et j'avais l'impression que ce n'était pas mal comparé à la création de code de test à partir de zéro.
Évaluation: Vitesse: ★★★★★ (plusieurs secondes) couverture: Personnalisation: ★★ (le cadre de test peut être sélectionné)
Cliquez ici pour le code de test et comment le générer
class ZipCodeServiceTest {
@Mock
ZipCodeApi zipCodeApi;
@InjectMocks
ZipCodeService zipCodeService;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
void testSearch() throws IOException {
when(zipCodeApi.search(anyString())).thenReturn(null);
List<ZipCodeData> result = zipCodeService.search("zipCode");
Assertions.assertEquals(
Arrays.<ZipCodeData>asList(
new ZipCodeData("zipcode", "prefcode", "address1", "address2", "address3", "kana1",
"kana2", "kana3")), result);
}
}
Squaretest
Est-ce presque la même chose que TestMe? C'est une impression, mais vous pouvez modifier le modèle sur l'écran de réglage. Je souhaite utiliser une autre bibliothèque telle que AssertJ ou Hamcrest pour l'assertion, donc cette zone est facile à utiliser. S'il ne s'agit pas d'une licence payante __, j'aimerais l'utiliser.
Évaluation: Vitesse: ★★★★★ (plusieurs secondes) couverture: Personnalisation: ★★★★ (Sélectionnez le cadre de test, modifiez le modèle)
Cliquez ici pour le code de test et comment le générer
class ZipCodeServiceTest {
@Mock
private ZipCodeApi mockZipCodeApi;
private ZipCodeService zipCodeServiceUnderTest;
@BeforeEach
void setUp() {
initMocks(this);
zipCodeServiceUnderTest = new ZipCodeService(mockZipCodeApi);
}
@Test
void testSearch() throws Exception {
// Setup
final List<ZipCodeData> expectedResult = Arrays.asList(
new ZipCodeData("zipcode", "prefcode", "address1", "address2", "address3", "kana1", "kana2",
"kana3"));
// Run the test
final List<ZipCodeData> result = zipCodeServiceUnderTest.search("zipCode");
// Verify the results
assertEquals(expectedResult, result);
}
}
EvoSuite
Le code de test créé à partir de 2 n'était pas assez bon, donc le code de test (partie) de 1 est décrit ci-dessous.
La génération du code de test prend 3 minutes. Cependant, cette zone peut être modifiée avec l'argument au moment de la génération. En regardant le taux de couverture du code de test ... __100% __ Incroyable!
Cependant, le code de test généré n'est pas lisible et je n'ai pas envie de le maintenir manuellement plus tard. De nombreuses annotations peu claires sont ajoutées, et le fait qu'il hérite de la classe de base d'EvoSuite est également un peu insatisfaisant. Pour simuler, jetez un œil à 1 code de test. Cependant, il n'a pas été réglé correctement. Ce problème indique qu'il peut être ajusté avec des arguments lors de la génération du code de test, mais une erreur se produit lors de l'exécution et cela finit par être une simulation. Il n'a pas été possible de générer du code de test. (Abandonné en chemin)
Cependant, le taux de couverture est très bon, il serait donc préférable de l'utiliser pour rechercher des bogues lors de la création d'une API sans état et publique. Je me sens comme.
Évaluation: Vitesse: ★★ (3 minutes) Couverture: ★★★★★ (100%!) Personnalisation: ★★ (Certains peuvent être spécifiés par des arguments lors de la génération du code de test)
Cliquez ici pour le code de test et comment le générer
@RunWith(EvoRunner.class) @EvoRunnerParameters(mockJVMNonDeterminism = true, useVFS = true, useVNET = true, resetStaticState = true, separateClassLoader = true, useJEE = true)
public class NumberUtils_ESTest extends NumberUtils_ESTest_scaffolding {
@Test(timeout = 4000)
public void test00() throws Throwable {
boolean boolean0 = NumberUtils.isOddNumberBetween1And50(50);
assertFalse(boolean0);
}
// omit other testcases.
Randoop
Ce que vous pouvez faire est presque identique à Evosuite. La couverture était également de 100%. __ Bien. __ Ce n'est pas facile à utiliser car il n'y a qu'une exécution en ligne de commande pour générer du code de test, mais je pense qu'il est bon que Jar d'exécution ne soit pas nécessaire pour exécuter le code de test généré.
Évaluation: Vitesse: ★★ (quelques minutes) Couverture: ★★★★★ (100%!) Personnalisation: ★★ (Certains peuvent être spécifiés par des arguments lors de la génération du code de test)
Cliquez ici pour le code de test et comment le générer
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class NumberUtilsTest {
public static boolean debug = false;
@Test
public void test01() throws Throwable {
if (debug)
System.out.format("%n%s%n", "RegressionTest0.test01");
// The following exception was thrown during execution in test generation
try {
boolean boolean1 = test.NumberUtils.isEvenNumberBetween1And10WithBadCode((-1));
org.junit.Assert.fail("Expected exception of type java.lang.IllegalArgumentException; message: input should be between 1 and 10.");
} catch (java.lang.IllegalArgumentException e) {
// Expected exception.
}
}
Jusqu'à présent, nous avons étudié et évalué les quatre outils de création automatique de tests unitaires. Pour être honnête, j'ai l'impression que c'est loin de l'image que j'attendais, mais je pense que c'était bon de connaître la situation actuelle.
Le code source, le code de test, l'ensemble de bibliothèques et HowTo ReadMe utilisés dans cette étude sont stockés sur le GitHub ci-dessous. Si vous souhaitez créer du code de test à l'aide de ces outils, nous vous serions reconnaissants de bien vouloir vous y référer.
Investigation of auto generation unit tests with Java
Eh bien, le long calendrier de l'Avent est terminé aujourd'hui. Merci à tous, lecteurs et écrivains! __ Bonne année!
Recommended Posts