SlideShare une entreprise Scribd logo
1  sur  165
Télécharger pour lire hors ligne
12 avril 2018
Technologies intelligentes
d'aide au développement
technique d'applications web
Sylvain Hallé
Université du Québec à Chicoutimi
CRSNG
NSERC
12 avril 2018
Qui suis-je?
Professeur-chercheur au
Département d'informatique et
de mathématique, Université du
Québec à Chicoutimi
Titulaire de la Chaire de recherche
du Canada en spécification, test
et vérification de systèmes
informatiques ($$$)
La personne dans
cette photo ;-)
12 avril 2018
$$
60 étudiants depuis 2010
prix
Best Paper
Award
en subventions de recherche (2010-2020)
4 3professeurs-
chercheurs
100+
publications
scientifiques
1 500 000
$
12 avril 2018
12 avril 2018
?
12 avril 2018
+
?
Quelques projets du LIF...
Librairie de event
stream processing
https://liflab.github.io/beepbeep-3
Utile pour tests en temps
réel, analyse de logs,
détection d'intrusions, ...
12 avril 2018
Quelques projets du LIF...
Détection de bugs dans les
jeux vidéo
Monitoring d'appareils
électriques
12 avril 2018
Quelques projets du LIF...
Librairie d'automatisation
d'expériences informatiques
https://liflab.github.io/labpal
Fonctions avancées de traçabilité
LabLabPalPal
À paraître dans IEEE Computer!
12 avril 2018
Quelques projets du LIF...
LabLabPalPal
Cell (0,2) in Table #3
The sum of column 2 in Table #2
Cell (0,2) in Table #2
The value of
Cell (1,1) in Table #1
Value of time in Experiment #2
Cell (1,2) in Table #1
Value of name in Experiment #2
Cell (1,2) in Table #2
The value of
Cell (5,1) in Table #1
Value of time in Experiment #6
Cell (5,2) in Table #1
Value of name in Experiment #6
Cell (2,2) in Table #2
The value of
Cell (9,1) in Table #1
Value of time in Experiment #10
Cell (9,2) in Table #1
Value of name in Experiment #10
12 avril 2018
Quelques projets du LIF...
Système de traçabilité
sécurisé
https://github.com/artichoke-x
Basé sur une variante des
blockchains
ARTICHOKE
$
DOCTOR
PATIENT
INSURANCE
COMPANY
PHARMACIST
NURSE
DOCUMENT
Best Paper Award en 2016
12 avril 2018
Quelques projets du LIF...
https://liflab.github.io/sealtest
3
4
1
a [n<2]
/ n=n+1
c
a [n>1] 5
6 7
a n=0
b
2
c c
d [n=0] d [n>0]
d d
8
G (a → (X (b ∨ c)))
Générateur de
séquences de test
Notre plus récent projet
(en développement)
Voici maintenant
votre programme principal
Gabrielle
Bastien
Nicolas
Bergeron
Oussama
Beroual
Xavier
Chamberland-
Thibeault
Francis
Guérin
Gabriel
Le Breton
Paul
Lesur
Jérémy
Spieldenner
Florence
Opalvens
Chafik
Meniar
Merci à
l'équipe!
12 avril 2018
Notre enquête (2014-2016)
12 avril 2018
Pièce à conviction #1
Éléments superposés
12 avril 2018
12 avril 2018
12 avril 2018
12 avril 2018
12 avril 2018
12 avril 2018
La boîte a la
bonne taille si
l'utilisateur
n'est pas logué
12 avril 2018
Pièce à conviction #2
Éléments qui dépassent de leur conteneur
12 avril 2018
12 avril 2018
Pièce à conviction #3
Propriété z-index incorrecte
12 avril 2018
12 avril 2018
12 avril 2018
Pièce à conviction #4
Mojibake!
12 avril 2018
Mojibake est un emprunt lexical du
japonais qui signifie que les caractères
affichés à l'écran d'un logiciel informatique
ne s'affichent pas correctement, à cause
d'un problème de codage. (Wikipedia)
«
»
Pièce à conviction #4
Mojibake!
12 avril 2018
décembre 2014
12 avril 2018
décembre 2015
décembre 2014
12 avril 2018
Pièce à conviction #5
Problèmes de zoom
12 avril 2018
Zoom = 100%
12 avril 2018
Zoom = 80%
12 avril 2018
Pièce à conviction #6
Cachez cet élément que je ne saurais voir
12 avril 2018
Pièce à conviction #6
Cachez cet élément que je ne saurais voir
(Bug dans le thème WordPress)
12 avril 2018
Pièce à conviction #7
Irresponsive web design
12 avril 2018
✓
12 avril 2018
✓
12 avril 2018
❌
12 avril 2018
Une minute...
Tout de même, les bugs d'affichage
ne mettent pas en danger la
fonctionnalité d'une application...
N'est-ce pas?
12 avril 2018
Pièce à conviction #8
Texte ton sur ton
12 avril 2018
12 avril 2018
12 avril 2018
Not now
12 avril 2018
Pièce à conviction #9
Trop d'échappement, c'est possible
12 avril 2018
12 avril 2018
12 avril 2018
Pièce à conviction #10
Éléments inaccessibles
12 avril 2018
On ne peut
atteindre la
partie gauche
du popup
12 avril 2018
On ne peut atteindre
les boutons cachés
12 avril 2018
12 avril 2018
...ça arrive même aux meilleurs!
La boîte de texte disparaît si
la fenêtre tombe sous une largeur précise
(le scroll ne change rien)
12 avril 2018
Page non scrollable!
12 avril 2018
12 avril 2018
Pièce à conviction #11
Problèmes de formulaires
12 avril 2018
Boîte pré-remplie avec 6 caractères,
mais le champ a maxlength=5
12 avril 2018
Pièce à conviction #12
Une page dans une page
12 avril 2018
Pièce à conviction #12
Une page dans une page
12 avril 2018
Une minute...
On ne peut pas observer l'état interne
de l'application simplement à partir
de son HTML...
N'est-ce pas?
Le bouton Fermer n'a aucun effet...
on est coincé dans le popup!
12 avril 2018
12 avril 2018
12 avril 2018
12 avril 2018
Une minute...
Si on observe la mise en page, on
est limité à un seul moment dans le
temps...
N'est-ce pas?
12 avril 2018
12 avril 2018
12 avril 2018
En mettant le focus sur
la boîte de texte...
La propriété padding
passe à 0
La boîte monte d'un
pixel
12 avril 2018
Résultats de recherche incorrects
https://youtu.be/zCg537MZ6Ww
Clic droit déchaîné
https://youtu.be/iw7x3H51TFo
État de bouton incorrect
https://youtu.be/NGbl4vP350s
Élément clignotant
https://youtu.be/luJXkenY0Oo
12 avril 2018
Pourquoi ces bugs sont-ils aussi fréquents?
12 avril 2018
Une partie de l'explication
Les navigateurs ne font pas le même rendu du même
code HTML/CSS (cross-browser layout problems)
(C'est la faute aux navigateurs!)
12 avril 2018
ACID2 Test: la même page dans deux (vieux) navigateurs
Safari (succès)
Internet Explorer (échec)
12 avril 2018
Une minute...
Presque tous les bugs que nous
avons vus sont présents dans tous
les navigateurs...
...alors est-ce uniquement
de leur faute?
12 avril 2018
Une autre partie de l'explication
CSS est complexe!
Difficile de savoir si les propriétés réelles d'un élément
correspondent à une règle CSS ("suggestion")
12 avril 2018
Une autre partie de l'explication
CSS est complexe!
Difficile de savoir si les propriétés réelles d'un élément
correspondent à une règle CSS ("suggestion")
#ext {
width: 200px;
}
.foo {
width: 150px;
}
<div id="ext">
<div class="foo">A</div>
<div class="foo">B</div>
</div>
12 avril 2018
Une autre partie de l'explication
CSS est complexe!
Difficile de savoir si les propriétés réelles d'un élément
correspondent à une règle CSS ("suggestion")
#ext {
width: 200px;
}
.foo {
width: 150px;
}
<div id="ext">
<div class="foo">A</div>
<div class="foo">B</div>
</div>
#ext
.foo .foo
300px
12 avril 2018
http://eli.fox-epste.in/rule110-full.html
12 avril 2018
La règle 110
12 avril 2018
Une autre partie
de l'autre partie de l'explication
Pourcentage des applications web qui n'ont
pas de suite de tests (source: ICST 2015)
86%
12 avril 2018
Les bugs liés à l'affichage peuvent révéler des problèmes
de design, mais aussi de fonctionnalité d'une application
Ils sont fréquents
Ils ne sont pas forcément causés par le navigateur
CSS peut donner des "suggestions",
mais pas imposer des contraintes
Conclusion: la détection de ces bugs
doit se faire par un moyen externe
à HTML/CSS
12 avril 2018
Solution #1
Observation "à l'oeil nu" par un testeur
M. TEST
Beaucoup de choses à vérifier
(lent)
Basé sur la compréhension
du testeur
C'est bizarre
ici!
12 avril 2018
Solution #2
Programmer la vérification des contraintes sur
l'interface avec un langage "traditionnel"
12 avril 2018
var textnodes = $(elem)
.contents()
.filter(function() {
return this.nodeType === 3; //Node.TEXT_NODE
});
var mojibake = ["é", "ô", "è"];
var contains = function(t, m) {
var re = new RegExp(m, "g");
return re.match(t);
};
evaluate = function() {
for (var tn in textnodes) {
var elem = $(tn);
var text = tn.text();
for (var moj in mojibake) {
if (contains(text, moj))
console.log("Error");
}
}
};
evaluate = function() {
if (!evaluate.positions) {
evaluate.positions = [];
evaluate.positionindex = 0;
$("li").each(function() {
evaluate.positions.push({
"top" : $(this).offsetTop,
"left" : $(this).offsetLeft
});
$(this).uniqueid = evaluate.positionindex;
evaluate.positionindex++;
});
}
$("li").each(function(index) {
var uniqueid = $(this).uniqueid;
if (uniqueid && (
evaluate.positions[uniqueid].top
!= $(this).offsetTop ||
evaluate.positions[uniqueid].left
!= $(this).left)
)
console.log("Error");
});
};
12 avril 2018
...et plusieurs autres!
Si jQuery ne fait pas notre affaire, il existe d'autres
solutions:
12 avril 2018
evaluate = function() {
if (!evaluate.positions) {
evaluate.positions = [];
evaluate.positionindex = 0;
$("li").each(function() {
evaluate.positions.push({
"top" : $(this).offsetTop,
"left" : $(this).offsetLeft
});
$(this).uniqueid = evaluate.positionindex;
evaluate.positionindex++;
});
}
$("li").each(function(index) {
var uniqueid = $(this).uniqueid;
if (uniqueid && (
evaluate.positions[uniqueid].top
!= $(this).offsetTop ||
evaluate.positions[uniqueid].left
!= $(this).left)
)
console.log("Error");
});
};
Quelques problèmes...
Expliquez ce que
fait ce bout de code
(en 5 secondes!)
12 avril 2018
evaluate = function() {
if (!evaluate.positions) {
evaluate.positions = [];
evaluate.positionindex = 0;
$("li").each(function() {
evaluate.positions.push({
"top" : $(this).offsetTop,
"left" : $(this).offsetLeft
});
$(this).uniqueid = evaluate.positionindex;
evaluate.positionindex++;
});
}
$("li").each(function(index) {
var uniqueid = $(this).uniqueid;
if (uniqueid && (
evaluate.positions[uniqueid].top
!= $(this).offsetTop ||
evaluate.positions[uniqueid].left
!= $(this).left)
)
console.log("Error");
});
};
Quelques problèmes...
Expliquez ce que
fait ce bout de code
(en 5 secondes!)
Retourne juste
"Error" ?!?
Si on veut plus d'info,
on doit écrire plus de
code....
12 avril 2018
Solution #3
Approche intelligente!
On écrit des énoncés
lisibles qui expriment des
contraintes que l'interface
doit suivre
La machine s'occupe de
trouver comment les vérifier
≠ IA
12 avril 2018
12 avril 2018
System
12 avril 2018
System
12 avril 2018
System
Instrumentation
12 avril 2018
System
Instrumentation
12 avril 2018
System
Trace
Instrumentation
12 avril 2018
System
Trace
Events
Instrumentation
12 avril 2018
System
Trace
Events
Instrumentation
12 avril 2018
Un langage pour exprimer des contraintes de haut
niveau sur des interfaces web (ou autres)
- DOM + attributs CSS
- Quantification du premier ordre
- Opérateurs temporels
1.
Notre solution:
12 avril 2018
Un architecture pour intstrumenter une application
web et rapporter les attributs pertinents à un
interpréteur
2.
Notre solution:
12 avril 2018
Un mécanisme pour vérifier automatiquement les
propriétés et donner une explication si une
contrainte est violée
3.
Notre solution:
12 avril 2018
BEST
TOOL
Hallé, Bergeron, Guérin, Le Breton. Testing
Web Applications Through Layout
Constraints. Proc ICST 2015.
https://github.com/liflab/cornipickle
Notre solution:
12 avril 2018
12 avril 2018
Application under test
Server
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
{{tagname:"div",cornipickleid:1,props:
{left:0,right:10,color:red,width:40},children:
[{tagname:"span",cornipickleid:21,props:
{left:20,right:145,color:black,width:120},children:[]},
{tagname:"p",cornipickleid:14,props:
{left:0,right:10,color:red,width:40},children:[]}]}}
...
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
{{tagname:"div",cornipickleid:1,props:
{left:0,right:10,color:red,width:40},children:
[{tagname:"span",cornipickleid:21,props:
{left:20,right:145,color:black,width:120},children:[]},
{tagname:"p",cornipickleid:14,props:
{left:0,right:10,color:red,width:40},children:[]}]}}
...
Probe log
10
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
{{tagname:"div",cornipickleid:1,props:
{left:0,right:10,color:red,width:40},children:
[{tagname:"span",cornipickleid:21,props:
{left:20,right:145,color:black,width:120},children:[]},
{tagname:"p",cornipickleid:14,props:
{left:0,right:10,color:red,width:40},children:[]}]}}
...
Probe log
10
11
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
{{tagname:"div",cornipickleid:1,props:
{left:0,right:10,color:red,width:40},children:
[{tagname:"span",cornipickleid:21,props:
{left:20,right:145,color:black,width:120},children:[]},
{tagname:"p",cornipickleid:14,props:
{left:0,right:10,color:red,width:40},children:[]}]}}
...
Probe log
10
11
Probe instructions (optional) 12
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
{{tagname:"div",cornipickleid:1,props:
{left:0,right:10,color:red,width:40},children:
[{tagname:"span",cornipickleid:21,props:
{left:20,right:145,color:black,width:120},children:[]},
{tagname:"p",cornipickleid:14,props:
{left:0,right:10,color:red,width:40},children:[]}]}}
...
Probe log
10
11
Probe instructions (optional) 12
Dashboard
(analytics)
Developer
13
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
{{tagname:"div",cornipickleid:1,props:
{left:0,right:10,color:red,width:40},children:
[{tagname:"span",cornipickleid:21,props:
{left:20,right:145,color:black,width:120},children:[]},
{tagname:"p",cornipickleid:14,props:
{left:0,right:10,color:red,width:40},children:[]}]}}
...
Probe log
10
11
Probe instructions (optional) 12
Dashboard
(analytics)
Developer
13
14
12 avril 2018
Application under test
Server
Probe
creation
Developer
1
Probe repository
2
Probe ID
3
<script ...
"getprobe?uid=39f2ac8">
4
Request for probe code
5
6
7
Probe code
Probe (JS object)
Probe
retrieval
8
{if("INPUT"===e.tagName||"BUTTON"===e.tagName)
return"range"===e.type||"number"==e.type?
e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re
freshDelay=500,Cornipickle.CornipickleProbe.elementCount
er=0,Cornipickle.CornipickleProbe.clickThrough
=!1,Cornipickle.CornipickleProbe.toggleClickThrough=
function(){return
Cornipickle.CornipickleProbe.clickThrough
!=Cornipickle.CornipickleProbe.clickThrough,
...
~12 ko
Probe
interaction
Probe status report
9
{{tagname:"div",cornipickleid:1,props:
{left:0,right:10,color:red,width:40},children:
[{tagname:"span",cornipickleid:21,props:
{left:20,right:145,color:black,width:120},children:[]},
{tagname:"p",cornipickleid:14,props:
{left:0,right:10,color:red,width:40},children:[]}]}}
...
Probe log
10
11
Probe instructions (optional) 12
Dashboard
(analytics)
Developer
13
14
16
15
12 avril 2018
$ java -jar cornipickle.jar --port 12345 spec.cp
Pour un usage local:
Fichier texte contenant les
contraintes à monitorer
Port sur lequel écoute
l'interpréteur Cornipickle
Dans l'en-tête de l'application
à tester, ajouter:
<script src="http://localhost:12345/probe" />
C'est tout!
12 avril 2018
MATHS
12 avril 2018
12 avril 2018
12 avril 2018
For each $x in $(css-selector)
something about $x.
There exists $x in $(css-selector)
such that
something about $x.
12 avril 2018
$x's prop is greater than
$y's prop
$x's height
$x's text
$x's color
$x's prop matches "a string"
...et la plupart des attributs
CSS et DOM
...et la plupart des
fonctions usuelles
12 avril 2018
something And something else
something Or something else
Not something
12 avril 2018
For each $x in $(.item)
$x's color equals "red".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
.item {
color: red;
}
12 avril 2018
VRAIFor each $x in $(.item)
$x's color equals "red".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
.item {
color: red;
}
12 avril 2018
For each $x in $(.item)
$x's color equals "red".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
.item {
color: red;
}
.item:first-child {
color: yellow;
}
12 avril 2018
FAUXFor each $x in $(.item)
$x's color equals "red".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
.item {
color: red;
}
.item:first-child {
color: yellow;
}
12 avril 2018
For each $x in $(.item)
$x's color equals "red".
<ul>
<li class="item">foo</li>
<li class="item"
style="color:blue">bar</li>
</ul>
.item {
color: red;
}
12 avril 2018
FAUXFor each $x in $(.item)
$x's color equals "red".
<ul>
<li class="item">foo</li>
<li class="item"
style="color:blue">bar</li>
</ul>
.item {
color: red;
}
12 avril 2018
There exists $x in $(li)
such that
$x's text equals "foo".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
.item {
color: red;
}
12 avril 2018
VRAIThere exists $x in $(li)
such that
$x's text equals "foo".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
.item {
color: red;
}
12 avril 2018
There exists $x in $(li)
such that
$x's text equals "foo".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
$().ready(function() {
$(".item").text("");
}
12 avril 2018
FAUXThere exists $x in $(li)
such that
$x's text equals "foo".
<ul>
<li class="item">foo</li>
<li class="item">bar</li>
</ul>
$().ready(function() {
$(".item").text("");
}
12 avril 2018
For each $x in $(#menu li) (
For each $y in $(#menu li) (
$x’s left equals $y’s left)).
A list item
Another list item
A third list item
The last list item
12 avril 2018
FAUXFor each $x in $(#menu li) (
For each $y in $(#menu li) (
$x’s left equals $y’s left)).
A list item
Another list item
A third list item
The last list item
12 avril 2018
We say that pattern
When something.
Exemple:
We say that $x is wider than $y
When
$x's width is greater
than $y's width.
On peut définir soi-même des prédicats (genres de
"macros") pour simplifier l'écriture.
12 avril 2018
We say that $x and $y are left-
aligned when
$x’s left equals $y’s left.
For each $x in $(#menu li) (
For each $y in $(#menu li) (
$x and $y are left-aligned)).
A list item
Another list item
A third list item
The last list item
12 avril 2018
... $(ul li) ...
... 's width ...
... $(p#abc) ...
... 's color ...
La sonde JavaScript est sélective:
elle ne renvoie que les attributs mentionnés dans
une contrainte
seulement pour les éléments qui correspondent à
un des sélecteurs
12 avril 2018
{
cornipickleid: 3,
x: 300,
y: 250,
event: "click"
...
Si un clic se produit dans la page, l'élément concerné
possède un attribut spécial event dans le message
renvoyé par la sonde:
On peut mentionner cet attribut dans une expression
comme toute autre propriété CSS.
12 avril 2018
(The Hitchhiker's
Guide to the
Galaxy)
12 avril 2018
(Quelque
chose de
compliqué
ici)
Spec, données, etc.
12 avril 2018
(Quelque
chose de
compliqué
ici)
Spec, données, etc.
vrai/faux
12 avril 2018
12 avril 2018
12 avril 2018
Voyons le logiciel en action sur quelques exemples
simples...
https://www.youtu.be/90YitGRRx2w
12 avril 2018
Identifier les éléments responsables d'une violation ne
nécessite aucun code
Ce n'est qu'un sous-produit de l'évaluation des
expressions
12 avril 2018
Il est possible de parler de l'état de l'interface à
différents moments dans le temps au moyen
d'opérateurs temporels.
12 avril 2018
Always something
L'expression something doit toujours être
vraie à partir de maintenant.
maintenant
something
Il est possible de parler de l'état de l'interface à
différents moments dans le temps au moyen
d'opérateurs temporels.
12 avril 2018
Il est possible de parler de l'état de l'interface à
différents moments dans le temps au moyen
d'opérateurs temporels.
Eventually something
Il est possible de parler de l'état de l'interface à
différents moments dans le temps au moyen
d'opérateurs temporels.
L'expression something doit être vraie
au moins une fois dans le futur.
maintenant
something
12 avril 2018
Il est possible de parler de l'état de l'interface à
différents moments dans le temps au moyen
d'opérateurs temporels.
Next something
Il est possible de parler de l'état de l'interface à
différents moments dans le temps au moyen
d'opérateurs temporels.
L'expression something doit être vraie
dans le prochain instantané.
maintenant
something
12 avril 2018
Maintenant, mélangeons
le tout!
12 avril 2018
Les opérateurs temporels permettent de décrire une
séquence de pages et leur contenu
Ouvre la porte à tester le comportement d'une
application
Faire la même chose avec du code
procédural est plus compliqué (variables
temporaires, conditions supplémentaires)
Bonus: le mécanisme de feedback
intelligent fonctionne toujours!
12 avril 2018
corni
pickle
We say that $x is immobile when (
Always (
When $x is now $y (
($x's left equals $y's left)
And
($x's top equals $y's top)
)
)
).
For each $item in $(li) (
$item is immobile
).
evaluate = function() {
if (!evaluate.positions) {
evaluate.positions = [];
evaluate.positionindex = 0;
$("li").each(function() {
evaluate.positions.push({
"top" : $(this).offsetTop,
"left" : $(this).offsetLeft
});
$(this).uniqueid = evaluate.positionindex;
evaluate.positionindex++;
});
}
$("li").each(function(index) {
var uniqueid = $(this).uniqueid;
if (uniqueid && (
evaluate.positions[uniqueid].top
!= $(this).offsetTop ||
evaluate.positions[uniqueid].left
!= $(this).left)
)
console.log("Error");
});
};
12 avril 2018
corni
pickle
We say that I click on Go when (
There exists $b in $(button) such that (
($b's text equals "Go")
And
($b's event equals "mouseup")
)
).
Always (
If (I click on Go)
Then (
There exists $x in $(.value) such that (
The next time (I click on Go)
Then (
There exists $y in $(.value) such that (
$x's text equals $y's text
)
)
)
)
).
click_on_go = function(event) {
return event.type === 'mouseup' &&
$(event.target).text() === "Go";
}
evaluate = function(event) {
if (click_on_go(event)) {
var current_values = [];
$(".value").each(
evaluate.lastValues.push($(this).text());
);
if (evaluate.lastValues !== undefined) {
var found = false;
for (var v in current_values) {
if ($.inArray(v, evaluate.lastValues))
found = true;
break;
}
}
}
if (!found)
console.log("Error");
evaluate.lastValues = current_values;
}
};
12 avril 2018
"La plupart des navigateurs"
{ {Part de marché
(desktop)
Part de marché
(non-desktop)
75%
25%
12 avril 2018
Dans les bugs d'interface, le navigateur est parfois
important
On ne devrait pas prendre des décisions de design qui
nous limitent dès le début (Selenium, plugin spécifique)
Si votre app/site tourne dans le navigateur X, votre outil
de test le devrait lui aussi!
12 avril 2018
For each $x in $(selector)
blabla...
There exists $y in $(selector)
blabla...
Les sélecteurs CSS sont fragiles. Des changements
simples à la mise en page peuvent "endommager" vos
contraintes.
12 avril 2018
Amélioration du feedback
intelligent: suggestions de
corrections
Extension à WebDriver
Passerelle avec outils
d'intégration continue (Jenkins,
Travis)
12 avril 2018
12 avril 2018
https://developer.android.com/guide/practices/ui_guidelines/index.html
12 avril 2018
12 avril 2018
✓ ✘
The Bottom Navigation can accommodate between 3 and 5
destinations.
12 avril 2018
✓ ✘
The floatting button should not be hidden by other components.
12 avril 2018
✓ ✘
The application should report by a color change if the number of
characters allowed is exceeded.
12 avril 2018
L'interpréteur local de Cornipickle est open source et
gratuit
Nous pouvons personnaliser et étendre Cornipickle via
des collaborations
Projet d'intégration avec Eckinox Média (Alma) en cours
(janvier-juillet 2017) sous financement de MITACS
12 avril 2018
https://liflab.ca
https://github.com/liflab/cornipickle
http://leduotang.ca/sylvain

Contenu connexe

Similaire à Technologies intelligentes d'aide au développement d'applications web (WAQ 2018)

2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan Bouveret
2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan Bouveret2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan Bouveret
2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan BouveretModern Workplace Conference Paris
 
Présentation FrenchWeb: Qu'est-ce que la visualisation des données?
Présentation FrenchWeb: Qu'est-ce que la visualisation des données?Présentation FrenchWeb: Qu'est-ce que la visualisation des données?
Présentation FrenchWeb: Qu'est-ce que la visualisation des données?Clement Levallois
 
Quizz - Plongée dans le cœur de WordPress
Quizz - Plongée dans le cœur de WordPressQuizz - Plongée dans le cœur de WordPress
Quizz - Plongée dans le cœur de WordPressBrice Capobianco
 
Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...
Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...
Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...SEO CAMP
 
Site Web Centrale Eco
Site Web   Centrale EcoSite Web   Centrale Eco
Site Web Centrale Ecom.dubucq
 
Formation « Méthodes agiles » -- construire et partager l'information et les ...
Formation « Méthodes agiles » -- construire et partager l'information et les ...Formation « Méthodes agiles » -- construire et partager l'information et les ...
Formation « Méthodes agiles » -- construire et partager l'information et les ...iganchev
 
Screaming frog - l'outil ne fait pas l'artisan
Screaming frog - l'outil ne fait pas l'artisanScreaming frog - l'outil ne fait pas l'artisan
Screaming frog - l'outil ne fait pas l'artisanAymeric Bouillat
 
Adictiz et LudoStat : Performances et best practices de l'advergame
Adictiz  et LudoStat : Performances et best practices de l'advergameAdictiz  et LudoStat : Performances et best practices de l'advergame
Adictiz et LudoStat : Performances et best practices de l'advergameConférence Jeu Vidéo et Marketing
 
L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021
L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021
L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021Philippe YONNET
 
20120612 06 - Un framework d'analyse de logiciels issu de la recherche
20120612 06 - Un framework d'analyse de logiciels issu de la recherche20120612 06 - Un framework d'analyse de logiciels issu de la recherche
20120612 06 - Un framework d'analyse de logiciels issu de la rechercheLeClubQualiteLogicielle
 
Stratégie et veille : Extraire et trier des données en ligne
Stratégie et veille : Extraire et trier des données en ligneStratégie et veille : Extraire et trier des données en ligne
Stratégie et veille : Extraire et trier des données en ligneErwan Tanguy
 
Recommandation, le défi
Recommandation, le défiRecommandation, le défi
Recommandation, le défiThomas Gasc
 
La métrique, ce n'est pas que pour le devops
La métrique, ce n'est pas que pour le devopsLa métrique, ce n'est pas que pour le devops
La métrique, ce n'est pas que pour le devopsPatrick Allaert
 
Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023
Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023
Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023BenjaminGrolleau3
 
Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...
Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...
Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...Mohammed JAITI
 
meetup devops aix-marseille 27/10/2022
meetup devops aix-marseille 27/10/2022meetup devops aix-marseille 27/10/2022
meetup devops aix-marseille 27/10/2022Frederic Leger
 
Cours Google Analytics - IUT Vannes (février 2014)
Cours Google Analytics - IUT Vannes (février 2014)Cours Google Analytics - IUT Vannes (février 2014)
Cours Google Analytics - IUT Vannes (février 2014)Redpoint
 
Radical Quality From Toyota to Tech - Devoxx France.pptx
Radical Quality From Toyota to Tech - Devoxx France.pptxRadical Quality From Toyota to Tech - Devoxx France.pptx
Radical Quality From Toyota to Tech - Devoxx France.pptxFlavian Hautbois
 

Similaire à Technologies intelligentes d'aide au développement d'applications web (WAQ 2018) (20)

2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan Bouveret
2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan Bouveret2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan Bouveret
2018-10-17 J1 6C - Un framework pour les gouverner tous - Gaëtan Bouveret
 
Présentation FrenchWeb: Qu'est-ce que la visualisation des données?
Présentation FrenchWeb: Qu'est-ce que la visualisation des données?Présentation FrenchWeb: Qu'est-ce que la visualisation des données?
Présentation FrenchWeb: Qu'est-ce que la visualisation des données?
 
Quizz - Plongée dans le cœur de WordPress
Quizz - Plongée dans le cœur de WordPressQuizz - Plongée dans le cœur de WordPress
Quizz - Plongée dans le cœur de WordPress
 
Paris Web
Paris WebParis Web
Paris Web
 
Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...
Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...
Booster son SEO on-site avec les entités - Frédéric LAURENT - SEO CAMP'us Par...
 
Site Web Centrale Eco
Site Web   Centrale EcoSite Web   Centrale Eco
Site Web Centrale Eco
 
Formation « Méthodes agiles » -- construire et partager l'information et les ...
Formation « Méthodes agiles » -- construire et partager l'information et les ...Formation « Méthodes agiles » -- construire et partager l'information et les ...
Formation « Méthodes agiles » -- construire et partager l'information et les ...
 
Screaming frog - l'outil ne fait pas l'artisan
Screaming frog - l'outil ne fait pas l'artisanScreaming frog - l'outil ne fait pas l'artisan
Screaming frog - l'outil ne fait pas l'artisan
 
Adictiz et LudoStat : Performances et best practices de l'advergame
Adictiz  et LudoStat : Performances et best practices de l'advergameAdictiz  et LudoStat : Performances et best practices de l'advergame
Adictiz et LudoStat : Performances et best practices de l'advergame
 
L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021
L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021
L'IA dans l'algorithme de Google - Matin neperien 7 juillet 2021
 
20120612 06 - Un framework d'analyse de logiciels issu de la recherche
20120612 06 - Un framework d'analyse de logiciels issu de la recherche20120612 06 - Un framework d'analyse de logiciels issu de la recherche
20120612 06 - Un framework d'analyse de logiciels issu de la recherche
 
Stratégie et veille : Extraire et trier des données en ligne
Stratégie et veille : Extraire et trier des données en ligneStratégie et veille : Extraire et trier des données en ligne
Stratégie et veille : Extraire et trier des données en ligne
 
Recommandation, le défi
Recommandation, le défiRecommandation, le défi
Recommandation, le défi
 
La métrique, ce n'est pas que pour le devops
La métrique, ce n'est pas que pour le devopsLa métrique, ce n'est pas que pour le devops
La métrique, ce n'est pas que pour le devops
 
Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023
Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023
Utiliser WP pour l'outillage interne — WP Meetup Nantes - 02/02/2023
 
Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...
Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...
Rapport de mon First Projet Web à l'Ecole Supérieure de Technologie de SAFI -...
 
meetup devops aix-marseille 27/10/2022
meetup devops aix-marseille 27/10/2022meetup devops aix-marseille 27/10/2022
meetup devops aix-marseille 27/10/2022
 
Cours Google Analytics - IUT Vannes (février 2014)
Cours Google Analytics - IUT Vannes (février 2014)Cours Google Analytics - IUT Vannes (février 2014)
Cours Google Analytics - IUT Vannes (février 2014)
 
Radical Quality From Toyota to Tech - Devoxx France.pptx
Radical Quality From Toyota to Tech - Devoxx France.pptxRadical Quality From Toyota to Tech - Devoxx France.pptx
Radical Quality From Toyota to Tech - Devoxx France.pptx
 
Formation Titanium
Formation TitaniumFormation Titanium
Formation Titanium
 

Plus de Sylvain Hallé

Monitoring Business Process Compliance Across Multiple Executions with Stream...
Monitoring Business Process Compliance Across Multiple Executions with Stream...Monitoring Business Process Compliance Across Multiple Executions with Stream...
Monitoring Business Process Compliance Across Multiple Executions with Stream...Sylvain Hallé
 
A Stream-Based Approach to Intrusion Detection
A Stream-Based Approach to Intrusion DetectionA Stream-Based Approach to Intrusion Detection
A Stream-Based Approach to Intrusion DetectionSylvain Hallé
 
Event Stream Processing with BeepBeep 3
Event Stream Processing with BeepBeep 3Event Stream Processing with BeepBeep 3
Event Stream Processing with BeepBeep 3Sylvain Hallé
 
Smart Contracts-Enabled Simulation for Hyperconnected Logistics
Smart Contracts-Enabled Simulation for Hyperconnected LogisticsSmart Contracts-Enabled Simulation for Hyperconnected Logistics
Smart Contracts-Enabled Simulation for Hyperconnected LogisticsSylvain Hallé
 
Test Suite Generation for Boolean Conditions with Equivalence Class Partitioning
Test Suite Generation for Boolean Conditions with Equivalence Class PartitioningTest Suite Generation for Boolean Conditions with Equivalence Class Partitioning
Test Suite Generation for Boolean Conditions with Equivalence Class PartitioningSylvain Hallé
 
Synthia: a Generic and Flexible Data Structure Generator (Long Version)
Synthia: a Generic and Flexible Data Structure Generator (Long Version)Synthia: a Generic and Flexible Data Structure Generator (Long Version)
Synthia: a Generic and Flexible Data Structure Generator (Long Version)Sylvain Hallé
 
Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)
Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)
Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)Sylvain Hallé
 
Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)
Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)
Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)Sylvain Hallé
 
A Generic Explainability Framework for Function Circuits
A Generic Explainability Framework for Function CircuitsA Generic Explainability Framework for Function Circuits
A Generic Explainability Framework for Function CircuitsSylvain Hallé
 
Detecting Responsive Web Design Bugs with Declarative Specifications
Detecting Responsive Web Design Bugs with Declarative SpecificationsDetecting Responsive Web Design Bugs with Declarative Specifications
Detecting Responsive Web Design Bugs with Declarative SpecificationsSylvain Hallé
 
Streamlining the Inclusion of Computer Experiments in Research Papers
Streamlining the Inclusion of Computer Experiments in Research PapersStreamlining the Inclusion of Computer Experiments in Research Papers
Streamlining the Inclusion of Computer Experiments in Research PapersSylvain Hallé
 
Writing Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeepWriting Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeepSylvain Hallé
 
Real-Time Data Mining for Event Streams
Real-Time Data Mining for Event StreamsReal-Time Data Mining for Event Streams
Real-Time Data Mining for Event StreamsSylvain Hallé
 
Mining event streams with BeepBeep 3
Mining event streams with BeepBeep 3Mining event streams with BeepBeep 3
Mining event streams with BeepBeep 3Sylvain Hallé
 
LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)
LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)
LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)Sylvain Hallé
 
