552 lines
28 KiB
Plaintext
552 lines
28 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<!-- Updated by Blorec Hervé 2016-08-03-->
|
|
<head>
|
|
<title>JMRI:Les tests unitaires avec JUnit</title>
|
|
<meta name="author" content="Bob Jacobsen">
|
|
<meta name="keywords" content="JMRI technical code ">
|
|
<!--#include virtual="/help/fr/parts/Style.shtml" -->
|
|
</head>
|
|
|
|
<body>
|
|
<!--#include virtual="/help/fr/parts/Header_fr.shtml" -->
|
|
<div id="mBody">
|
|
<!--#include virtual="Sidebar.shtml" -->
|
|
<div id="mainContent">
|
|
<!-- Page Body -->
|
|
|
|
<h1>JMRI: Les tests unitaires avec JUnit</h1>
|
|
|
|
<ul>
|
|
<li><a href="#Introduction">Introduction</a></li>
|
|
<li><a href="#run">Exécutions de Tests</a></li>
|
|
<li><a href="#Continuous">Exécution du Test d'Intégration Continue</a></li>
|
|
<li><a href="#Reporting">Rapport d'Erreur</a></li>
|
|
<li><a href="#Coverage">Rapports de Couverture de Codes</a></li>
|
|
<li><a href="#write">Tests d'Écritures</a>
|
|
<ul>
|
|
<li><a href="#writeAddl4ExistClass">Écriture de Tests Supplémentaires pour une Class Existante</a></li>
|
|
<li><a href="#write4NewClass">Écriture de Tests pour une Nouvelle Classe</a></li>
|
|
<li><a href="#Write4NewPackage">Écriture de Tests pour un Nouveau Paquet</a></li>
|
|
</ul></li>
|
|
<li><a href="#keyMetaphors">Clés Métaphores</a>
|
|
<ul>
|
|
<li><a href="#HandlingLogOutput">Manipulation Sortie Log4J De Tests</a></li>
|
|
<li><a href="#ResetInstMgr">Réinitialisation de l'InstanceManager</a></li>
|
|
<li><a href="#RunningListeners">Exécution des Écouteurs</a></li>
|
|
<li><a href="#io">Test des I/O</a></li>
|
|
<li><a href="#tempFileCreation">Création de Fichier Temporaire dans les Tests</a></li>
|
|
</ul></li>
|
|
<li><a href="#testSwingCode">Test du code Swing</a>
|
|
<ul>
|
|
<li><a href="#complicatedGuiTesting">Test code GUI* Compliqué</a></li>
|
|
</ul></li>
|
|
<li><a href="#testScriptCode">Test du Code Script</a>
|
|
<ul>
|
|
<li><a href="#sampleScriptTesting">Test exemple de scripts Jython</a></li>
|
|
</ul></li>
|
|
<li><a href="#issues">Problèmes</a></li>
|
|
</ul>
|
|
|
|
<a name="Introduction">Introduction</a>
|
|
<p>
|
|
JJUnit est un système de construction de "tests unitaires" du logiciel.
|
|
Les tests unitaires sont de petits tests qui vous assurent que les parties
|
|
individuelles du logiciel font ce qu'elles sont censées faire.
|
|
Dans un projet distribué comme JMRI, où il y a beaucoup de
|
|
développeurs qui peuvent perdre la communication avec les autres,
|
|
les tests unitaires sont une bonne façon pour s'assurer que le code n'a pas
|
|
été cassé par un changement.
|
|
<p>
|
|
Pour plus d'informations sur JUnit, voir
|
|
<a href="http://www.junit.org"> la page d'accueil JUnit</a>.
|
|
Un exemple très intéressant du développement basé sur les tests est disponible à partir du livre de
|
|
<a href="http://www.objectmentor.com/publications/xpepisode.htm"> Robert Martin </a> .
|
|
<p>
|
|
Certaines classes ont des tests JUnit disponibles. C'est bon
|
|
d'ajouter des tests JUnit quand vous apportez des modifications, tester vos nouvelles fonctionnalités
|
|
pour s'assurer qu'elle est au travail, et continue à travailler),
|
|
lorsque vous devez comprendre le code que quelqu'un a fait
|
|
(les tests documentent exactement ce qui doit arriver!),
|
|
et quand vous traquer un bug (assurez-vous qu'il ne revient pas).
|
|
|
|
<h2><a name="run"></a>Exécutez les Tests</h2>
|
|
|
|
Pour exécuter les tests existants, dire
|
|
<code>
|
|
ant antalltest
|
|
</code>
|
|
Cela compilera le code de test, qui est dans le sous-répertoire "test"
|
|
du répertoire "java" dans nos distributions habituelles de code,
|
|
et puis exécutez les tests sous une interface graphique.
|
|
(Pour vous assurer que vous avez tout recompilé, vous
|
|
voudrez peut-être faire <code>ant clean</code> en premier).
|
|
Si vous connaissez le nom
|
|
de votre classe de test, ou la classe de test pour votre paquet, vous
|
|
pouvez exécuter directement avec le script "runTest" :
|
|
<code>
|
|
ant tests<br>
|
|
./runtest.cshjmri.jmrit.powerpanel.PowerPanelTest
|
|
</code>
|
|
Le première ligne compile tout le code de test, et la seconde
|
|
effectue un test spécifique ou une suite de test.
|
|
|
|
<h2><a name="Continuous">Exécution de test d'Intégration Continue</a></h2>
|
|
|
|
L'<a href="ContinuousIntegration.shtml">environnement d'intégration continue</a>
|
|
détecte des changements dans le répertoire de code, reconstruit le code, effectue une variété de
|
|
contrôles. Si aucun problème fatal n'est trouvé, le processus d'intégration continue exécute
|
|
la cible ant "alltest" contre la construction pour exécuter les tests
|
|
contre la construction réussie du code de base.
|
|
|
|
<h3><a name="Reporting">Rapport d'Erreur</a></h3>
|
|
|
|
Si un test échoue durant l'exécution de l'intégration continue de "alltest",
|
|
un e-mail est envoyé à la liste e-mail jmri-build ainsi qu'aux développeurs qui
|
|
ont vérifié le code qui a été inclus dans la construction.
|
|
<p>Vous pouvez visiter le site web
|
|
<a href="https://lists.sourceforge.net/lists/listinfo/jmri-builds">pour
|
|
vous inscrire sur la liste e-mail de jmri-build</a>pour obtenir les mauvaises nouvelles aussi
|
|
rapidement que possible, ou surveiller
|
|
<a href="http://sourceforge.net/mailarchive/forum.php?forum_name=jmri-builds">
|
|
pour voir les archives de la liste e-mail</a> et voir les journaux du passé. Ou vous pouvez
|
|
surveiller le "tableau de bord" sur le site web <a href="ContinuousIntegration.shtml">
|
|
intégration continue</a>.
|
|
|
|
<p>
|
|
( Quand la construction réussit, rien n'est envoyé, pour pour réduire le trafic )
|
|
|
|
<h3><a name="Coverage">Rapports de couverture de code</a></h3>
|
|
|
|
Comme élément d'exécution des tests, Jenkins accumule les informations sur la
|
|
part de code exécuté, appelée "couverture de code". Nous utilisons l'
|
|
<a href="http://eclemma.org/jacoco/">outil JaCoCo</a>
|
|
pour faire le décompte. Il fournit des rapports détaillés à des niveaux multiples:
|
|
<ul>
|
|
<li><a href="https://builds.jmri.org/jenkins/job/Development/job/JaCoCo/jacoco/">Une parcelle de couverture dans son
|
|
ensemble</a>.Cliquez sur le graphique pour en voir une</li>
|
|
<li><a href="https://builds.jmri.org/jenkins/job/Development/job/JaCoCo/lastBuild/jacoco/">Sommaire par paquet Java
|
|
package</a>. Cliquez sur un paquet pour en voir un</li>
|
|
<li><a
|
|
href="https://builds.jmri.org/jenkins/job/Development/job/JaCoCo/lastBuild/jacoco/jmri.jmrit.blockboss/">Sommaire par fichier</a> (ex: class). Cliquez sur une class pour en voir une</li>
|
|
<li><a
|
|
href="https://builds.jmri.org/jenkins/job/Development/job/JaCoCo/lastBuild/jacoco/jmri.jmrit.blockboss/BlockBossLogic/">Sommaire par procédé</a>. Cliquez sur un procédé pour voir</li>
|
|
<li><a
|
|
href="https://builds.jmri.org/jenkins/job/Development/job/JaCoCo/lastBuild/jacoco/jmri.jmrit.blockboss/BlockBossLogic/defineIO()/">Comment chaque partie du code a été couvert</a> (peut nécessiter un défilement).</li>
|
|
</ul>
|
|
|
|
<h2><a name="write">Écriture de Tests</a></h2>
|
|
|
|
Par convention, nous avons un "test" d'observation de classe
|
|
de ( presque ) toutes les classes réelles.
|
|
Le répertoire de "test" contient un arbre de paquet
|
|
répertoires parallèles à l'arbre source.
|
|
Chaque classe de test a le même nom
|
|
que la classe devant être testée, excepté avec "Test" annexé, et
|
|
qui apparaît dans le "test" de l'arbre source.
|
|
Par exemple,
|
|
le code source de la classe "jmri.Version" est dans "src/jmri/Version.java",
|
|
et sa classe de test est "jmri.VersionTest" trouvé dans "test//jmri/VersionTest.java".
|
|
|
|
<p>
|
|
Il y a des classes supplémentaires qui sont utilisées pour
|
|
grouper des classes de test pour un paquet particulier
|
|
dans des suites de test JUnit.
|
|
|
|
<h3><a name="writeAddl4ExistClass">Écriture de Test Supplémentaires pour une Classe Existante</a></h3>
|
|
|
|
Pour écrire des tests supplémentaires pour une classe ayant des tests existants,
|
|
premièrement localisez la classe de test. ( Si elle n'existe pas, voir la
|
|
section ci-dessous au sujet de l'écriture de tests pour une nouvelle classe )
|
|
<p>
|
|
Pour cette classe test, ajoutez une ou plusieurs méthodes de test utilisant les
|
|
conventions JUnit. Basiquement, chaque méthode nécessite un nom qui démarre avec
|
|
"test", exemple: "testFirst" et doit avoir une signature "publique vide".
|
|
JUnit gèrera tout ce qui suit.
|
|
|
|
En général, les méthodes de test doivent être petites, testant juste une partie de
|
|
l'opération classe. C'est pourquoi elles sont appelées tests "unitaire".
|
|
|
|
<h3><a name="write4NewClass">Écriture de Tests pour une Nouvelle Classe</a></h3>
|
|
|
|
( Nécessite des infos ici: basiquement, copier quelques autres paquet, et
|
|
ne pas oublier de mettre une entrée dans l'enceinte du paquet de suite de test )
|
|
|
|
<h2><a name="keyMetaphors">Clé de Test Métaphores</a></h2>
|
|
|
|
<h3><a name="HandlingLogOutput">Manipulation de la Sortie Log4J Pour les Tests</a></h3>
|
|
|
|
JMRI utilise
|
|
<a href="http://logging.apache.org/log4j/docs/index.html">Log4j</a>
|
|
pour
|
|
<a href="Logging.shtml">gérer l'enregistrement des différentes conditions</a>
|
|
incluant messages erreurs et
|
|
information de débogage. Les tests sont destinés à fonctionner sans sortie d'erreur ou
|
|
d'avertissement, de sorte qu'il est immédiatement apparent qu'un rapport standard vide
|
|
indique qui ils ont été parcouru proprement.
|
|
<p>
|
|
L'usage de Log4j dans les classes de test elle-mêmes a deux aspects:
|
|
<ol>
|
|
<li>Il est parfaitement Ok pour utiliser les états Log.debug(...) pour le rendre
|
|
facile pour les problèmes de débogage dans les tests d'états. log.info(...) peut être utilisé
|
|
avec parcimonie pour indiquer la progression normale, parce qu'il est normalement désactivé
|
|
pendant l'exécution des tests.
|
|
<li>En général, log.warn ou log.error doit seulement être utilisé quand le test
|
|
va ensuite déclencher une assertion ou une exception de JUnit, parce que le fait qu'une
|
|
erreur est enregistrée, elle ne se montre pas directement dans le résumé des résultats JUnit.
|
|
</ol>
|
|
D'autre part, vous pourriez vouloir provoquer délibérément des erreurs dans le
|
|
code devant être testé pour être sûr que les conditions sont gérées proprement.
|
|
Ceci produira souvent des messages log.error(...) ou log.warn(...); qui doivent
|
|
être interceptés et vérifiés.
|
|
<p>
|
|
Pour permettre ceci, JMRI fonctionne et il utilise des tests avec un dispositif log4j spécial, qui
|
|
stocke les messages de sorte que les tests JUnit peuvent les regarder avant de les transmettre
|
|
dans le journal. Il y a deux aspects pour faire ce travail:
|
|
<ol>
|
|
<li>Toutes les classes d'essai doivent inclure le code commun dans leur configuration()
|
|
et leur code de désassemblage() pour être sûr que log4j est proprement initié, et que
|
|
le dispositif personnalisé discute quand un test démarre ou s'arrête.
|
|
<code>
|
|
@Before<br>
|
|
public void setUp() throws Exception { <br>
|
|
jmri.util.JUnitUtil.setUp(); <br>
|
|
}<br>
|
|
@After<br>
|
|
public void tearDown() throws Exception { <br>
|
|
jmri.util.JUnitUtil.tearDown(); <br>
|
|
}<br>
|
|
</code></li>
|
|
<li>Quand un test invoque délibérément un message, il faut
|
|
alors utiliser le contrôle pour voir si le message a été créé.
|
|
Par exemple, si la classe en test devrait faire
|
|
<br>
|
|
<code>
|
|
log.warn("Provoked message");
|
|
</code>
|
|
la case du test appelant devrait suivre avec la ligne:
|
|
<br>
|
|
<code>
|
|
jmri.util.JUnitAppender.assertWarnMessage("Provoked message");
|
|
</code>
|
|
<br>
|
|
Ce sera une erreur de JUnit si un message log.warn(...) ou log.error(...) est
|
|
produit et qu'il ne correspond pas à un appel JUnitAppender.assertWarnMessage(...).
|
|
</li>
|
|
</ol>
|
|
|
|
Dans tous les cas, l'ensemble de vos routines principales() devrait commencer par
|
|
<code>
|
|
jmri.util.JUnitUtil.setUp();
|
|
</code>
|
|
de sorte qu'elles peuvent être exécutées de façon indépendante.
|
|
|
|
<p>
|
|
Note: Nos
|
|
<a href="ContinuousIntegration.shtml ">CI test</a>
|
|
exécutables sont configurés pour échouer si des messages FATAL ou ERROR
|
|
sont émis au lieu d'être traités. Cela signifie que même si vous pouvez
|
|
exécuter vos tests avec succès sur votre ordinateur, s'ils emettent des messages d'erreurs,
|
|
mais vous ne serez pas en mesure de fusionner votre code dans le répertoire commun jusqu'à ce que ceux-ci soient traités.
|
|
|
|
<h3><a name="ResetInstMgr">Réinitialisation de l'InstanceManager</a></h3>
|
|
|
|
si vous testez du code qui va référencer l'InstanceManager,
|
|
vous devez
|
|
effacer et réinitialiser pour vous assurer d'obtenir des résultats reproductibles.
|
|
<p>
|
|
Dépendant du code utilisé par vos gestionnaires, votre mise en œuvre de <code>configuration()</code> devrait commencer par:
|
|
<p><code>
|
|
jmri.util.JUnitUtil.setUp();<br>
|
|
jmri.util.JUnitUtil.resetInstanceManager();<br>
|
|
jmri.util.JUnitUtil.initInternalTurnoutManager();<br>
|
|
jmri.util.JUnitUtil.initInternalLightManager();<br>
|
|
jmri.util.JUnitUtil.initInternalSensorManager();<br>
|
|
</code>
|
|
( Vous pouvez omettre l'initialisation des gestionnaires dont vous n'avez pas besoin )
|
|
Voir la classe jmri.util.JUnitUtil pour la liste complète de ceux qui sont disponibles, et svp ajoutez
|
|
en plus si vous avez besoin d'un que vous n'avez pas déjà.
|
|
|
|
<p>
|
|
Votre <code>désassemblage()</code> doit se terminer par
|
|
<p>
|
|
<code>
|
|
jmri.util.JUnitUtil.resetInstanceManager();<br>
|
|
jmri.util.JUnitUtil.tearDown();
|
|
</code>
|
|
|
|
<h3><a name="RunningListeners">Travailler avec les Auditeurs</a></h3>
|
|
|
|
JMRI est une application multi tâches. Les Auditeurs
|
|
pour les les objets JMRI sont informés sur les différentes tâches.
|
|
Parfois, il faut attendre que cela se déroulent
|
|
<p>
|
|
Si vous voulez attendre pour une condition spécifique pour être vrai, ex:
|
|
recevoir une réponse d'un objet, vous pouvez utiliser
|
|
un appel à la méthode waitFor
|
|
qui ressemble à:
|
|
<pre><code>
|
|
JUnitUtil.waitFor(()->{reply!=null}, "reply didn't arrive");
|
|
</code></pre>
|
|
Le premier argument est une une fermeture lambda, un petit morceau de code
|
|
qui est évaluer répétitivement jusqu'à être vrai. La chaîne, deuxième argument, est le
|
|
texte de l'assertion ( message d'erreur ) que vous obtiendrez si la condition
|
|
ne devient pas vrai dans un temps raisonnable.
|
|
<p>
|
|
L'attente d'un résultat spécifique est plus rapide et plus fiable.
|
|
Si vous ne pouvez pas faire cela pour une raison quelconque,
|
|
vous pouvez faire une attente basée sur un temps court
|
|
<pre><code>
|
|
JUnitUtil.releaseThread(this);
|
|
</code></pre>
|
|
Celui-ci utilise un retard nominal.
|
|
<p>
|
|
Notez que celui-ci ne devrait <b>pas</b> être utilisé en synchronisme avec les tâches Swing
|
|
Voir le <a href="#testSwingCode"> Test Code Swing</a>, une section faite pour ça.
|
|
<p>
|
|
En général,vous ne devriez pas avoir d'appels pour dormir(), attendre(), produire() dans votre code.
|
|
Utilisez l'aide de JUnitUtil pour ceux en place.
|
|
|
|
<h3><a name="threads">Travailler avec les Tâches</a></h3>
|
|
|
|
( Voir la
|
|
<a href="#testSwingCode">Section suivante</a>
|
|
pour voir comment travailler avec les
|
|
<a href="#testSwingCode">Objets Swing (GUI*)</a>
|
|
et le
|
|
<a href="#testSwingCode">Lien Swing/AWT</a>)
|
|
<p>
|
|
Certains tests devront commencer les tâches, par exemple pour tester pour tester les commandes de signaux
|
|
ou les aspects sur le réseau I/O
|
|
<p>Principes généraux: vos tests doivent obéir à un fonctionnement fiable:</p>
|
|
<ul>
|
|
<li>À la fin de chaque test, vous devez arrêter () toutes les tâches que vous avez commencées.
|
|
Faire cela en interruption () peut être plus fiable, parce que l'interruption s'exécute
|
|
même si votre méthode test existe en raison d'une erreur.
|
|
<p>
|
|
Si vous faites de multiples tests avec les tâches, vous devez
|
|
attendre la tâche pour réellement arrêter avant de passer à l'opération suivante.
|
|
Vous pouvez faire cela avec un appel <code>JUnitUtil.waitFor(..)</code>
|
|
qui attends certains drapeau dans la tâche.
|
|
<li>Si votre tâche fait toutes les opérations de <code>code()</code>
|
|
qui doivent se produire avant de tester son fonctionnement,vous devez également attendre pour ceux à terminer.
|
|
</ul>
|
|
<p>
|
|
Par exemple, si la création d'une tâche est basée sur
|
|
<a href="https://jmri.org/JavaDoc/doc/jmri/jmrit/automat/AbstractAutomaton.html">AbstractAutomat</a>
|
|
vous pouvez vérifier le démarrage avec:
|
|
<pre><code>
|
|
AbsractAutomat p = new MyThreadClass();<br>
|
|
p.start();<br>
|
|
JUnitUtil.waitFor(()->{return p.isRunning();}, "logic running");
|
|
</code></pre>
|
|
et s'assurer de la fin avec:
|
|
<pre><code>
|
|
p.stop();<br>
|
|
JUnitUtil.waitFor(()->{return !p.isRunning();}, "logic stopped");
|
|
</code></pre>
|
|
|
|
<h3><a id="io" name="io"></a>Essai E/S</h3>
|
|
|
|
Certains environnements de test n'alignent pas automatiquement les opérations d'E/S tels
|
|
que le flux au cours des essais. Si vous testez quelque chose qui fait 'E/S, par exemple
|
|
un TrafficController, vous devrez ajouter une instruction "flush ()" sur tous vos flux de sortie.
|
|
( Avoir à attendre longtemps pour faire un test fiable est un indice de ce qui se passe quelque chose quelque part dans votre code )
|
|
|
|
<h3><a name="tempFileCreation">Création de Fichier Temporaire dans les Essais</a></h3>
|
|
|
|
Testcases qui créent des fichiers temporaires doivent être soigneusement créées de sorte
|
|
qu'il n'y aura pas de problèmes avec le chemin du fichier,la sécurité du système de fichiers,
|
|
pré-existence du fichier, etc. Ces tests doivent également être rédigés d'une manière
|
|
qui va opérer avec succès dans l'environnement <a href="ContinuousIntegration.shtml">
|
|
construction d'intégration continue</a>. Et les fichiers temporaire ne doivent
|
|
pas devenir un élément du répertoire de code JMRI
|
|
<p>
|
|
Voici quelques idées qui peuvent aider à éviter ces types de problèmes.
|
|
<ul>
|
|
<li>Placez le fichier temporaire dans le répertoire "temp" qui est un sous-
|
|
répertoire du répertoire exécutable JMRI. Ce répertoire est utilisé par
|
|
beaucoup de testcases et est déjà configuré comme exclus du répertoire
|
|
de code JMRI. Il peut être utile de créer un sous-répertoire là pour les
|
|
fichiers créés par un test particulier. Assurez-vous que le répertoire
|
|
existe avant la création de fichiers dans le répertoire, et de créer le
|
|
répertoire si nécessaire.
|
|
Un exemple est montré ici:
|
|
<code>
|
|
String tempDirectoryName = "temp";<br>
|
|
if ( <strong>! (new File(tempDirectoryName).isDirectory())</strong>) {<br>
|
|
// create the temp directory if it does not exist<br>
|
|
<strong>FileUtil.createDirectory(tempDirectoryName);</strong><br>
|
|
}<br>
|
|
</code>
|
|
</li>
|
|
<li> Laisser le JRE définir le caractère de séparation de hiérarchie de répertoire
|
|
automatiquement:
|
|
<code>
|
|
String filename = tempDirectoryName + <strong>File.separator</strong> + "testcaseFile.txt";
|
|
</code>
|
|
</li>
|
|
<li> Codez la testcase d'une manière qui ne cassera pas si le fichier existe
|
|
déjà avant que la testcase soit exécutée. Une façon de le faire est de coder
|
|
la testcase pour vérifier l'existence du fichier temporaire de testcase(s),
|
|
et le supprimer le cas échéant, avant d'écrire sur le fichier(s).L'exemple
|
|
suivant supprime le fichier précédent s'il existe:
|
|
<code>
|
|
String filename = tempDirectoryName + File.separator + "testcaseFile.txt";<br>
|
|
File file = new File(filename);<br>
|
|
<strong>if (file.exists())</strong> {<br>
|
|
<strong> try {<br>
|
|
file.delete();<br>
|
|
} catch (java.lang.Exception e) {<br>
|
|
Assert.fail("Exception while trying to delete the existing file " + <br>
|
|
filename + <br>
|
|
".\n Exception reported: " + <br>
|
|
e.toString());<br>
|
|
// perform some appropriate action in this case<br>
|
|
}</strong><br>
|
|
}<br>
|
|
</code>
|
|
</li>
|
|
<li>Soyez sûr de "fermer" le fichier temporaire après qu'il ait été écrit.</li>
|
|
<li>Effacer le(s) fichier(s) temporaire comme élément du test une fois qu'il n'y
|
|
en a plus besoin pour le(s) testcase(s). Pour permettre le débogage des testcases
|
|
il peut être interressant d'afficher le chemin et le nom de fichier, lors de la
|
|
connexion des messages de débogage (sans supprimer le fichier temporaire) et pour
|
|
effectuer la suppression uniquement lorsque la journalisation du débogage est pas
|
|
activée, tels que:
|
|
<code>
|
|
<strong>if (log.isDebugEnabled()) {</strong><br>
|
|
log.debug("Path to written hex file is: "+filename);<br>
|
|
<strong>}<br>
|
|
else {<br>
|
|
file.delete();<br>
|
|
}</strong><br>
|
|
</code>
|
|
</li>
|
|
<li>Il est difficile de savoir si les routines de la bibliothèque Java natives qui créent des
|
|
fichiers temporaires de manière opératoire spécifique au système, tels que:
|
|
<code>
|
|
java.io.File.createTempFile("testcasefile","txt")
|
|
</code>
|
|
fonctionneront de manière fiable dans l'environnement <a href="ContinuousIntegration.shtml">
|
|
construire en intégration continue</a>.</li>
|
|
</ul>
|
|
<p>Les questions ci-dessus ont été identifiées par l'intermédiaire d'une testcase qui a exécutée correctement
|
|
sur un PC sous Windows pour les deux cibles ant "alltest" et "headlesstest", peu importe combien de
|
|
fois il a été exécuté. dans l'environnement
|
|
<a href="ContinuousIntegration.shtml"> intégration continue</a>
|
|
le test a couru correctement la première fois après avoir été vérifié, mais a échoué pour chaque
|
|
exécution de l'environnement d'intégration continue ultérieur de "headlesstest".Une fois que le test a été modifié sur
|
|
la base des recommandations de fichiers temporaires présentées ici, le test est devenu stable sur plusieurs exécutions d'intégration
|
|
continue de "headlesstest".
|
|
|
|
<h2><a id="testSwingCode" name="testSwingCode"></a>Essai du Code</h2>
|
|
|
|
AWT et le code Swing fonctionne sur une tâche séparée de tests JUnit.
|
|
Une fois qu'un objet Swing ou AWT a été affiché (via <Code>show ()</code>
|
|
ou <code> setVisible (true)</code>), il ne peut pas être accessible de manière
|
|
fiable à partir de la tâche JUnit. Même l'utilisation de la technique de
|
|
retard d'écouteur décrit ci-dessus n'est pas fiables.
|
|
|
|
<p>
|
|
Parce que nous utilisons les tests en mode "headless" pendant les
|
|
<a href="ContinuousIntegration.shtml">constructions en intégration continue</a>
|
|
il est important que l'accès de Swing ( et AWT ) à des tests soit enfermé dans
|
|
un mode de vérification:
|
|
<p><code>
|
|
if (!System.getProperty("jmri.headlesstest","false").equals("true")) {<br>
|
|
suite.addTest(myTest.suite());<br>
|
|
}<br>
|
|
</code>
|
|
<p>Ceci exécute Le myTest suite de test seulement quand un affichage est disponible.
|
|
|
|
<p>Les test GUI* doivent fermer les fenêtres quand ils sont terminés, et en général se nettoient après eux-mêmes.
|
|
Si vous voulez garder les fenêtres autour de sorte que vous pouvez les manipuler, par exemple pour le test manuel ou débogage
|
|
vous pouvez utiliser le paramètre système jmri.demo pour contrôler que:
|
|
<p><code>
|
|
if (!System.getProperty("jmri.demo", "false").equals("false")) {<br>
|
|
myFrame.setVisible(false);<br>
|
|
myFrame.dispose();<br>
|
|
}
|
|
</code>
|
|
|
|
<p>
|
|
Pour de nombreux tests, vous pourrez à la fois faire des tests fiables et améliorer la structure
|
|
de votre code en séparant le code GUI (Swing) de la logique JMRI et des
|
|
communications. Cela vous permet de vérifier le code logique séparément, mais en invoquant
|
|
ces méthodes et de vérifier l'état de leurs mise à jour.
|
|
|
|
<h3><a name="complicatedGuiTesting">Essai code GUI Compliqué</a></h3>
|
|
<p>
|
|
Pour des tests GUI* plus compliqués, nous utilisons
|
|
<a href="http://jfcunit.sourceforge.net/">JFCUnit</a>
|
|
pour contrôler les interactions avec les objets Swing.
|
|
|
|
<p>
|
|
Pour un très simple exemple de l'utilisation de JFCUnit, voir le fichier
|
|
<a href="https://github.com/JMRI/JMRI/blob/master/java/test/jmri/util/SwingTestCaseTest.java">test/jmri/util/SwingTestCaseTest.java</a>.
|
|
|
|
<p>
|
|
Pour utiliser JFCUnit,vous héritez premièrement de votre classe depuis
|
|
<code>SwingTestCase</code> au lieu de <code>TestCase</code>.
|
|
Cela est suffisant pour obtenir le fonctionnement de base des tests Swing; la classe de base
|
|
interrompt la tâche de test jusqu'à ce que Swing (en fait, le mécanisme d'événement AWT)
|
|
a terminé tous les traitements après chaque appel Swing dans le test.
|
|
Pour cette raison, les tests vont s'exécuter beaucoup plus lentement si vous vous déplacez par exemple
|
|
le curseur de la souris pendant qu'ils s'exécutent)
|
|
|
|
<p>
|
|
Pour les tests plus complexe de l'interface graphique, vous pouvez appeler les différents aspects de l'interface
|
|
et vérifier l'état interne en utilisant le code de test.
|
|
|
|
<h2><a id="testScriptCode" name="testScriptCode"></a>Essai Code Script</h2>
|
|
|
|
JMRI est fourni avec des exemples de scripts. Cette section discute de comment vous pouvez écrire
|
|
des tests simples pour vous assurez qu'ils continuent de travailler.
|
|
|
|
<h3><a id="sampleJythonScriptTesting" name="sampleJythonScriptTesting"></a>Essai d'exemple de scripts Jython</h3>
|
|
|
|
Les tests de scripts peuvent être placés dans <code>jython</code> et appelés par
|
|
<code><a href="https://github.com/JMRI/JMRI/blob/master/java/test/jmri/jmrit/jython/SampleScriptTest.java">java/test/jmri/jmrit/jython/SampleScriptTest.java</a></code>.
|
|
<p>
|
|
Voir <code> <a href="https://github.com/JMRI/JMRI/blob/master/jython/test/jmri_bindings_test.py">jmri_bindings_test
|
|
.py</a></code>
|
|
exemple pour la syntaxe.
|
|
<p>
|
|
La classe <code>SampleScriptTest</code> est un espace réservé, et doit (éventuellement) être étendu pour ramasser automatiquement les fichiers,
|
|
pour soutenir les essais Unit, etc.
|
|
|
|
<h2><a name="issues">Problèmes</a></h2>
|
|
|
|
JUnit utilise un classloader personnalisé, ce qui peut causer des problèmes pour trouver
|
|
des singletons (classes uniques) et démarrer Swing. Si vous obtenez l'erreur
|
|
de ne pas être en mesure de trouver ou de charger une classe,
|
|
soupçonnez que l'ajout de la classe manquante
|
|
au fichier test/junit/runner/ excluded.properties la corrigerait.
|
|
<p>
|
|
<em> Comme un test seulement</em> , vous pouvez essayer de régler l'option "-noloading" dans le
|
|
<code>main</code> de n'importe quel test de classe avec lequelque vous avez des problèmes avec:
|
|
<code>
|
|
static public void main(String[] args) {<br>
|
|
String[] testCaseName = {"-noloading", LogixTableActionTest.class.getName()};<br>
|
|
junit.swingui.TestRunner.main(testCaseName);<br>
|
|
}<br>
|
|
</code>
|
|
|
|
<p>
|
|
SVP ne laissez pas "-noloading" en place, car il empêche les gens de réexécuter le test
|
|
dynamique. Au lieu de cela, le bon correctif à long terme est d'avoir toutes les classes
|
|
ayant des problèmes chargeur JUnit incluses dans le fichier
|
|
<code>test/junit/runner/excluded.properties</code>
|
|
JUnit utilise ces propriétés pour décider comment gérer le chargement et le rechargement des classes.
|
|
<p>
|
|
GUI* = Interface Graphique Utilisateur
|
|
</p>
|
|
|
|
<!--#include virtual="/help/fr/parts/Footer_fr.shtml" -->
|
|
</div><!-- closes #mainContent-->
|
|
</div> <!-- closes #mBody-->
|
|
<script src="/js/help.js"></script>
|
|
</body>
|
|
</html>
|