Principe de UUTUC

UUTUC est une bibliothèque offrant un certain nombre de méthodes facilitant le processus de test des composants UIMA. On y trouve notamment un certain nombre de classes de type Factory qui facilitent la mise en place de chaînes de traitement simples pour expérimenter les composants.

À l'aide de ces classes, l'exécution d'un AE sur un simple fichier texte se résume à ces quelques lignes :

  1. AnalysisEngine engine =
  2. AnalysisEngineFactory.createAnalysisEngineFromPath("descriptors/tutorial/ex1/RoomNumberAnnotator.xml");
  3. JCas jCas =
  4. AnalysisEngineFactory.process(engine, "data/WatsonConferenceRooms.txt");

Le couplage de UUTUC avec JUnit permet de mettre en place un banc de tests unitaires :

  • Afin de tester la conformité de l'implémentation avec les spécifications attendues ;
  • Prévenir les problèmes de régression lors de l'évolution des composants

Écriture de tests unitaires

J'utilise le framework JUnit 4 pour les tests unitaires. Il suffit de faire précéder les méthodes considérées comme des tests par @Test pour qu'elles soient reconnues comme telles par JUnit. Exemple :

  1. import org.junit.Test;
  2. import static org.junit.Assert.*;
  3. ...
  4. /**
  5.  * This class defines the tests for the main methods of the Shingle class.
  6.  */
  7. public class ShingleTest {
  8. ...
  9. /**
  10.   * This method just checks that the isComplete method works
  11.   * @throws InvalidShingleException
  12.   * @throws OverloadShingleException
  13.   */
  14. @Test
  15. public void completeness() throws InvalidShingleException, OverloadShingleException {
  16. Shingle s1 = new Shingle(2);
  17. assertFalse( s1.isComplete() ); // before any adding
  18. s1.add( theShingleItems[0] );
  19. assertFalse( s1.isComplete() ); // after a first adding
  20. s1.add( theShingleItems[0] );
  21. assertTrue( s1.isComplete() ); // should be complete by now
  22. }
  23. ...
  24. }

Combiné à UUTUC, il permet de mettre en place un environnement UIMA assez simplement. Ainsi dans l'exemple ci-dessous, nous définissons une méthode à exécuter avant chaque test (@Before) qui crée un JCas et y ajoute quelques annotations à l'aide des Factory de UUTUC :

  1. /** Static data for testing */
  2. private static String CAS_CONTENT =
  3. "Suisse : inauguration d'une nouvelle synagogue, une première depuis 50 ans";
  4. private static Integer[][] CAS_OFFSETS = { {0,6}, {9,21}, {22,24}, {24,27},
  5. {28,36}, {37,46}, {48,51}, {52,60}, {61,67}, {68,74} };
  6. ...
  7. /**
  8.  * This method is used to set up the testing environment, creating the
  9.  * data necessary for the different tests methods.
  10.  */
  11. @Before
  12. public void setUp() throws UIMAException, IOException, ShinglingTestingException {
  13. // Set up a CAS with a couple of shingle items in
  14. TypeSystemDescription tsd = TypeSystemDescriptionFactory
  15. .createTypeSystemDescription("shingling-ts");
  16. theTestingCas = JCasFactory.createJCas(tsd);
  17. theTestingCas.setDocumentText(CAS_CONTENT);
  18. for(Integer[] idx: CAS_OFFSETS) {
  19. AnnotationFactory.createAnnotation(theTestingCas,
  20. idx[0], idx[1], ShingleItem.class) );
  21. }
  22. }

Malheureusement il y a assez peu de documentation concernant UUTUC. Il est ainsi régulièrement nécessaire d'aller jeter un œil au code source qui heureusement est très bien écrit.

Intégration avec Maven

Maven modélisant toutes les étapes du cycle de développement, il intègre une étape test entre le compile et le package. La gestion des tests unitaires se faisant quant à eux au travers du plugin maven-surefire-plugin.

Il faut tout d'abord rajouter dans le pom.xml les informations de dépendance sur UUTUC et JUnit :

  1. <repository>
  2. <snapshots>
  3. <enabled>false</enabled>
  4. </snapshots>
  5. <id>uutuc-googlecode</id>
  6. <name>uutuc Google Code repository</name>
  7. <url>http://uutuc.googlecode.com/svn/repo/</url>
  8. </repository>
  9. ...
  10. <!-- UUTUC for testing -->
  11. <dependency>
  12. <groupId>org.uutuc</groupId>
  13. <artifactId>uutuc</artifactId>
  14. <version>0.9.10</version>
  15. <optional>false</optional>
  16. <scope>test</scope>
  17. </dependency>
  18. <!-- JUnit 4 for testing -->
  19. <dependency>
  20. <groupId>junit</groupId>
  21. <artifactId>junit</artifactId>
  22. <version>4.3.1</version>
  23. <scope>test</scope>
  24. </dependency>

Il suffit ensuite de faire appel au plugin maven-surefire-plugin qui prend en charge tout ce qui concerne les tests, sous réserve que ces derniers soient bien présents dans src/test/java :

  1. <!-- Testing -->
  2. <plugin>
  3. <groupId>org.apache.maven.plugins</groupId>
  4. <artifactId>maven-surefire-plugin</artifactId>
  5. <configuration>
  6. <reportFormat>brief</reportFormat>
  7. <useFile>false</useFile>
  8. </configuration>
  9. </plugin>

Il est alors possible de lancer l'exécution des tests avec Maven :

$ mvn test
...
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running tddts.uima.shingling.ShingleTest
Tests run: 16, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.992 sec

Results :

Tests run: 16, Failures: 0, Errors: 0, Skipped: 0
...

Plus d'excuse pour ne pas tester votre code maintenant ! L'excuse de faire du prototypage pour la recherche n'en est pas une bonne dès que les résultats que vous publiez dépendent de la qualité dudit code. C'est votre intégrité et honnêteté scientifique qui est en jeux ;)