A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)
A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)
A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)Sylvain Hallé
 
Event Stream Processing with Multiple Threads
Event Stream Processing with Multiple ThreadsEvent Stream Processing with Multiple Threads
Event Stream Processing with Multiple ThreadsSylvain Hallé
 
A Few Things We Heard About RV Tools (Position Paper)
A Few Things We Heard About RV Tools (Position Paper)A Few Things We Heard About RV Tools (Position Paper)
A Few Things We Heard About RV Tools (Position Paper)Sylvain Hallé
 
Solving Equations on Words with Morphisms and Antimorphisms
Solving Equations on Words with Morphisms and AntimorphismsSolving Equations on Words with Morphisms and Antimorphisms
Solving Equations on Words with Morphisms and AntimorphismsSylvain Hallé
 
Runtime monitoring de propriétés temporelles par (streaming) XML
Runtime monitoring de propriétés temporelles par (streaming) XMLRuntime monitoring de propriétés temporelles par (streaming) XML
Runtime monitoring de propriétés temporelles par (streaming) XMLSylvain Hallé
 

Plus de Sylvain Hallé (20)

Monitoring Business Process Compliance Across Multiple Executions with Stream...
Monitoring Business Process Compliance Across Multiple Executions with Stream...Monitoring Business Process Compliance Across Multiple Executions with Stream...
Monitoring Business Process Compliance Across Multiple Executions with Stream...
 
