Dans un projet Maven, j'ai des classes de test et des classes source dans le même package, mais dans des emplacements physiques différents.
.../src/main/Java/package/** <-- application code
.../src/test/Java/package/** <-- test code
Ce n'est pas un problème pour accéder aux classes source dans les classes de test, mais je voudrais exécuter un exécuteur de test dans la méthode principale et accéder à AllTest.class
pour que je puisse créer un pot et exécuter mes tests.
public static void main(String[] args) {
// AllTest not found
Result result = JUnitCore.runClasses(AllTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
Mais cela ne fonctionne pas car je n'ai pas accès au code de test. Je ne comprends pas car ils sont dans le même paquet.
Question: comment accéder aux classes de test à partir des classes d'application? Sinon, comment Maven peut-il emballer un gros pot contenant des classes de test et exécuter des tests?
Vous ne devez pas accéder aux classes de test à partir de votre code d'application, mais plutôt créer un principal (le même principal) dans la portée du test et créer un artefact supplémentaire pour votre projet.
Cependant, dans cet artefact supplémentaire (pot), vous devriez avoir:
compile
)test
)Ce qui signifie essentiellement un gros pot avec l'ajout de classes de test (et leurs dépendances). Le Maven Jar Plugin et son test-jar
objectif ne répondrait pas à ce besoin. L'option Maven Shade Plugin et son option shadeTestJar
n'aideraient pas non plus.
Alors, comment créer dans Maven un gros pot avec des classes de test et des dépendances externes?
Le Maven Assembly Plugin est un candidat parfait dans ce cas.
Voici un échantillon minimal de POM:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>sample-project</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<artifactId>maven-Assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptor>src/main/Assembly/assembly.xml</descriptor>
</configuration>
<executions>
<execution>
<id>make-Assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>com.sample.TestMain</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
La configuration ci-dessus définit la classe principale que vous avez définie dans vos classes de test. Mais cela ne suffit pas.
Vous devez également créer un fichier descripteur , dans le src\main\Assembly
dossier et Assembly.xml
fichier avec le contenu suivant:
<Assembly
xmlns="http://maven.Apache.org/plugins/maven-Assembly-plugin/Assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.Apache.org/plugins/maven-Assembly-plugin/Assembly/1.1.3 http://maven.Apache.org/xsd/Assembly-1.1.3.xsd">
<id>fat-tests</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>test</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.directory}/test-classes</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*.class</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
</fileSets>
</Assembly>
La configuration ci-dessus est:
test
(qui prendra également l'étendue compile
)fileset
pour inclure les classes de test compilées dans le cadre du pot de graisse emballéfat-tests
classifier (donc votre fichier final sera quelque chose comme sampleproject-1.0-SNAPSHOT-fat-tests.jar
).Vous pouvez ensuite appeler le principal comme suit (à partir du dossier target
):
Java -jar sampleproject-1.0-SNAPSHOT-fat-tests.jar
À partir d'un tel principal, vous pouvez également appeler tous vos cas de test comme suit:
Exemple de suite de tests:
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses({ AppTest.class })
public class AllTests {
}
Remarque: dans ce cas, la suite de tests ne concerne que l'exemple de test AppTest
.
Ensuite, vous pourriez avoir une classe principale comme suit:
import org.junit.internal.TextListener;
import org.junit.runner.JUnitCore;
public class MainAppTest {
public static void main(String[] args) {
System.out.println("Running tests!");
JUnitCore engine = new JUnitCore();
engine.addListener(new TextListener(System.out)); // required to print reports
engine.run(AllTests.class);
}
}
Le principal ci-dessus exécuterait alors la suite de tests qui exécutera en chaîne tous les tests configurés.