Master Informatique 2015-2016 Spécialité STL Développement des
Transcription
Master Informatique 2015-2016 Spécialité STL Développement des
Master Informatique 2015-2016 Spécialité STL Développement des langages de programmation DLP – 4I501 Carlos Agon [email protected] 1/64 Introduction Librement inspiré du cours ILP de Christian Queinnec. Slides et mp3 sur le site : www-master.ufr-info-p6.jussieu.fr/2007/Ext/queinnec/ILP/ 2/64 Introduction Buts Implanter un langage de la classe de Javascript à syntaxe XML avec un interprète écrit en Java et un compilateur écrit en Java qui produit du C. 3/64 Introduction Buts pédagogiques Exercice de lecture de code Usage élaboré de Java 8 Non modification des codes précédemment donnés Réflexions sur la conception de langages 4/64 Introduction Cheminement Carlos Agon (cours 1-4) Syntaxe, interprétation, compilation vers C (ILP1) DOM, XML, RelaxNG, JUnit3, JUnit4, visiteur (cours 5) Fonctions, affectation, boucle (ILP2) Généricité, analyse statique Antoine Miné (cours 6) Exceptions (ILP3) C longjmp/setjmp (cours 7) Lambda expressions (ILP3) Définition, interprétation, compilation (cours 8-9) Classe, objet, appel de méthode (ILP4) (cours 10) Édition de liens (ILP4) 5/64 Introduction Évaluation Première évaluation (ILP1 et ILP2, cours 1-5) 40% Deuxième évaluation (ILP1 - ILP4) 60% TME hebdomadaire (groupe 1 vendredi) Carlos Agon/Antoine Miné, (groupe 2 jeudi) Binh Minh Bui Xuan, (groupe 3 jeudi) Philippe Esling. 6/64 Cours 1 Plan du cours 1 Grand schéma Langage ILP1 sémantique discursive syntaxes XML DOM grammaires : Relax NG DOM et IAST AST Tests JUnit3 et JUnit4 7/64 Cours 1 Grand schéma javaCC, sableCC, CUP, ANTLR source syntaxe Scheme source syntaxe XML source syntaxe concrète source DOM jaxb, castor XStream, xmlBeans source AST Transformations, optimisations AST2 texte C a.out AST resultat gcc 8/64 Cours 1 Langage ILP1 ILP1 Ce qu’il y a : constantes (entière, flottante, chaîne de caractères, booléens) alternative, séquence variable, bloc local n-aire invocation de fonctions opérateurs unaires ou binaires ce qu’il n’y a pas (encore !) (liste non exhaustive) : pas pas pas pas pas pas d’affectation de boucle de définition de fonction d’exception des lambda de classe 9/64 Cours 1 Langage ILP1 Les composants d’un langage Des principes de calcul et d’architecture calcul : impératif, fonctionnel, logique, etc. architecture : modularité, polymorphisme, etc. Lexique + syntaxe Un système de types (pas tous) Une sémantique Un environnement de programmation compilateurs, débogueurs, manuels, Une communauté d’utilisateurs 10/64 Cours 1 Langage ILP1 Syntaxe Python-Caml let x = 111 in let y = true in if ( y == -3.14 ) then print " O " + " K " else print ( x * 6.0) endif newline 11/64 Cours 1 Langage ILP1 Syntaxe Scheme ( let (( x 111)) ( let (( y # t )) ( if (= y -3.14) ( print ( plus " O " " K ")) ( print (* x 6.0)) ) ) ( newline ) ) 12/64 Cours 1 Langage ILP1 Syntaxe C/Java { int x = 111; { boolean y = true ; if ( y == -3.14 ) { print ( " O " + " K " ); } else { print ( x * 6.0); } } newline (); } 13/64 Cours 1 Langage ILP1 Définition d’un langage Définitions : Symbole : signe primitif (lettre, chiffre, point, ligne, ?) Alphabet : ensemble fini de symboles (Σ) Chaîne : séquence finie de symboles (la chaîne vide ) Langages formel : ensemble de chaînes définies sur un alphabet Σ Problèmes : Comment définir un langage en intension ? Comment calculer si une chaîne ω appartient ou non à un langage L ? 14/64 Cours 1 Langage ILP1 The dragon book C’est important,mais, on ne s’y intéressera pas ! On partira donc d’une syntaxe XML. 15/64 Cours 1 Langage ILP1 Syntaxe arborescente programme1 blocUnaire variable nom=x valeur corps blocUnaire entier valeur=111 variable nom=y valeur corps booleen valeur=true alternative condition consequence alternant ... operationBinaire operateur=== operandeGauche variable nom=y operandeDroit flottant valeur=−3.14 invocationPrimitive fonction=print arguments invocation fonction arguments variable nom=plus chaine valeur=O chaine valeur=K 16/64 Cours 1 Langage ILP1 Syntaxe XML < program > < block > < bindings > < binding > < variable name = ’x ’/ > < initialisation > < float value = ’ 111 ’/ > </ initialisation > </ binding > < binding > < variable name = ’y ’/ > < initialisation > < boolean value = ’ true ’/ > </ initialisation > </ binding > </ bindings > < body > < alternative > < condition > < b in aryOperation operator = ’ == ’ > < leftOperand > < variable name = ’y ’ </ leftOperand > < rightOperand > < unaryOperation operator = ’ - ’ > < operand > < float value = ’ 3.14 ’/ > </ rightOperand > </ operand > </ unaryOperation > </ b in aryOperation > </ condition > < consequence > < invocation > < function > < variable name = ’ print ’/ > </ function > < arguments > . . . </ arguments > </ invocation > </ consequence > < alternant > . . . </ alternant > 17/64 Cours 1 XML Rudiments d’XML Un langage normalisé pour représenter des arbres. <? xml version ="1.0" encoding = ’ ISO -8859 -1 ’ standalone =" yes " ?> <? xml - stylesheet type =" text / xsl " href =" style . xsl "? > <ul > < li > un & nbsp ; </ li > <! - - attention : --> < li rien =" du tout "/ > </ ul > Attention à UTF-8, ISO-8859-1 (latin1) ou ISO-8859-15 (latin9). 18/64 Cours 1 XML Terminologie Un élément débute par le < de la balise ouvrante et se termine avec le > de la balise fermante correspondante. Un élément contient au moins une balise mais peut contenir d’autres éléments, du texte, des commentaires (et des références à des entités éventuellement des instructions de mise en œuvre). Une balise (pour tag) débute par un < et s’achève au premier > qui suit. Une balise possède un nom et, possiblement, des attributs. Les noms des balises sont structurés par espaces de noms (par exemple xml:namespace ou rdf:RDF). 19/64 Cours 1 XML Caractères bizarres en XML Entités prédéfinies ou sections particulières (échappements) : & amp ; & lt ; & gt ; & apos ; & quot ; <? xml version ="1.0" encoding =" ISO -8859 -15" standalone =" ye <ul > < li / > <li > <![ CDATA [ 1 li >1 m ? <! @ #~*} ]] > </ li > <li > 1 li & gt ;1 m ? & lt ;! @ #~*} </ li > </ ul > 20/64 Cours 1 XML Validation d’XML Un programme écrit en XML doit être bien formé c’est-à-dire respectueux des conventions d’XML. Un programme écrit en XML doit aussi être valide vis-à-vis d’une grammaire. Les grammaires sont des DTD (pour Document Type Definition) ou maintenant des XML Schémas ou des schémas Relax NG. Énorme intérêt pour la lecture en cas d’erreur. 21/64 Cours 1 XML Backus Naur Form BNF méta-symboles : ::=, (, ), | non terminaux : <nom> terminaux : «mots» 22/64 Cours 1 XML Exemple <terme> ::= <nombre signé> | <nombre signé> <op> <terme> <nombre signé> ::= <nombre> | «+» <nombre> | «-» <nombre> <nombre> ::= <entier> | <nombre fractionnaire> <nombre fractionnaire> ::= <entier> | <entiere> «/» <entiere> <entier> ::= <chiffre> | <chiffre><entier> <chiffre> ::= «0» | «1» | ... | «9» 23/64 Cours 1 XML Exemple <terme> ::= <nombre signé> | <nombre signé> <op> <terme> <nombre signé> ::= <nombre> | «+» <nombre> | «-» <nombre> <nombre> ::= <entier> | <nombre fractionnaire> <nombre fractionnaire> ::= <entier> | <entiere> «/» <entiere> <entier> ::= <chiffre> | <chiffre><entier> <chiffre> ::= «0» | «1» | ... | «9» 1 + 3 - 1/4 1 + 3 * 1/4 1 + 3 * 1/0 23/64 Cours 1 RelaxNG RelaxNG Relax NG est un formalisme pour spécifier des grammaires pour XML (bien plus lisible que les schémas XML (suffixe .xsd mais pour lesquels existe un mode dans Eclipse)). Les grammaires Relax NG (prononcer relaxing) sont des documents XML (suffixe .rng) écrivables de façon compacte (suffixe .rnc) et surtout lisibles ! Une fois validé, les textes peuvent être réifiés en DOM (Document Object Model). 24/64 Cours 1 RelaxNG Grammaire RelaxNG – ILP1 Les caractéristiques simples sont codées comme des attributs, les composants complexes (sous-arbres) sont codés comme des sous-éléments. Ressource: Grammars/grammar1.rnc s t a r t = program program = element program { expression + } expression = alternative | sequence | block | constant | invocation | operation | variable 25/64 Cours 1 RelaxNG alternative = element alternative { element condition { expression } , element consequence { expression + } , element alternant { expression + } ? } sequence = element sequence { expression + } block = element block { element bindings { element binding { variable , element initialisation { expression } } * }, element body { expression + } } 26/64 Cours 1 RelaxNG invocation = element invocation { element function { expression } , element arguments { expression * } } variable = element variable { a t t r i b u t e name { xsd : Name - ( xsd : Name { pattern = " ( empty } operation = unaryOperation | binaryOperation unaryOperation = element unaryOperation { a t t r i b u t e operator { " -" | " ! " } , element operand { expression } } 27/64 Cours 1 RelaxNG binaryOperation = element binaryOperation { element leftOperand { expression } , a t t r i b u t e operator { " + " | " -" | " * " | " / " | " % " | "|" | "&" | "^" | " <" | " <= " | " == " | " >= " | " >" | " <>" | " != " }, element rightOperand { expression } } constant = element integer { a t t r i b u t e value { xsd : integer } , empty } | element float { a t t r i b u t e value { xsd : float } , empty } | element string { t e x t } | element boolean { a t t r i b u t e value { " true " | " false " } , empty } 28/64 Cours 1 RelaxNG Validation < program > < block > < bindings > < binding > < variable name = ’x ’/ > < initialisation > < float value = ’ 111 ’/ > </ initialisation > </ binding > < binding > < variable name = ’y ’/ > < initialisation > < boolean value = ’ true ’/ > </ initialisation > </ binding > </ bindings > < body > < alternative > < condition > < b in aryOperation operator = ’ == ’ > < leftOperand > < variable name = ’y ’ </ leftOperand > < rightOperand > < unaryOperation operator = ’ - ’ > < operand > < float value = ’ 3.14 ’/ > </ rightOperand > </ operand > </ unaryOperation > </ b in aryOperation > </ condition > < consequence > < invocation > < function > < variable name = ’ print ’/ > </ function > < arguments > . . . Si le programme est validé vis-à-vis la grammaire, il sera réifié en DOM (Document Object Model). 29/64 Cours 1 DOM Interface DOM L’interface DOM (pour Document Object Model) lit le document XML et le convertit entièrement en un arbre (en fait un graphe modifiable). DOM est une interface, il faut lui adjoindre une implantation et, pour XML, il faut adjoindre un analyseur syntaxique (pour parser) 30/64 Cours 1 DOM Verification Paquetage org.w3c.dom.* Implantations : javax.xml.parsers.*, org.xml.sax.* RelaxNG : com.thaiopensource.validate.ValidationDriver; public IASTprogram getProgram () throws Pa rseExc eption { try { final String programText = input . getText (); final String rngFilePath = rngFile . g et A bs o lu te P at h (); final InputSource isg = V a l i d a t i o n D r i v e r . fi l eI np u tS ou r ce ( rngFilePath ); final V al i dat ion Dri ver vd = new V a l i d a t i o n D r i v e r (); vd . loadSchema ( isg ); InputSource is = new InputSource ( new StringReader ( programText )); if ( ! vd . validate ( is ) ) { throw new P arseExceptio n ( " Invalid XML program ! " ); } ... } 31/64 Cours 1 DOM Conversion à DOM public IASTprogram getProgram () throws Pa rseExc eption { try { ... final D o c u m e n t B u i l d e r F a c t o r y dbf = D o c u m e n t B u i l d e r F a c t o r y . newInstance (); final Docu men t Bu il d er db = dbf . n e w D o c u m e n t B u i l d e r (); // the previous value of is is totally drained ! is = new InputSource ( new StringReader ( programText )); final Document document = db . parse ( is ); ... } catch ( ParseE xcepti on e ) { throw e ; } catch ( Exception e ) { throw new Pa rseExc eption ( e ); } } 32/64 Cours 1 DOM Les interfaces du DOM org.w3c.dom.Document org.w3c.dom.Node org.w3c.dom.Element org.w3c.dom.CharacterData org.w3c.dom.NodeList 33/64 Cours 1 DOM Arpentage du DOM org.w3c.dom.Document Element getDocumentElement (); org.w3c.dom.Node Node . uneCONSTANTE getNodeType (); // avec Node . DOCUMENT_NODE , Node . ELEMENT_NODE , // Node . TEXT_NODE ... NodeList getChildNodes (); org.w3c.dom.Element hérite de Node String getTagName (); String getAttribute ( " attributeName " ); org.w3c.dom.Text hérite de Node String getData (); org.w3c.dom.NodeList int getLength (); Node item ( int ); 34/64 Cours 1 DOM Variations autour du DOM attention au découpage des textes, aux blancs superflus, <a b = ’c ’ > </ a > <a b = ’c ’ > </ a > attention à la présence de commentaires, instructions de traitement <a > <b > text1 <! -- comment -- > text2 </ b > </ a > 35/64 Cours 1 DOM Du bon emploi de XML XML favorise l’auto-description avec des balises signifiantes Ne pas employer d’attributs là où une certaine extensibilité est envisagée ou là où ne peut être contenue l’information souhaitée. XML cherche à minimiser les efforts d’analyse (d’où l’intérêt des conteneurs) < point > <x >1 </ x > <y >2 </ y > </ point > < ligne > < characteristics color = ’ blue ’ / > < points > < point > .. </ point > < point > .. </ point > </ points > </ ligne > < point x = ’1 ’ y = ’2 ’/ > < ligne > < point > .. </ point > < characteristics ../ > < point > .. </ point > .. </ ligne > 36/64 Cours 1 Sémantique Sémantique discursive Langage non typé statiquement : les variables n’ont pas de type Langage sûr, typé dynamiquement : toute valeur a un type (donc de la classe de Scheme, Javascript, Smalltalk) Langage à instruction (séquence, alternative, bloc unaire) Toute expression est une instruction Les expressions sont des constantes, des variables, des opérations ou des appels de fonctions (des invocations). 37/64 Cours 1 Sémantique Détails sémantiques Opérateurs unaires : - (opposé) et ! (négation) Opérateurs binaires : arithmétiques : + (sur nombres et chaînes), -, *, /, % (sur entiers), comparateurs arithmétiques : <, <=, >, >=, comparateurs généraux : ==, <>, != (autre graphie), booléens : |, &, ^. Variables globales prédéfinies : fonctions primitives : print et newline (leur résultat est indéfini) ou constantes comme pi. Le nom d’une variable ne peut débuter par ilp ou ILP. L’alternative est binaire ou ternaire (l’alternant est facultatif). La séquence contient au moins un terme. 38/64 AST AST DOM est une façon simple de réifier un document XML (quelques lignes de programme), mais il est peu adapté à la manipulation d’arbres de syntaxe AST (pour Abstract Syntax Tree) car il est non typé, trop coûteux, mal extensible. Une fois le DOM obtenu, on le transforme en un AST. NOTA : on aurait pu passer directement de la syntaxe concrète à l’AST. 39/64 AST Grand schéma javaCC, sableCC, CUP, ANTLR source syntaxe Scheme source syntaxe XML source syntaxe concrète source DOM jaxb, castor XStream, xmlBeans source AST Transformations, optimisations AST2 texte C a.out AST resultat gcc 40/64 AST IAST Le paquetage com.paracamplus.ilp1.interfaces fournit une interface pour chaque concept syntaxique : IAST IASTalternative IASTconstant IASTboolean IASTinteger IASTfloat IASTstring IASTinvocation IASToperation IA STun ary Op er ati on IAS T bi n a ry O per a ti o n IASTsequence IASTBlock IASTvariable IASTprogram 41/64 AST Alternative D’un point de vue syntaxique, une alternative est une entité ayant trois composants dont un optionnel : alternative = element alternative { element condition { expression } , element consequence { instructions } , element alternant { instructions } ? } 42/64 AST IASTalternative package com . paracamplus . ilp1 . interfaces ; public interface IASTalternative extends IAST { IASTexpression getCondition (); IASTexpression getConsequence (); @OrNull IASTexpression getAlternant (); /* * Indique si l ’ alternative est ternaire . */ boolean isTernary (); } Interfaces décalquables de la grammaire ! Pourquoi ? Pour dissocier les interfaces des implantations afin de permettre d’autres analyseurs syntaxiques 43/64 AST Hiérarchies IAST implante AST hérite IASTalternative IASToperation IASTinvocation ASTalternative ASToperation ASTinvocation ASTinvocationPrimitive 44/64 AST AST Les classes dans le package com.paracamplus.ilp1.ast implantent les interfaces respectives dans com.paracamplus.ilp1.interfaces. AST implante IAST ASTalternative implante IASTalternative ASTBlock implante IASTBlock ASTboolean implante IASTboolean ASTstring implante IASTstring ASTinteger implante IASTinteger ASTfloat implante IASTfloat ASTinvocation implante IASTinvocation ASToperation implante IASToperation ASTun aryOpera tion implante IAS Tu na ryOperation AS Tbin ary Op er ati on implante IA S Tb i n aryOperation ASTsequence implante IASTsequence ASTvariable implante IASTvariable 45/64 AST ASTalternative package com . paracamplus . ilp1 . ast ; import com . paracamplus . ilp1 . annotation . OrNull ; import com . paracamplus . ilp1 . interfaces . IASTalternative ; import com . paracamplus . ilp1 . interfaces . IASTexpression ; public class ASTalternative extends ASTexpression implements IASTalternative { public ASTalternative ( IASTexpression condition , IASTexpression consequence , IASTexpression alternant ) { this . condition = condition ; this . consequence = consequence ; this . alternant = alternant ; } 46/64 AST private final IASTexpression condition ; private final IASTexpression consequence ; private @OrNull final IASTexpression alterna public IASTexpression getCondition () { return condition ; } public IASTexpression getConsequence () { return consequence ; } public IASTexpression getAlternant () { return alternant ; } public boolean isTernary () { return this . alternant != null ; 47/64 AST Conversion DOM vers AST public IASTprogram getProgram () throws ParseException { try { ... Validation } ... XML to DOM final Document document = db . parse ( is ); IASTprogram program = parse ( document ); return program ; } catch ( ParseException e ) { throw e ; } catch ( Exception e ) { throw new ParseException ( e ); } } 48/64 AST La classe Parser La conversion est effectuée par la méthode parse(Node) de la classe Parser : package com . paracamplus . ilp1 . ast ; public class Parser extends A b s t r a c t E x t e n s i b l e P a r s e r { public Parser ( IParse rFacto ry factory ) { super ( factory ); addMethod ( " alternative " , Parser . class ); addMethod ( " sequence " , Parser . class ); addMethod ( " in t eg er C on st a nt " , Parser . class , " integer " ); addMethod ( " floatConstant " , Parser . class , " float " ); addMethod ( " st ringCo nstant " , Parser . class , " string " ); addMethod ( " bo o le an C on st a nt " , Parser . class , " boolean " ); addMethod ( " un aryOpe ration " , Parser . class ); addMethod ( " bi n ar yO p er at i on " , Parser . class ); addMethod ( " block " , Parser . class ); addMethod ( " binding " , Parser . class ); addMethod ( " variable " , Parser . class ); addMethod ( " invocation " , Parser . class ); } 49/64 AST public abstract class A b s t r a c t E x t e n s i b l e P a r s e r extends Ab stract Parser public A b s t r a c t E x t e n s i b l e P a r s e r ( IPa rserFa ctory factory ) { super ( factory ); this . parsers = new HashMap < >(); } private final HashMap < String , Method > parsers ; public void addParser ( String name , Method method ) { this . parsers . put ( name , method ); } public void addMethod ( String name , Class <? > clazz ) { addParser ( name , findMethod ( name , clazz )); } public void addMethod ( String name , Class <? > clazz , String tagName ) { addParser ( tagName , findMethod ( name , clazz )); } 50/64 AST public Method findMethod ( String name , Class <? > clazz ) { try { for ( Method m : clazz . getMethods () ) { if ( ! name . equals ( m . getName ()) ) { continue ; } if ( Modifier . isStatic ( m . getModifiers ()) ) { continue ; } Class <? >[] par ameter Types = m . g e t P a r a m e t e r T y p e s (); if ( param eterTy pes . length != 1 ) { continue ; } if ( ! Element . class . i s A s s i g n a b l e F r o m ( par ameter Types [0]) continue ; } return m ; } if ( Object . class == clazz ) { final String msg = " Cannot find suitable parsing method ! throw new R u n t i m e E x c e p t i o n ( msg ); } else { return findMethod ( name , clazz . getSuperclass ()); } } catch ( S e c u r i t y E x c e p t i o n e1 ) { final String msg = " Cannot access parsing method ! " ; 51/64 throw new R u n t i m e E x c e p t i o n ( msg );}} AST public IAST parse ( final Node n ) throws Parse Except ion { switch ( n . getNodeType () ) { case Node . ELEMENT_NODE : { final Element e = ( Element ) n ; final String name = e . getTagName (); if ( parsers . containsKey ( name ) ) { final Method method = parsers . get ( name ); try { Object result = method . invoke ( this , new Object []{ e }); if ( result != null && result instanceof IAST ) { return ( IAST ) result ; } else { final String msg = " Not an IAST " + result ; throw new Pa rseExc eption ( msg ); } } catch ( I l l e g a l A r g u m e n t E x c e p t i o n exc ) { ... } catch ( I l l e g a l A c c e s s E x c e p t i o n exc ) { ... } catch ( I n v o c a t i o n T a r g e t E x c e p t i o n exc ) { ... } } else { final String msg = " Unknown element name : " + name ; throw new Pa rseExc eption ( msg ); } } default : { final String msg = " Unknown node type : " 52/64 AST Méthode pour l’alternative public IAST expres sion alternative ( Element e ) throws Pars eExcep tion { IAST iastc = f i n d T h e n P a r s e C h i l d C o n t e n t (e , " condition " ); IAST expres sion condition = n a r r o w T o I A S T e x p r e s s i o n ( iastc ); IAST expres sion [] iaste = f i n d T h e n P a r s e C h i l d A s E x p r e s s i o n s (e , " consequence " ); IAST expres sion consequence = getFactory (). newSequence ( iaste ); try { IAST expres sion [] iasta = f i n d T h e n P a r s e C h i l d A s E x p r e s s i o n s (e , " alternant " ); IAST expres sion alternant = getFactory (). newSequence ( iasta ); return getFactory (). new Altern ative ( condition , consequence , alternant ); } catch ( P arseEx ceptio n exc ) { return getFactory (). new Altern ative ( condition , consequence , null ); } } 53/64 AST Récapitulation syntaxe d’ILP1 (grammaire RelaxNG, XML, IAST) représentation d’un programme ILP1 (AST) RelaxNG, DOM, XML 54/64 AST Grand schéma javaCC, sableCC, CUP, ANTLR source syntaxe Scheme source syntaxe XML source syntaxe concrète source DOM jaxb, castor XStream, xmlBeans source AST Transformations, optimisations AST2 texte C a.out AST resultat gcc 55/64 AST Bibliographie Cours de C http://www-ari.ufr-info-p6.jussieu.fr/ RESSOURCES/doc/cederoms/Videoc2000/ Cours de Java http://www.pps.jussieu.fr/~emmanuel/Public/ enseignement/JAVA/SJP.pdf developper en java avec Eclipse http://www.jmdoudoux.fr/java/dejae/ (500 pages) Cours sur XML http://apiacoa.free.fr/teaching/xml/ RelaxNG http: //www.oasis-open.org/committees/relax-ng/tutorial.html ou le livre « Relax NG » d’Éric Van der Vlist, O’Reilly 2003. 56/64 AST Tests Tests Tests avec JUnit3 Cf. http://www.junit.org/ package com . paracamplus . ilp1 . tools . test ; import junit . framework . TestCase ; import com . paracamplus . ilp1 . tools . ProgramCaller ; public class ProgramCallerTest extends TestCase { public void t e s t P r o g r a m Ca l l er I n ex i s t e n t V er b o s e () { final String programName = " lasdljsdfousadfl lsjd " ; ProgramCaller pc = new ProgramCaller ( programName ); assertNotNull ( pc ); pc . setVerbose (); pc . run (); assertTrue ( pc . getExitValue () != 0); } 57/64 AST Tests Séquencement JUnit3 Pour une classe de tests SomeTest : 1 2 charger la classe de test SomeTest pour chaque méthode nommée testX, 1 2 3 4 instancier la classe de test SomeTest tourner setUp() tourner testX tourner tearDown() 58/64 AST Tests JUnit 4 Les tests ne sont plus déclarés par héritage mais par annotation (cf. aussi TestNG). Les annotations sont (sur les méthodes) : @BeforeClass @Before @Test @Test ( expected = Exception . class ) @After @AfterClass et quelques autres comme (sur les classes) : @RunWith @SuiteClasses @Parameters 59/64 AST Tests Séquencement JUnit4 Pour une classe de tests Foobar : 1 charger la classe Foobar 2 tourner toutes les methodes @BeforeClass pour chaque méthode annotée @Test, 3 1 2 3 4 4 instancier la classe Foobar tourner toutes les méthodes @Before tourner la méthode testée tourner toutes les méthodes @After enfin, tourner toutes les methodes @AfterClass 60/64 AST Tests Annotations Les annotations sont des métadonnées dans le code source originalement en JAVA avec Javadoc annotations connues : @Deprecated, @Override, ... annotations multi paramétrées : @Annotation(arg1="val1", arg2="val2", ... ) Utilisations des annotations : par le compilateur pour détecter des erreurs pour la documentation pour la génération de code pour la génération de fichiers Avec les annotations le code source est parcouru mais il n’est pas modifié. 61/64 AST Tests Définition d’une annotation public @interface MyAnnotation { int arg1 () default 4; String arg2 (); } @MyAnnotation ( arg1 =0 , arg2 = " valeur2 " ) public class UneCLasse { ... } 62/64 AST Tests Les annotations des annotations @Target ({ ElementType . METHOD , ElementType . CONSTRUCTOR }) @Retention ( RetentionPolicy . RUNTIME ) @Inherited public @interface MyAnnotation { int arg1 () default 4; String arg2 (); } Pour l’annotation @Retention : RetentionPolicy.SOURCE : dans le code source uniquement (ignorée par le compilateur) RetentionPolicy.CLASS : dans le code source et le bytecode (fichier .java et .class) RetentionPolicy.RUNTIME : dans le code source et le bytecode et pendant l’exécution par introspection 63/64 AST Tests Les annotations pendant l’exécution La pluspart des méta-objets implémentent java.lang.reflect.AnnotatedElement : boolean isAnnotationPresent(Class<? extends Annotation>) : True si le méta-objet est annoté avec le type du paramètre <T extends Annotation> getAnnotation(Class<T>) : renvoie l’annotation de type T ou null Annotation[] getAnnotations() : renvoie la liste des annotations Annotation[] getDeclaredAnnotations() : renvoie la liste des annotations directes (pas les heritées) 64/64