A Stream-Based Approach to Intrusion Detection
A Stream-Based Approach to Intrusion DetectionA Stream-Based Approach to Intrusion Detection
A Stream-Based Approach to Intrusion Detection
 
Event Stream Processing with BeepBeep 3
Event Stream Processing with BeepBeep 3Event Stream Processing with BeepBeep 3
Event Stream Processing with BeepBeep 3
 
Smart Contracts-Enabled Simulation for Hyperconnected Logistics
Smart Contracts-Enabled Simulation for Hyperconnected LogisticsSmart Contracts-Enabled Simulation for Hyperconnected Logistics
Smart Contracts-Enabled Simulation for Hyperconnected Logistics
 
Test Suite Generation for Boolean Conditions with Equivalence Class Partitioning
Test Suite Generation for Boolean Conditions with Equivalence Class PartitioningTest Suite Generation for Boolean Conditions with Equivalence Class Partitioning
Test Suite Generation for Boolean Conditions with Equivalence Class Partitioning
 
Synthia: a Generic and Flexible Data Structure Generator (Long Version)
Synthia: a Generic and Flexible Data Structure Generator (Long Version)Synthia: a Generic and Flexible Data Structure Generator (Long Version)
Synthia: a Generic and Flexible Data Structure Generator (Long Version)
 
Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)
Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)
Test Sequence Generation with Cayley Graphs (Talk @ A-MOST 2021)
 
Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)
Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)
Efficient Offline Monitoring of LTL with Bit Vectors (Talk at SAC 2021)
 
