Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
1
Outils de Tests d'Interface
a) Plateformes de tests : JUnit, PHPUnit, Qunit
b) Outils de qualité : sonar
c) Selenium
d) Outils de déploiement : maven
http://www.fil.univ-lille1.fr/~bilasco/OTI/OTI2014a.pdf
2
Tests
● Les tests assurent
– qualité du code : fiable, robuste
– tests de régression fréquents
– retour d'expérience rapide
– identification des problèmes rares et/ou non testé manuellement
– documentation : exemples fonctionnels
● A quel prix ? Quand est-ce qu'on en écrit ?
● Séparation entre code tests et code métier
– code défi ni, développé et livré séparément des tests● src/ vs test/
3
Tests
Dans un cadre collaboratif code écrit 1 fois, répliqué n fois
Dans un cadre Agile itérations courtes, documentées par les tests
eXtreme Programming (XP) / Test Driven Development développer les tests unitaires en même temps/avant le
programme à tester à partir des spécifi cations on n'écrit que le code nécessaire à valider les tests
… en TP ?
4
Tests
Qu'est-ce … et comment écrire des Tests unitaires ?http://fr.wikipedia.org/wiki/Test_%28informatique%29http://fr.wikipedia.org/wiki/Test_unitairehttp://portail.fi l.univ-lille1.fr/portail/index.php?dipl=MInfo&sem=S8&ue=SVL
Tests pour les applications connectées
Code métier
BD
Interface & Interactions
Code
T. Interface
T. Métier T. Métier
5
● Outils pour tests unitaires : – JUnit 4.0– PHPUnit, SimpleTest– QUnit JS, Jasmine, Buster.JS, jstestdriver ...
● Outils pour tests interface utilisateur : – Selenium
● Exercices (rendus à la fi n de séances / module)● Evaluations
– Couverture de tests pour l'application WebA
6
Organisation générique des tests
Code
- classes- méthodes
Ou
- modules- fonctions/procédures
Test Case A
- tests - par fonctionnalités
- par méthode/fonction- par contexte d'usage
AssertionsEchecs
Test Case B
- tests - par fonctionnalités
- par méthode/fonction- par contexte d'usage
AssertionsEchecs
Test suite
7
Un Cas de Test - Principe général
● Hypothèse
– configuration de l'état de départ du système● Actions (testées)
– transformation sur l'état du système● Résultat attendu
– vérification de l'état attendu (assert)
– production d'une exception
8
Tests – JUnitorg.junit.* (JUnit 4.0)
Interface : Test
Classes : (J4.0) Toute classe contenant @org.junit.Test
(J4.0) @org.junit.runners.Suite
Assert (méthodes assertXXX() et failZZZ()) - JSONAssert de net.sf.json.tests → asserts pour JSONObject, JSONArray
Méthodes
@Test or @Test(expected=Exc.class) void yyy() {...} (Test.)assertXXX(...) - True, False, Equal @Before{Class} – init. des objets auxiliaires par test/classe
@After{Class} - relâche les objets auxiliaires @Suite.SuiteClasses({ MyT.class })
9
Exemple JUnit 4.x - Assert
import org.junit.*;
public class MoneyTest { //Construire un nouveau test case
private Money f12EUR, f14EUR;
@BeforeClass /* or Before – each Test */
protected void init() { //Construction de objets tests
f12EUR = new Money(12,"EUR");
f14EUR = new Money(14,"EUR");
}
@Test
public void simpleAdd () { //Une des méthodes de test
Money expected = new Money(26,"EUR");
Money result= f12EUR.add(f14EUR);
assertTrue(expected.equals(result));
}
} .
10
Exemple JUnit 4.x - Exception
import org.junit.*;
public class MoneyTest { //Construire un nouveau test case
private Money f12EUR, f14EUR;
@BeforeClass /* or Before – each Test */
protected void init() { //Construction de objets tests
f12EUR = new Money(12,"EUR");
f14EUR = new Money(14,"EUR");
}
@Test(expected=SubImpossibleException.class,timeout=msTimeoutValue)
public void simpleSubImpossible () { //Une des méthodes de test
Money result= f12EUR.add(f14EUR);
}
} .
11
Suites de tests - JUnit
Organiser/Composer/Regrouper plusieurs Tests JU 3.8 : TestSuite TestSuite suite = new TestSuite("MoneyTestSuite"); suite.addTestSuite(MoneyTest.class); //ajout de tous les tests suite.addTest(new AnotherMoneyTest("testOtherMoneyMethodName");
//ajout de tests spécifi ques JU 4.0 : Suite @RunWith(Suite.class) @SuiteClasses({MoneyTest.class,AnotherMoneyTest.class})
class AllTests {} ;;
RepeatedTest (JU3.8) Performance ou erreur intermittente suite.addTest(new RepeatedTest(new MoneyTest("testSimpleAdd"),100)); suite.addTest(new RepeatedTest(new MoneyTest("testComplexAdd"),100));
12
JUnit Exercices
● http://forge.fil.univ-lille1.fr/OTI/wiki/JUnitExo
● http://forge.fil.univ-lille1.fr/OTI/wiki/JUnit4Exo
MoneyFactory.class
::+getDefaultFactory+createMoney
Money.class
- Money+getValue +getCurrency
+toString
MoneyOps.class
:: +simpleAdd
IncompatibleCurrenciesException.class
UnexistingCurrencyException.class
MoneyAddTestCase.class
+testSimpleAdd
MoneySameCurrTest.class
+testSame+testNotSame
MoneyEqTest.class
+testMemeValeurMemeDevise+testMemeValeurDeviseDifff//
13
Outils de Tests d'Interface
a) Plateformes de tests : JUnit, PHPUnit, Qunit
b) Outils de qualité : sonar
c) Selenium
d) Outils de déploiement : maven
http://www.fil.univ-lille1.fr/~bilasco/OTI/OTI2014a.pdf
14
Tests Unitaires pour Javascript
● Une grande variété de plateformes de tests JS– http://en.wikipedia.org/w/index.php?title=List_of_unit_testing_frameworks§ion=32#JavaScript
● Restructurer votre code en vue de mettre en place de tests
– Séparer la partie fonctionnelle/métier ...
– … de la partie rendu (modification DOM, alertes, etc.)
– Organisez-le en fonctions indépendamment testables
– Un exemple de restructuration : http://qunitjs.com/intro/
15
Tests Unitaires pour Javascript
● Réfléchir à la séparation entre tests clients et tests serveurs
– Tests unitaire JS (client) vs Tests unitaires Java/PHPUnit (serveur)
Code métier
BD
Interface & Interactions
Code
T. Interface
T. Métier T. Métier
16
QUnit by JQueryhttp://code.jquery.com/qunit/qunit-1.12.0.csshttp://code.jquery.com/qunit/qunit-1.12.0.js
● Tests et reports matérialisés dans des pages HTML
● TestCases
– Synchrones : test (nom[, nbr_tests], funcDef)
– Asynchronnes : asyncTest(nom, [nbr_tests,] funcDef)
● stop() puis setTimeout() sur appel bloquant puis start()
– Structurées: module(nomMod, setup : funcDef, tearDown : funcDef)
● module("suiteA", setup:function(){...}, teardown:function(){…})● asyncTest("testA1", function() {...})● test("testA2",3,function() {...}) ← ici sont attendues 3 assertions
● TestSuites (qunit-composite.js sur github.com)
– QUnit.testSuites(["moduleA.html", "moduleB.html"]);
17
QUnit – test & throwsexemples
test("test accesseurs", 2, function(){
var m=new money(1,"EUR");ok(m.getValue()==1,"valeur = 1");equal(m.getCurrency(),"EUR","currency = EUR");
});
test("test simple ops", 2, function(){ var m1=new money(1,"EUR"); var m2=new money(2,"EUR"); var m3=new money(3,"EUR"); ok(m3.equals(MoneyOps.add(m1,m2)),"3e = 1e+2e");});
test("test multi devise add", 1, function(){
var m1=new money(1,"EUR"); var m2=new money(2,"CHF"); throws(function() {var m3=MoneyOps.add(m1,m2)},
DevisesIncompatibleExc, "Devises Incompatibles");});
18
QUnit – tests and Ajax … the wrong way
module("async");
test("start",function(){ ok(true); });
test("connect using Ajax",function(){ var xmlhttp=new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { equal(xmlhttp.responseText,10); console.log("recieved "+xmlhttp.responseText); } } xmlhttp.open("GET","random.php",true); xmlhttp.send();});
test("end",function( ){ ok(true); });
<?phpsleep ( rand ( 2, 4));echo rand (9,11);?> random.php
http://www.fil.univ-lille1.fr/~bilasco/OTI/random_test_NS.htmlhttp://www.fil.univ-lille1.fr/~bilasco/OTI/random_test_NS.js
19
QUnit – tests and Ajax
module("async");
test("start",function(){ ok(true); });
test("connect using Ajax",function(){ var xmlhttp=new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { equal(xmlhttp.responseText,10); console.log("recieved "+xmlhttp.responseText);
QUnit.start(); } } xmlhttp.open("GET","random.php",true); xmlhttp.send(); QUnit.stop() ;});
test("end",function( ){ ok(true); });
<?phpsleep ( rand ( 2, 4));echo rand (9,11);?> random.php
http://www.fil.univ-lille1.fr/~bilasco/OTI/random_test_NS2.htmlhttp://www.fil.univ-lille1.fr/~bilasco/OTI/random_test_NS2.js
20
QUnit – asynchronous tests et Ajax
module("async");
test("start",function(){ ok(true); });
asyncTest("connect using Ajax",function(){ //implicit QUnit.stop() var xmlhttp=new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { equal(xmlhttp.responseText,10); console.log("recieved "+xmlhttp.responseText); QUnit.start(); } } xmlhttp.open("GET","random.php",true); xmlhttp.send();});
test("end",function( ){ ok(true); });
<?phpsleep ( rand ( 2, 4));echo rand (9,11);?> random.php
http://www.fil.univ-lille1.fr/~bilasco/OTI/random_test.htmlhttp://www.fil.univ-lille1.fr/~bilasco/OTI/random_test.js
21
QUnit by JQueryhttp://code.jquery.com/qunit/qunit-1.12.0.csshttp://code.jquery.com/qunit/qunit-1.12.0.js
● Assertions
– ok(param[,msg]) – test passé si paramètre param true
● ok (1==1,"1 est tjs égal à 1") ;
– [strict|deep}equal(result,expected[,msg]) – test passé si paramètres {strictement (type et valeur) / structurellement } égaux
● strictEqual(1=="1","jamais ça marchera") ;● equal(1=="1","la rigueur c'est pas pour nous") ;
– throws(funcDef,expected[,msg]) – test passé si expected lancée
● throws(function(){throw "oups"},"oups","oups c'est passé")
22
QUnit by Jquery
● Page HTML de test QUnit
– inclusion de scripts src
– inclusion de scripts tests
● Résultats et données dans des divs prédéfinies
– id='qunit' – affichage des résultats
– id='qunit-fixture' – inclusion des éléments (champs, etc.) servant de support pour la réalisation des tests
● Utilise le trigger de jQuery pour simuler les interactions– .trigger( eventType [, extraParameters] )
23
Qunit - exemplequnit.js + qunit.css
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.12.0.css" /><script src="http://code.jquery.com/qunit/qunit-1.12.0.js"></script><script src="../src/money.js"></script><script src="../test/money_test.js"></script></head><body><div id="qunit"/><div id="qunit-fixture"/></body></html>
module("money", {// setup:function(){alert("setup money");},// teardown:function(){alert("teardown money");}});
test("test accesseurs", 2, function(){
var m=new money(1,"EUR");ok(m.getValue()==1,"valeur = 1");equal(m.getCurrency(),"EUR","currency = EUR");
});
24
Test unitaires – Exos 1
● QUnit
● Commencer à réfléchir à comment mettre en place les tests sur votre projet WebA
money.js
money(v,curr)getValue
getCurrrencyequals
money_ops.js
money(v,curr)getValue
getCurrrencyequals
money_exc.js
DevisesIncompatibleExc
money_test.js
constructoraccesseurs
equals
money_test.html
money_ops_test.js
simpleAddmultiDevise
money_ops_test.html
money_test_suite.js
money_test.htmlmoney_ops_test.html
money_test_suite.html
25
Retours
● « // throw new Exception » (this.d1 + " " + this.d2)
● « Le test c'est bien mais la console c'est mieux »– try { ... } catch (e) {console.log(e.toString());}
● «Ca y est, un test ca suffit »– var f=new factory(); ok(f.cur.length==2,"nb = 2"); equal(f.cur[0],"EUR","");
– var m1=f.create(1,"E") ; var m2=f.create(2,"E") ; equal(f.crees["E"]=3);
● «Un test en plus ne fait pas de mal »MoneyFactory.prototype.create = function (value, currency) { if (this.currencies.indexOf(currency.toUpperCase()) == -1) throw new Exc(); return new money( value, currency );}test("test create", function(){ throws(function() {var m = this.fact.create(1, "YEN")}, .., "Devise Inexistante"); throws(function() {var m = this.fact.create(-1, "EUR")}, ...,"Monnaie Négative");});
26
● « Je me fâche avec personne »– ok(m1.getValue()<"0","Negatif") ;
– If (v<0) alert 'Attention' ;
– default : this.moneyClass = mFactory.Euro;
● « Je suis généreux»– m1 = new Money(1, "EUR") ; m1.setValue(100) ;
● « Tant que j'utilise pas mes sous c'est pas grave »– this.curr=curr ; et puis test sur currency en Money_Ops
● « Egocentric »– throw new MonPropreEx
27
QUnit
● Tests sur le comportement métier des scripts
● Tests sur le comportement de l'interface
– changements dans le DOM
– apparition des alertes
28
QUnit et DOM
● Les tests s'exécutent au sein d'une page ← contexte DOM
● Isoler le contexte DOM associé dans le div id=qunit-fixtures
● Avant chaque tests construire les fixtures
– réfletant l'état du DOM suite aux actions de l'utilisateur var fixture=""; fixture+=("<div id='res'></div>"); fixture+=("<form id='form0'>"); fixture+=("<input type='text' id='v1' name='v1' value='2'/>"); fixture+=("<input type='text' id='c1' name='c1' value='EU'/>"); … var fixtureNode=document.getElementById("qunit-fixture"); fixtureNode.innerHTML=fixture; … c.computeResult(document.getElementById('form0'));
equal(c.message,"...") ;
29
QUnit et (window.)alert
● Pas d'assertion spécifique pour traiter les alertes
● Redéfinir la fonction window.alert
● Garder une trace dans le div qunit-fixtures
...
30
Test unitaires – Exos 2
● QUnit et fixtures
index.html
div resform
calc.js
calc()computeResult(form)
displayResult(div)
calc_test.js
test computeResulttest outputResult
Utilisation de fixtures
var fixture="" ;fixture+="<div id='res'>.." ;fixture+="<form..>" ;fixture+="<input ..>" ;…document.getElementById
("qunit-fixture").innerHTML=fixture
31
Outils de Tests d'Interface
a) Plateformes de tests : JUnit, PHPUnit, Qunit
b) Outils de qualité : sonar
c) Selenium
d) Outils de déploiement : maven
http://www.fil.univ-lille1.fr/~bilasco/OTI/OTI2014a.pdf
32
SONAR
● Outil pour mesurer la qualité du code
33
SONAR
● Analyser le code (sonar-runner)
– Structure
– Convention de Codage
– Couverture et Tests
–
● Archivage des informations (sonarQube)
– Rapports
– Evolution de la qualité
–
● Solution générique
– plugins par langage et par fonctionnalité
SonarQube
R1 R2
sonar runner
plugins
outils externes
34
Sonar et JS
● Plugin SonarQube Javascript disponible
– n'extrait pas directement les données de couverture de tests
● Exécuter les tests JS en ligne de commande + récupérer résultats
– utiliser JsTestDriver (1.3.5) – un autre framework de tests JS
– serveur prenant la main sur un ou plusieurs navigateurs
– QUnitAdapter – fonctionnalités minimales (test, ok)
– configuration du projet (jsTestDrive.conf)
● Récupération des informations de « coverage » (1.3.5)
● Alimenter SonarQube en utilisant sonar-runner
35
JsTestDriver et QunitAdapter
● QUnit.test → QUnitTestCase extends (Js)TestCase
● ok -> assertTrue
● + equal
● + throws
● + fixtures
36
Sonar - exercices
● Travail sur le projet Money_JS
– Installer SonarQube
– Configurer sonar-project.properties (runner->qube)
– Lancer Analyse
– Installer JsTestDriver
– Configurer jsTestDriver.conf
– Lancer Analyser / Récupérer informations sur les tests
– Faire évoluer votre code
– Re-lancer l'analyser
37
Sonar - exercices
● Travail sur le projet Money_Java
– Installer SonarQube
– Configurer sonar-project.properties (runner->qube)
– Lancer Analyse
– Configurer Maven
– Lancer Analyser / Récupérer informations sur les tests
– Faire évoluer votre code
– Re-lancer l'analyseur
38
Selenium – Tests UIhttp://seleniumhq.org/docs/
● Selenium automates browsers.
● Initialement conçu pour réaliser des tests dans les applis Web
– Interaction à travers les pages d'un navigateur
– Clique/Ecrit/Valide/Interagit/Constate à ma place● Construire des macros visuels pour la maintenance
● Formalisme pour décrire les actions simulées
● Formalisme pour constater/mésuser les effets des actions
– sur la page (modifications du DOM)
– ou dans l'interaction (alertes ...)
39
Selenium – une famille de solutions
● Selenium IDE
– Plugin navigateur pour enregistrer/exécuter les scénarios de tests
– Création des tests rapides
– Reproduire des bugs
– Absence de logs, metrics
● Selenium WebDriver
– Tests robustes en vue d'automatiser l'étude de la régression
– Passage à l’échelle des tests
– Clients en Java, C#, Python, Ruby, PHP, Javascript
40
Selenium IDE Commandes (ou Selenese)
● Enregistrer des Actions
– Ouvrir une page (open)
– Saisir un texte (type)
– Cliquer (click*)
– Choisir options (select*)
● Accessors pour le contenu
● Assertions des effets sur
– le contenu du document
– les propriétés des éléments
– les fenêtres du navigateur
● 1 Script = actions + assertions
41
Selenium IDE – Commandes et suites
● Une commande selenese est composée de :
– Action : ensemble prédéfini des types de commandes
– Locator : comment identifier/référencer l'élément concerné
● id, xpath, css
– Value : paramètre de la commande
● Un encodage HTML pour l'instant
● Assembler les commandes dans un test case (.html)
– <table> dont les lignes sont des commandes
– <tr> commande et <td> éléments de la commande● Assembler les tests cases en tests suite
– <table> dont les lignes sont des liens vers tests cases
42
Selenium UI – Référencement des élémentsLocators
● Référencer les éléments concernées par les actions
● Par id: id = elementID (attribut id requis sur les éléments à référencer)● Par name: name = elementNom (attribut name requis)● Par identifier: identifier=formNOMouID (par id et puis par name)● Par XPath: xpath=/html/body/form0/input[3], xpath=//form/input[@id='x']● Par link: link=Texte_Entre_<A>_et_</A>● Par DOM: dom=document.getElementById('myForm')● Par CSS: css=#loginForm input[type="button"] (4)
● Adaptez vous à la nature du document testé
● Choisissez des références robustes aux changements dans la page – limitez les contraintes de localisation dans le code
43
Selenium UI – Actionshttp://release.seleniumhq.org/selenium-core/1.0/reference.html#actions
● Interactions
– Souris : {double/}click{/At}, mouseMove{/At}, dragAndDrop{/ToObject} ...
– Clavier : keyPressed,{alt/control}Key{Up/Down}, type …
● Formulaires : select(selectLocator,labelLocator)
● Fenêtres et PopUp
– Ouverture: openWindow, select{Window,Frame,PopUp}
– Interaction: choose{Cancel/OK}OnNextConfirmation, deselectPopUp
● Scripts : addScripts
● Interactions+temps d'arrêt pour rechargement : XXXAndWait
– À éviter en présence d'AJAX
<tr><td>clickAndWait</td><td>id=nextPageBtn</td><td></td></tr>
44
Selenium UI - Actions
● Stockage et Variables
– storeXXX{/Present/NotPresent}, storeEval
<tr><td>storeText</td><td>id=login</td><td>lg</td></tr>
<tr><td>storeEval</td><td>storedVars['lg'].toUpperCase()</td><td>M</td></tr>
● Validation
– assertXXX{/Present/NotPresent} → le test s'arrête définitivement
– verifyXXX → test continue, notification de l'échec
– waitForXXX → le script attend qu'un état soit observé (support AJAX)
45
Selenium UI - Exemple
Addition Test
open ~bilasco/MoneyMoneyMoney/index.php
type name=v1 12
type name=c1 EUR
type name=v2 12
type name=c2 EUR
clickAndWait css=input[type="submit"]
assertText id=ops ADD
assertText id=result_detail (EUR) 24
v1
v2
d1
d2
ops
result_detail
46
Selenium WebDriver
● Construire de tests d'intégration automatisé à base d'API
– s'abstraire d'un navigateur spécifique
– automatiser exécution
– structures de contrôle
● Navigateur supportés
– Safari, InternetExplorer, Firefox, Opera, Chrome
● Dispositifs d'accès
– Desktop, Android, Iphone
● API décliné en
– java, c#, python, ruby, php, perl, javascript
47
Selenium TestsAPI.java
SeleniumWeb Driver
server
Android Chrome Firefox
Actions Créer WebDriverExécuter Selenesse
InformerSignaler
Selenium TestsAPI.php
Selenium TestsAPI.js
RemoteWebDrivers
48
Selenium WebDriver – APIorg.openqa.selenium.*
● Navigateur générique : RemoteWebDriver
● Navigateur spécifique : selenium.{nomnavigateur}
– classes spécifiques pour interaction avec navigateur spécifique
● Interactions simples et complexes : selenium.interactions
– ClickAction,ClickAndHold,ContextClick,DoubleClick,...
– KeyDownAction,KeyUpAction,SendKeys
– touch.*
– CompositeAction
● Localisation des élements : Interface Locators
– selenium.internals
● FindsBy{ClassName,CssSelector,Id,LinkText,Name,TagName,XPath}
●
49
Selenium Web Driver - RemoteWebDriver
● Capabilities – un sac de CapabilityType
– startSession(Capabilities)/stopSession() ● Chargement page : get(String adresseWeb)
● Naviguer navigate()
– back(),forward(),refresh(),to()
– switchTo().{alert(),frame(name),window(name)}● Executer scripts
– execute{Async}Script(String script, Object... args)
● Contrôle de la souris/clavier getKeyboard()/getMouse()
50
Selenium Web Driver - RemoteWebDriver
● Localiser : findElement(s){ByClassName,...}(Object cle)
– les WebElement sont contrôlables
– By.xpath, By.id, By.tagName, By.name …
51
Selenium Web Driver - {Remote}WebElement
● Etat du WebElement
– isEnabled(),isSelected(),isDisplayed()
– getSize(),getLocation(),getText(),getAttribute()
– findElement()
● Interactions simples à partir du WebElement
– welt.sendKeys(), welt.click(), welt.submit()
● Interactions complexes avec interactions.Actions
– construire une suite d'actions new Actions(driver)
– ajouter this.keyDown(Keys.CONTROL).click(welt1).keyUp(welt2).
– executer this.build().perfom()
● Interagir avec les options d'un select dans un formulaire : Select(WebElement)
52
Selenium WebDriveTemps d'arrêt (...AndWait)
● Navigation entre pages / Rechargement de pages / AJAX
● Combien de temps attendre avant de poursuivre?
● Observer un changement
– Apparition/Disparition d'un élément sur la page
– Changement d'état sur un élément existant
– Alertes
53
Selenium WebDriveTemps d'arrêt (...AndWait)
● Objets marquant les temps d'arrêt : WebDriveWait
WebDriverWait wdwait = new WebDriverWait(driver, timeout);
● Continuer à condition que …
wdwait.until(ExpectedCondition)
● Collections de conditions prédéfinies ExpectedConditions
– [in]visibilityOf(WebElt.)/[in]visibilityofElementLocated(By l) ...
wdwait.until(ExpectedConditions.alertsPresent());
wdwait.until(ExpectedConditions.presenceOfElementLocated(By.id("v1")))
● Definir ses propres ExpectedCondition
– surcharger la methode apply(WebDriver d)
54
Selenium WebDriveTemps d'arrêt (...AndWait) - Exemple
● Utilisation d'une condition prédéfinie
● Création d'une condition
new WebDriverWait(driver,10,500). until(ExpectedConditions.
visibilityOfElementLocated(By.id("result"))
;
new WebDriverWait(driver,10,500). until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {return d.findElement(By.id("result")).isDisplayed() ;
} }
55
Selenium UI - Exemplev1
v2
c1
c2
ops
result_detail
@Before public void createDriver() {driver = new FirefoxDriver();}@Test public void test() { driver.get("http://localhost/~bilasco/Money/index.php"); WebElement element = driver.findElement(By.name("v1"));
element.sendKeys("12"); … ;element.submit(); new WebDriverWait(driver, 10).until(ExpectedConditions.
visibilityOfLocatedElement(By.id("result_detail"))); assertEquals(driver.findElement(By.id("result_detail")).getText(),
"(EUR) 24")) ; }@After public void releaseDriver() {driver.quit()} ;
56
Exercices
● Exercices sur Wiki– http://forge.fil.univ-lille1.fr/OTI/wiki/TestsSelenium
– http://forge.fil.univ-lille1.fr/OTI/wiki/TestsSeleniumWebDriver
● Travailler sur les tests pour votre projet JavaScript
57
Outils de Tests d'Interface
a) Plateformes de tests : JUnit, PHPUnit, Qunit
b) Selenium
c) Outils de déploiement : maven
d) Outils de qualité : sonar
http://www.fil.univ-lille1.fr/~bilasco/OTI/OTI2014a.pdf
58
Systèmes de déploiement
(GNU) MakeCompilation & dépendances
(Apache) AntCompilation & dépendances & tâches
(Apache) MavenDépendances symboliques
Structuration des projets en familles
Automatisation
Plugins dédiés pour :
distribution : Jar, Ear, War, Aar
tests : surfire
sonar : sonar
scv : maven-scm-plugin
59
Maven
●Proposer un système de build universel
●Un cadre type pour la construction de projet
●Organiser les projets de manière hierarchique ● GroupID/ArtifactID/Version● Réutilisation à tout prix● Héritage entre projets
●Aider dans la gestion des distributions et suivi de bugs●Management de distributions – intégration SCM ●Management de dépendances
60
Maven
●Proposer un système de build universel
●Un cadre type pour la construction de projet
●Organiser les projets de manière hierarchique ● GroupID/ArtifactID/Version● Réutilisation à tout prix● Héritage entre projets
●Aider dans la gestion des distributions et suivi de bugs●Management de distributions – intégration SCM ●Management de dépendances
61
Maven – fonctionnalités
Proposer des lignes de conduites pour un développement optimal
Structure de projets prédéfinie
Séparation entre sources (main) et tests (test)
- src/ - main/
- java/ - ressources/ - config/ - test/ ...
- target/ ...- pom.xml
62
Maven - POM
POM ou "Project Object Model"● Représentation XML pour les projets Maven
Un project (Maven) ou archetype contient ● Identification du projet● fichiers de configuration ● développeurs intervenant dans le projet● l'organisation et les licences ● l'URL où est visible le projet ● les dépendances du projet ● les plugins
– SCV, Tests, Système de traçage de bugs ...
63
Maven – POM
<project xmlns="http://maven.apache.org/POM/4.0.0"...> <modelVersion>4.0.0</...>
<!-- The Basics -->
<groupId>...</...> <version>...</...> <packaging>...</...> <dependencies>...</...>
<parent>...</...> <dependencyManagement> … </...> <modules>...</...> <packaging>...</...>
<!-- Build Settings -->
<build>...</build> <reporting>...</reporting>
<!-- More Project Information -->
<name>...</...> <url>...</...> <licenses>...</...> <developers>...</...> <contributors>...</...>
<!-- Environment Settings -->
<mailingLists>...</...> <scm>...</...> <prerequisites>...</...> <repositories>...</...>
<pluginRepositories>...</...> <distributionManagement>...</...> ...
</project>
64
Maven – cycle de vie
65
Maven - cycle de vie
mvn archetype:generate – construction POM + dossiers
mvn validate - POM correctement défini
mvn compile - compile les sources
mvn test - Lance les tests unitaires
mvn package - Prépare la distribution (J/W/Ear)
mvn verify - Tests de validation nv package.
mvn install - Installe le pk en local (dép. int.)
mvn deploy - Déploie le pk sur un serveur
66
Maven & Sonar - exercises
http://forge.fil.univ-lille1.fr/ODEVA/wiki/MavenExo
● Travail sur le projet JUnit
– Creation d'un projet Maven
– Compilation et Tests Unitaires
– Installer SonarQube
– Configurer sonar-project.properties (runner->qube)
– Lancer Analyse
– Faire évoluer votre code
– Re-analyser
67
● … the end
● ...plus loin du contenu supplémentaire
68
Outils de Tests d'Interface
a) Plateformes de tests : JUnit, PHPUnit, Qunit
b) Outils de qualité : sonar
c) Selenium
d) Outils de déploiement : maven
http://www.fil.univ-lille1.fr/~bilasco/OTI/OTI2014a.pdf
69
PHPUnit
● Quasiment même concepts que JUnit
● Code test écrit et exécuté depuis le serveur
– phpunit.phar
● Intégré également dans frameworks (Symfony...)
● Classes de tests étendent
– PHPUnit_Framework_TestCaseclass TestCase1 extends PHPUnit_Framework_TestCase {...}
70
PHPUnit
● Initialisation – setUp{BeforeClass}, tearDown{BeforeClass}
● Asserts de langage – assert{InstanceOf,ClassHasAttribute,ObjectHasAttribute}
– assert{ArrayHasKey, Contains, Count}
– assertString{EndsWith,StartsWith}
● Exceptions – try {opsProduisantExc ; fail ("absence") ;} catch (Exc $e) {}
– $this->setExpectedException(excClassName,excMsg)
– /** * @expectedException Exc_Class_Name */
71
PHPUnit et les applis Web
● Asserts Sortie écran – setExpectedOutput{String/Regexp}
● Asserts orientés Web– XML : assert{EqualXMLStructure,XMLStringEqualsXMLFile,...}
– JSon : assertJsonFileEqualsJsonFile
– CSS : assertSelect{Count,Equals,Regexp}
– HTML : assertTag
● Extensions– PHPUnit/Extensions/Database/TestCase.php
72
PhpUnit
● Générateur de données (@dataProvider) pour simuler RepeatedTest
– function nomF() { return array(array(v1a,v1b),array(v2a,v2b),...)} ;
– /** @dataProvider nomF */ → fournit tableau de params.
– function testXXX($a,$b) {…}–
● Dépendances entres tests – ordonnancer les tests– /** @depends test1 */ function test2() { … }
Test1 * <----- Test2* mettre le système dans l'état attendu par Test2 – pas atomique
* les opérations autres que la cible du Test2 déjà validées
73
PHPUnit – Suite de tests
● Structurer les tests en répertoires– tests_dir
● test1.php● tests_dir2
– test2.php
– $ phpunit tests_dir
● … ou configurer phpunit.xml – <phpunit>– <testsuites>– <testsuite name="ts1">– <directory>Tests</directory>– <file>OtherTests/Test1.php</file>– <exclude>OtherTests/Test2.php</exclude>
– </testsuite>– </testsuites>– </phpunit>
74
PHPUnit Exercices
● http://forge.fil.univ-lille1.fr/OTI/wiki/PHPUnitExo
MoneyFactory.class.php
::+getDefaultFactory+createMoney
Money.class.php
-__construct+getValue +getCurrency
+toString+sameCurrency +equal
MoneyOps.class.php
:: +add
MoneyException.php
IncompatibleCurrenciesExceptionInvalidCurrencyException
InvalidMoneyValueException
MoneyOpsAddTest.php
+testSimpleAdd
MoneySameCurrTest.php
+testSame+testNotSame
MoneyEqTest.php
+testMemeValeurMemeDevise+testMemeValeurDeviseDifff//