A Generic Explainability Framework for Function Circuits
A Generic Explainability Framework for Function CircuitsA Generic Explainability Framework for Function Circuits
A Generic Explainability Framework for Function Circuits
 
Detecting Responsive Web Design Bugs with Declarative Specifications
Detecting Responsive Web Design Bugs with Declarative SpecificationsDetecting Responsive Web Design Bugs with Declarative Specifications
Detecting Responsive Web Design Bugs with Declarative Specifications
 
Streamlining the Inclusion of Computer Experiments in Research Papers
Streamlining the Inclusion of Computer Experiments in Research PapersStreamlining the Inclusion of Computer Experiments in Research Papers
Streamlining the Inclusion of Computer Experiments in Research Papers
 
Writing Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeepWriting Domain-Specific Languages for BeepBeep
Writing Domain-Specific Languages for BeepBeep
 
Real-Time Data Mining for Event Streams
Real-Time Data Mining for Event StreamsReal-Time Data Mining for Event Streams
Real-Time Data Mining for Event Streams
 
Mining event streams with BeepBeep 3
Mining event streams with BeepBeep 3Mining event streams with BeepBeep 3
Mining event streams with BeepBeep 3
 
LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)
LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)
LabPal: Repeatable Computer Experiments Made Easy (ACM Workshop Talk)
 
A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)
A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)
A "Do-It-Yourself" Specification Language with BeepBeep 3 (Talk @ Dagstuhl 2017)
 
Event Stream Processing with Multiple Threads
Event Stream Processing with Multiple ThreadsEvent Stream Processing with Multiple Threads
Event Stream Processing with Multiple Threads
 
A Few Things We Heard About RV Tools (Position Paper)
A Few Things We Heard About RV Tools (Position Paper)A Few Things We Heard About RV Tools (Position Paper)
A Few Things We Heard About RV Tools (Position Paper)
 
Solving Equations on Words with Morphisms and Antimorphisms
Solving Equations on Words with Morphisms and AntimorphismsSolving Equations on Words with Morphisms and Antimorphisms
Solving Equations on Words with Morphisms and Antimorphisms
 
Runtime monitoring de propriétés temporelles par (streaming) XML
Runtime monitoring de propriétés temporelles par (streaming) XMLRuntime monitoring de propriétés temporelles par (streaming) XML
Runtime monitoring de propriétés temporelles par (streaming) XML
 

Technologies intelligentes d'aide au développement d'applications web (WAQ 2018)

  • 1. 12 avril 2018 Technologies intelligentes d'aide au développement technique d'applications web Sylvain Hallé Université du Québec à Chicoutimi CRSNG NSERC
  • 2. 12 avril 2018 Qui suis-je? Professeur-chercheur au Département d'informatique et de mathématique, Université du Québec à Chicoutimi Titulaire de la Chaire de recherche du Canada en spécification, test et vérification de systèmes informatiques ($$$) La personne dans cette photo ;-)
  • 3. 12 avril 2018 $$ 60 étudiants depuis 2010 prix Best Paper Award en subventions de recherche (2010-2020) 4 3professeurs- chercheurs 100+ publications scientifiques 1 500 000 $
  • 6. 12 avril 2018 + ? Quelques projets du LIF... Librairie de event stream processing https://liflab.github.io/beepbeep-3 Utile pour tests en temps réel, analyse de logs, détection d'intrusions, ...
  • 7. 12 avril 2018 Quelques projets du LIF... Détection de bugs dans les jeux vidéo Monitoring d'appareils électriques
  • 8. 12 avril 2018 Quelques projets du LIF... Librairie d'automatisation d'expériences informatiques https://liflab.github.io/labpal Fonctions avancées de traçabilité LabLabPalPal À paraître dans IEEE Computer!
  • 9. 12 avril 2018 Quelques projets du LIF... LabLabPalPal Cell (0,2) in Table #3 The sum of column 2 in Table #2 Cell (0,2) in Table #2 The value of Cell (1,1) in Table #1 Value of time in Experiment #2 Cell (1,2) in Table #1 Value of name in Experiment #2 Cell (1,2) in Table #2 The value of Cell (5,1) in Table #1 Value of time in Experiment #6 Cell (5,2) in Table #1 Value of name in Experiment #6 Cell (2,2) in Table #2 The value of Cell (9,1) in Table #1 Value of time in Experiment #10 Cell (9,2) in Table #1 Value of name in Experiment #10
  • 10. 12 avril 2018 Quelques projets du LIF... Système de traçabilité sécurisé https://github.com/artichoke-x Basé sur une variante des blockchains ARTICHOKE $ DOCTOR PATIENT INSURANCE COMPANY PHARMACIST NURSE DOCUMENT Best Paper Award en 2016
  • 11. 12 avril 2018 Quelques projets du LIF... https://liflab.github.io/sealtest 3 4 1 a [n<2] / n=n+1 c a [n>1] 5 6 7 a n=0 b 2 c c d [n=0] d [n>0] d d 8 G (a → (X (b ∨ c))) Générateur de séquences de test Notre plus récent projet (en développement)
  • 14. 12 avril 2018 Notre enquête (2014-2016)
  • 15. 12 avril 2018 Pièce à conviction #1 Éléments superposés
  • 21. 12 avril 2018 La boîte a la bonne taille si l'utilisateur n'est pas logué
  • 22. 12 avril 2018 Pièce à conviction #2 Éléments qui dépassent de leur conteneur
  • 24. 12 avril 2018 Pièce à conviction #3 Propriété z-index incorrecte
  • 27. 12 avril 2018 Pièce à conviction #4 Mojibake!
  • 28. 12 avril 2018 Mojibake est un emprunt lexical du japonais qui signifie que les caractères affichés à l'écran d'un logiciel informatique ne s'affichent pas correctement, à cause d'un problème de codage. (Wikipedia) « » Pièce à conviction #4 Mojibake!
  • 30. 12 avril 2018 décembre 2015 décembre 2014
  • 31. 12 avril 2018 Pièce à conviction #5 Problèmes de zoom
  • 34. 12 avril 2018 Pièce à conviction #6 Cachez cet élément que je ne saurais voir
  • 35. 12 avril 2018 Pièce à conviction #6 Cachez cet élément que je ne saurais voir (Bug dans le thème WordPress)
  • 36. 12 avril 2018 Pièce à conviction #7 Irresponsive web design
  • 40. 12 avril 2018 Une minute... Tout de même, les bugs d'affichage ne mettent pas en danger la fonctionnalité d'une application... N'est-ce pas?
  • 41. 12 avril 2018 Pièce à conviction #8 Texte ton sur ton
  • 45. 12 avril 2018 Pièce à conviction #9 Trop d'échappement, c'est possible
  • 49. Pièce à conviction #10 Éléments inaccessibles 12 avril 2018
  • 50. On ne peut atteindre la partie gauche du popup 12 avril 2018
  • 51. On ne peut atteindre les boutons cachés 12 avril 2018
  • 52. 12 avril 2018 ...ça arrive même aux meilleurs!
  • 53. La boîte de texte disparaît si la fenêtre tombe sous une largeur précise (le scroll ne change rien) 12 avril 2018
  • 55. 12 avril 2018 Pièce à conviction #11 Problèmes de formulaires
  • 56. 12 avril 2018 Boîte pré-remplie avec 6 caractères, mais le champ a maxlength=5
  • 57. 12 avril 2018 Pièce à conviction #12 Une page dans une page
  • 58. 12 avril 2018 Pièce à conviction #12 Une page dans une page
  • 59. 12 avril 2018 Une minute... On ne peut pas observer l'état interne de l'application simplement à partir de son HTML... N'est-ce pas?
  • 60. Le bouton Fermer n'a aucun effet... on est coincé dans le popup! 12 avril 2018
  • 63. 12 avril 2018 Une minute... Si on observe la mise en page, on est limité à un seul moment dans le temps... N'est-ce pas?
  • 66. 12 avril 2018 En mettant le focus sur la boîte de texte... La propriété padding passe à 0 La boîte monte d'un pixel
  • 67. 12 avril 2018 Résultats de recherche incorrects https://youtu.be/zCg537MZ6Ww Clic droit déchaîné https://youtu.be/iw7x3H51TFo État de bouton incorrect https://youtu.be/NGbl4vP350s Élément clignotant https://youtu.be/luJXkenY0Oo
  • 68. 12 avril 2018 Pourquoi ces bugs sont-ils aussi fréquents?
  • 69. 12 avril 2018 Une partie de l'explication Les navigateurs ne font pas le même rendu du même code HTML/CSS (cross-browser layout problems) (C'est la faute aux navigateurs!)
  • 70. 12 avril 2018 ACID2 Test: la même page dans deux (vieux) navigateurs Safari (succès) Internet Explorer (échec)
  • 71. 12 avril 2018 Une minute... Presque tous les bugs que nous avons vus sont présents dans tous les navigateurs... ...alors est-ce uniquement de leur faute?
  • 72. 12 avril 2018 Une autre partie de l'explication CSS est complexe! Difficile de savoir si les propriétés réelles d'un élément correspondent à une règle CSS ("suggestion")
  • 73. 12 avril 2018 Une autre partie de l'explication CSS est complexe! Difficile de savoir si les propriétés réelles d'un élément correspondent à une règle CSS ("suggestion") #ext { width: 200px; } .foo { width: 150px; } <div id="ext"> <div class="foo">A</div> <div class="foo">B</div> </div>
  • 74. 12 avril 2018 Une autre partie de l'explication CSS est complexe! Difficile de savoir si les propriétés réelles d'un élément correspondent à une règle CSS ("suggestion") #ext { width: 200px; } .foo { width: 150px; } <div id="ext"> <div class="foo">A</div> <div class="foo">B</div> </div> #ext .foo .foo 300px
  • 76. 12 avril 2018 La règle 110
  • 77. 12 avril 2018 Une autre partie de l'autre partie de l'explication Pourcentage des applications web qui n'ont pas de suite de tests (source: ICST 2015) 86%
  • 78. 12 avril 2018 Les bugs liés à l'affichage peuvent révéler des problèmes de design, mais aussi de fonctionnalité d'une application Ils sont fréquents Ils ne sont pas forcément causés par le navigateur CSS peut donner des "suggestions", mais pas imposer des contraintes Conclusion: la détection de ces bugs doit se faire par un moyen externe à HTML/CSS
  • 79. 12 avril 2018 Solution #1 Observation "à l'oeil nu" par un testeur M. TEST Beaucoup de choses à vérifier (lent) Basé sur la compréhension du testeur C'est bizarre ici!
  • 80. 12 avril 2018 Solution #2 Programmer la vérification des contraintes sur l'interface avec un langage "traditionnel"
  • 81. 12 avril 2018 var textnodes = $(elem) .contents() .filter(function() { return this.nodeType === 3; //Node.TEXT_NODE }); var mojibake = ["é", "ô", "è"]; var contains = function(t, m) { var re = new RegExp(m, "g"); return re.match(t); }; evaluate = function() { for (var tn in textnodes) { var elem = $(tn); var text = tn.text(); for (var moj in mojibake) { if (contains(text, moj)) console.log("Error"); } } }; evaluate = function() { if (!evaluate.positions) { evaluate.positions = []; evaluate.positionindex = 0; $("li").each(function() { evaluate.positions.push({ "top" : $(this).offsetTop, "left" : $(this).offsetLeft }); $(this).uniqueid = evaluate.positionindex; evaluate.positionindex++; }); } $("li").each(function(index) { var uniqueid = $(this).uniqueid; if (uniqueid && ( evaluate.positions[uniqueid].top != $(this).offsetTop || evaluate.positions[uniqueid].left != $(this).left) ) console.log("Error"); }); };
  • 82. 12 avril 2018 ...et plusieurs autres! Si jQuery ne fait pas notre affaire, il existe d'autres solutions:
  • 83. 12 avril 2018 evaluate = function() { if (!evaluate.positions) { evaluate.positions = []; evaluate.positionindex = 0; $("li").each(function() { evaluate.positions.push({ "top" : $(this).offsetTop, "left" : $(this).offsetLeft }); $(this).uniqueid = evaluate.positionindex; evaluate.positionindex++; }); } $("li").each(function(index) { var uniqueid = $(this).uniqueid; if (uniqueid && ( evaluate.positions[uniqueid].top != $(this).offsetTop || evaluate.positions[uniqueid].left != $(this).left) ) console.log("Error"); }); }; Quelques problèmes... Expliquez ce que fait ce bout de code (en 5 secondes!)
  • 84. 12 avril 2018 evaluate = function() { if (!evaluate.positions) { evaluate.positions = []; evaluate.positionindex = 0; $("li").each(function() { evaluate.positions.push({ "top" : $(this).offsetTop, "left" : $(this).offsetLeft }); $(this).uniqueid = evaluate.positionindex; evaluate.positionindex++; }); } $("li").each(function(index) { var uniqueid = $(this).uniqueid; if (uniqueid && ( evaluate.positions[uniqueid].top != $(this).offsetTop || evaluate.positions[uniqueid].left != $(this).left) ) console.log("Error"); }); }; Quelques problèmes... Expliquez ce que fait ce bout de code (en 5 secondes!) Retourne juste "Error" ?!? Si on veut plus d'info, on doit écrire plus de code....
  • 85. 12 avril 2018 Solution #3 Approche intelligente! On écrit des énoncés lisibles qui expriment des contraintes que l'interface doit suivre La machine s'occupe de trouver comment les vérifier ≠ IA
  • 94. 12 avril 2018 Un langage pour exprimer des contraintes de haut niveau sur des interfaces web (ou autres) - DOM + attributs CSS - Quantification du premier ordre - Opérateurs temporels 1. Notre solution:
  • 95. 12 avril 2018 Un architecture pour intstrumenter une application web et rapporter les attributs pertinents à un interpréteur 2. Notre solution:
  • 96. 12 avril 2018 Un mécanisme pour vérifier automatiquement les propriétés et donner une explication si une contrainte est violée 3. Notre solution:
  • 97. 12 avril 2018 BEST TOOL Hallé, Bergeron, Guérin, Le Breton. Testing Web Applications Through Layout Constraints. Proc ICST 2015. https://github.com/liflab/cornipickle Notre solution:
  • 99. 12 avril 2018 Application under test Server
  • 100. 12 avril 2018 Application under test Server Probe creation Developer 1
  • 101. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2
  • 102. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3
  • 103. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4
  • 104. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5
  • 105. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7
  • 106. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8
  • 107. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko
  • 108. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9
  • 109. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9 {{tagname:"div",cornipickleid:1,props: {left:0,right:10,color:red,width:40},children: [{tagname:"span",cornipickleid:21,props: {left:20,right:145,color:black,width:120},children:[]}, {tagname:"p",cornipickleid:14,props: {left:0,right:10,color:red,width:40},children:[]}]}} ...
  • 110. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9 {{tagname:"div",cornipickleid:1,props: {left:0,right:10,color:red,width:40},children: [{tagname:"span",cornipickleid:21,props: {left:20,right:145,color:black,width:120},children:[]}, {tagname:"p",cornipickleid:14,props: {left:0,right:10,color:red,width:40},children:[]}]}} ... Probe log 10
  • 111. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9 {{tagname:"div",cornipickleid:1,props: {left:0,right:10,color:red,width:40},children: [{tagname:"span",cornipickleid:21,props: {left:20,right:145,color:black,width:120},children:[]}, {tagname:"p",cornipickleid:14,props: {left:0,right:10,color:red,width:40},children:[]}]}} ... Probe log 10 11
  • 112. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9 {{tagname:"div",cornipickleid:1,props: {left:0,right:10,color:red,width:40},children: [{tagname:"span",cornipickleid:21,props: {left:20,right:145,color:black,width:120},children:[]}, {tagname:"p",cornipickleid:14,props: {left:0,right:10,color:red,width:40},children:[]}]}} ... Probe log 10 11 Probe instructions (optional) 12
  • 113. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9 {{tagname:"div",cornipickleid:1,props: {left:0,right:10,color:red,width:40},children: [{tagname:"span",cornipickleid:21,props: {left:20,right:145,color:black,width:120},children:[]}, {tagname:"p",cornipickleid:14,props: {left:0,right:10,color:red,width:40},children:[]}]}} ... Probe log 10 11 Probe instructions (optional) 12 Dashboard (analytics) Developer 13
  • 114. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9 {{tagname:"div",cornipickleid:1,props: {left:0,right:10,color:red,width:40},children: [{tagname:"span",cornipickleid:21,props: {left:20,right:145,color:black,width:120},children:[]}, {tagname:"p",cornipickleid:14,props: {left:0,right:10,color:red,width:40},children:[]}]}} ... Probe log 10 11 Probe instructions (optional) 12 Dashboard (analytics) Developer 13 14
  • 115. 12 avril 2018 Application under test Server Probe creation Developer 1 Probe repository 2 Probe ID 3 <script ... "getprobe?uid=39f2ac8"> 4 Request for probe code 5 6 7 Probe code Probe (JS object) Probe retrieval 8 {if("INPUT"===e.tagName||"BUTTON"===e.tagName) return"range"===e.type||"number"==e.type? e.valueAsNumber:e.value},Cornipickle.CornipickleProbe.re freshDelay=500,Cornipickle.CornipickleProbe.elementCount er=0,Cornipickle.CornipickleProbe.clickThrough =!1,Cornipickle.CornipickleProbe.toggleClickThrough= function(){return Cornipickle.CornipickleProbe.clickThrough !=Cornipickle.CornipickleProbe.clickThrough, ... ~12 ko Probe interaction Probe status report 9 {{tagname:"div",cornipickleid:1,props: {left:0,right:10,color:red,width:40},children: [{tagname:"span",cornipickleid:21,props: {left:20,right:145,color:black,width:120},children:[]}, {tagname:"p",cornipickleid:14,props: {left:0,right:10,color:red,width:40},children:[]}]}} ... Probe log 10 11 Probe instructions (optional) 12 Dashboard (analytics) Developer 13 14 16 15
  • 116. 12 avril 2018 $ java -jar cornipickle.jar --port 12345 spec.cp Pour un usage local: Fichier texte contenant les contraintes à monitorer Port sur lequel écoute l'interpréteur Cornipickle Dans l'en-tête de l'application à tester, ajouter: <script src="http://localhost:12345/probe" /> C'est tout!
  • 120. 12 avril 2018 For each $x in $(css-selector) something about $x. There exists $x in $(css-selector) such that something about $x.
  • 121. 12 avril 2018 $x's prop is greater than $y's prop $x's height $x's text $x's color $x's prop matches "a string" ...et la plupart des attributs CSS et DOM ...et la plupart des fonctions usuelles
  • 122. 12 avril 2018 something And something else something Or something else Not something
  • 123. 12 avril 2018 For each $x in $(.item) $x's color equals "red". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> .item { color: red; }
  • 124. 12 avril 2018 VRAIFor each $x in $(.item) $x's color equals "red". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> .item { color: red; }
  • 125. 12 avril 2018 For each $x in $(.item) $x's color equals "red". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> .item { color: red; } .item:first-child { color: yellow; }
  • 126. 12 avril 2018 FAUXFor each $x in $(.item) $x's color equals "red". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> .item { color: red; } .item:first-child { color: yellow; }
  • 127. 12 avril 2018 For each $x in $(.item) $x's color equals "red". <ul> <li class="item">foo</li> <li class="item" style="color:blue">bar</li> </ul> .item { color: red; }
  • 128. 12 avril 2018 FAUXFor each $x in $(.item) $x's color equals "red". <ul> <li class="item">foo</li> <li class="item" style="color:blue">bar</li> </ul> .item { color: red; }
  • 129. 12 avril 2018 There exists $x in $(li) such that $x's text equals "foo". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> .item { color: red; }
  • 130. 12 avril 2018 VRAIThere exists $x in $(li) such that $x's text equals "foo". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> .item { color: red; }
  • 131. 12 avril 2018 There exists $x in $(li) such that $x's text equals "foo". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> $().ready(function() { $(".item").text(""); }
  • 132. 12 avril 2018 FAUXThere exists $x in $(li) such that $x's text equals "foo". <ul> <li class="item">foo</li> <li class="item">bar</li> </ul> $().ready(function() { $(".item").text(""); }
  • 133. 12 avril 2018 For each $x in $(#menu li) ( For each $y in $(#menu li) ( $x’s left equals $y’s left)). A list item Another list item A third list item The last list item
  • 134. 12 avril 2018 FAUXFor each $x in $(#menu li) ( For each $y in $(#menu li) ( $x’s left equals $y’s left)). A list item Another list item A third list item The last list item
  • 135. 12 avril 2018 We say that pattern When something. Exemple: We say that $x is wider than $y When $x's width is greater than $y's width. On peut définir soi-même des prédicats (genres de "macros") pour simplifier l'écriture.
  • 136. 12 avril 2018 We say that $x and $y are left- aligned when $x’s left equals $y’s left. For each $x in $(#menu li) ( For each $y in $(#menu li) ( $x and $y are left-aligned)). A list item Another list item A third list item The last list item
  • 137. 12 avril 2018 ... $(ul li) ... ... 's width ... ... $(p#abc) ... ... 's color ... La sonde JavaScript est sélective: elle ne renvoie que les attributs mentionnés dans une contrainte seulement pour les éléments qui correspondent à un des sélecteurs
  • 138. 12 avril 2018 { cornipickleid: 3, x: 300, y: 250, event: "click" ... Si un clic se produit dans la page, l'élément concerné possède un attribut spécial event dans le message renvoyé par la sonde: On peut mentionner cet attribut dans une expression comme toute autre propriété CSS.
  • 139. 12 avril 2018 (The Hitchhiker's Guide to the Galaxy)
  • 140. 12 avril 2018 (Quelque chose de compliqué ici) Spec, données, etc.
  • 141. 12 avril 2018 (Quelque chose de compliqué ici) Spec, données, etc. vrai/faux
  • 144. 12 avril 2018 Voyons le logiciel en action sur quelques exemples simples... https://www.youtu.be/90YitGRRx2w
  • 145. 12 avril 2018 Identifier les éléments responsables d'une violation ne nécessite aucun code Ce n'est qu'un sous-produit de l'évaluation des expressions
  • 146. 12 avril 2018 Il est possible de parler de l'état de l'interface à différents moments dans le temps au moyen d'opérateurs temporels.
  • 147. 12 avril 2018 Always something L'expression something doit toujours être vraie à partir de maintenant. maintenant something Il est possible de parler de l'état de l'interface à différents moments dans le temps au moyen d'opérateurs temporels.
  • 148. 12 avril 2018 Il est possible de parler de l'état de l'interface à différents moments dans le temps au moyen d'opérateurs temporels. Eventually something Il est possible de parler de l'état de l'interface à différents moments dans le temps au moyen d'opérateurs temporels. L'expression something doit être vraie au moins une fois dans le futur. maintenant something
  • 149. 12 avril 2018 Il est possible de parler de l'état de l'interface à différents moments dans le temps au moyen d'opérateurs temporels. Next something Il est possible de parler de l'état de l'interface à différents moments dans le temps au moyen d'opérateurs temporels. L'expression something doit être vraie dans le prochain instantané. maintenant something
  • 150. 12 avril 2018 Maintenant, mélangeons le tout!
  • 151. 12 avril 2018 Les opérateurs temporels permettent de décrire une séquence de pages et leur contenu Ouvre la porte à tester le comportement d'une application Faire la même chose avec du code procédural est plus compliqué (variables temporaires, conditions supplémentaires) Bonus: le mécanisme de feedback intelligent fonctionne toujours!
  • 152. 12 avril 2018 corni pickle We say that $x is immobile when ( Always ( When $x is now $y ( ($x's left equals $y's left) And ($x's top equals $y's top) ) ) ). For each $item in $(li) ( $item is immobile ). evaluate = function() { if (!evaluate.positions) { evaluate.positions = []; evaluate.positionindex = 0; $("li").each(function() { evaluate.positions.push({ "top" : $(this).offsetTop, "left" : $(this).offsetLeft }); $(this).uniqueid = evaluate.positionindex; evaluate.positionindex++; }); } $("li").each(function(index) { var uniqueid = $(this).uniqueid; if (uniqueid && ( evaluate.positions[uniqueid].top != $(this).offsetTop || evaluate.positions[uniqueid].left != $(this).left) ) console.log("Error"); }); };
  • 153. 12 avril 2018 corni pickle We say that I click on Go when ( There exists $b in $(button) such that ( ($b's text equals "Go") And ($b's event equals "mouseup") ) ). Always ( If (I click on Go) Then ( There exists $x in $(.value) such that ( The next time (I click on Go) Then ( There exists $y in $(.value) such that ( $x's text equals $y's text ) ) ) ) ). click_on_go = function(event) { return event.type === 'mouseup' && $(event.target).text() === "Go"; } evaluate = function(event) { if (click_on_go(event)) { var current_values = []; $(".value").each( evaluate.lastValues.push($(this).text()); ); if (evaluate.lastValues !== undefined) { var found = false; for (var v in current_values) { if ($.inArray(v, evaluate.lastValues)) found = true; break; } } } if (!found) console.log("Error"); evaluate.lastValues = current_values; } };
  • 154. 12 avril 2018 "La plupart des navigateurs" { {Part de marché (desktop) Part de marché (non-desktop) 75% 25%
  • 155. 12 avril 2018 Dans les bugs d'interface, le navigateur est parfois important On ne devrait pas prendre des décisions de design qui nous limitent dès le début (Selenium, plugin spécifique) Si votre app/site tourne dans le navigateur X, votre outil de test le devrait lui aussi!
  • 156. 12 avril 2018 For each $x in $(selector) blabla... There exists $y in $(selector) blabla... Les sélecteurs CSS sont fragiles. Des changements simples à la mise en page peuvent "endommager" vos contraintes.
  • 157. 12 avril 2018 Amélioration du feedback intelligent: suggestions de corrections Extension à WebDriver Passerelle avec outils d'intégration continue (Jenkins, Travis)
  • 161. 12 avril 2018 ✓ ✘ The Bottom Navigation can accommodate between 3 and 5 destinations.
  • 162. 12 avril 2018 ✓ ✘ The floatting button should not be hidden by other components.
  • 163. 12 avril 2018 ✓ ✘ The application should report by a color change if the number of characters allowed is exceeded.
  • 164. 12 avril 2018 L'interpréteur local de Cornipickle est open source et gratuit Nous pouvons personnaliser et étendre Cornipickle via des collaborations Projet d'intégration avec Eckinox Média (Alma) en cours (janvier-juillet 2017) sous financement de MITACS