• Aucun résultat trouvé

Property-based testing SVL - Cours-TD9

N/A
N/A
Protected

Academic year: 2022

Partager "Property-based testing SVL - Cours-TD9"

Copied!
40
0
0

Texte intégral

(1)

Property-based testing SVL - Cours-TD9

Mirabelle Nebut

Bureau 203 - M3 ext mirabelle.nebut at univ-lille.fr

Master 1 info S2 - 2016.2017

(2)

But de ce cours

Faire un retour sur l’´ecriture des tests

`a la lumi`ere de la programmation par contrats et de l’analyse statique de programmes.

(3)

Avec des contrats. . .

On peutprogrammer en supervisant ou non automatiquement les contrats (cf C#, JML).

On peut (tenter de)v´erifier que leprogrammeest conforme `a ses contrats(cf Spec#, openJML).

Mais quid du TDD ?

⇒Derri`ere chaque oraclese cache uncontrat implicite.

Mais pas tous les contrats, malheureusement. . . essentiellement lequel ?

(4)

Int´egrer l’esprit des contrats dans les tests Post-conditions

Pre-conditions Invariants

Property-based testing

Property-based testing avec Hypothesis Quelles propri´et´es utiliser ?

Lien avec les parameterized tests et theories de JUnit

(5)

Avec un test type TDD de base

public void testPaulDebiteSonCompte() { Compte compte = new Compte();

compte.crediter(50);

compte.debiter(12);

assertEquals(38, compte.solde()) }

Tel que c’est ´ecrit :

I le test pr´esente un exemple

I le contrat sous-jacent `a l’oracle ne saute pas aux yeux.

⇒quoi modifier en premi`ere approche ?

(6)

Avec un test type TDD, en mieux

public void

testPaulDebiteSonCompteLeSoldeEstDiminueDuMontant() { Compte compte = new Compte();

compte.crediter(50);

compte.debiter(12);

assertEquals(38, compte.solde()) }

Le nom du test doit faire apparaˆıtre la propri´et´e test´ee.

Chaque test doit ˆetre clairement reli´e :

I `a une fonctionnalit´e, unbesoin du client (cf nom de la classe de test)

I une propri´et´e du programme.

(7)

De l’oracle ` a la propri´ et´ e

La propri´et´e sous-jacente est :

//@ ensures solde = \old(solde) - montant;

public void debiter(float montant) { ... }

Mˆeme sans utiliser un langage de sp´ecification ou des contrats supervis´es, cettepost-condition existe.

Vous devez l’avoir en tˆete en ´ecrivant les tests.

(8)

Avec un oracle ` a la post-condition

public void

testPaulDebiteSonCompteLeSoldeEstDiminueDuMontant() { Compte compte = new Compte();

compte.crediter(50);

ancien_solde = compte.solde();

montant = 12;

compte.debiter(montant);

assertEquals(ancien_solde - montant, compte.solde()) }

I l’oracle est plus clair, mais pas le reste du test ;

I Il est souvent conseill´e dans les bonnes pratiques d’utiliser une constanteen durdans l’oracle.

I on peut r´ep´eter ce cas de test avec d’autres DT (ex : valeur limite).

(9)

Int´egrer l’esprit des contrats dans les tests Post-conditions

Pre-conditions Invariants

Property-based testing

Property-based testing avec Hypothesis Quelles propri´et´es utiliser ?

Lien avec les parameterized tests et theories de JUnit

(10)

2 cas selon le traitement des pr´ e-conditions

A la programmation d´` efensive:

I = lev´ee d’exception

I post-condition exceptionnelle

I mˆeme cons´equence sur l’oracle qu’une post-condition normale A la contrat` = pr´e-condition (supervis´ee ou non) :

I g´en´eralement on teste toujours `a l’int´erieur du domaine de la m´ethode

I ⇒ les pr´e-cond apparaissent implicitement dans le setUp, mais pas en tant qu’oracle

I dans le cas de l’utilisation syst´ematique de pr´e-conditions supervis´ees, il peut ˆetre utile de tester qu’on ne s’est pas tromp´e dans l’´ecriture de la spec.

(11)

Avec des post-conditions exceptionnelles

Le contrat implicite est :

//@ signals (MontantError) montant <= 0;

public void debiter(float montant) { ... } On peut ´ecrire le test ainsi :

public void

testPaulDebiteSonCompteAvecUnMontantNegatifEchec() { ...

montant_negatif = -2

with self.assertRaises(MontantError):

compte.debiter(montant_negatif);

}

(12)

Int´egrer l’esprit des contrats dans les tests Post-conditions

Pre-conditions Invariants

Property-based testing

Property-based testing avec Hypothesis Quelles propri´et´es utiliser ?

Lien avec les parameterized tests et theories de JUnit

(13)

Quels invariants ?

Les invariants, je ne vois pas `a quoi ¸ca sert un ´etudiant qui se reconnaˆıtra.

Un invariant d´ecrit une propri´et´e toujours vraiede toute instance d’une classe :

I le solde est toujours positif

I la tour est toujours tri´ee par taille de disque d´ecroissante

I un arbre est toujours ´equilibr´e

I l’indice de tableau est toujours compris dans ses bornes L’invariant porte surl’´etatde l’objet.

Une violation de l’invariant indique que l’objet de trouve dans un

´etat inconsistant.

(14)

Quels invariants ?

En programmation par contrats c’est une notion fondamentale :

I l’invariant est v´erifi´e avant et apr`es chaque appel de m´ethode.

I on peut le voir comme une post-condition implicite, mais c’est plus que ¸ca avec Spec#.

En v´erification c’est aussi une propri´et´e fondamentale `a prouver.

Mais chez les testeurs. . . souventon l’oublie.

Pas facile `a faire apparaˆıtre dans les tests.

(15)

Invariants et test

Rajoute-t-on un oracle codant l’invariant `a la fin de chaque test ? Ou dans une m´ethode detearDown?

Ou unassertdans le code ?

On n’atteindra pas la lisibilit´e d’un invariant sp´ecifi´e.

Qui plus est on rate letoujours vrai de toute instance.

(16)

Tests, documentation et sp´ ecification

Les tests jouent le rˆole de documentation / sp´ecification ex´ecutable par l’exemple.

On dit parfois que les tests sp´ecifient un contrat ou une propri´et´e, mais le terme tel quel me semble impropre.

Les tests n’ont pas vocation `a remplacer les sp´ecifications.

Les approches TDD / sp´ecification formelle des contrats sont compl´ementaires.

´Ecrire les contrats dans le code (`a titre informatif) s’int`egre bien avec le TDD, et indique quoi tester.

(17)

Limitation intrins` eque au test

On teste toujours pour des DT donn´ees, donc pour des cas particuliers.

Vs le contrat qui est implicitement quantifi´e universellement :

I la post-condition est vraie qqsoit les valeurs de ses param`etres

I l’invariant est vrai qqsoit les appels re¸cus par les instances Vs la v´erification effectu´ee par les analyses statiques.

(18)

Repousser les limites avec les contrats + g´ en´ erateurs de test

On peut g´en´erer automatiquement des donn´ees de test et des instances. . .

et v´erifier post-conditions et invariants pour les donn´ees qui satisfont les pr´e-conditions.

Cf AutoTest pour Eiffel, les outils pour JML.

Avantage : la g´en´eration al´eatoire d’un grand nombre de DT nous rapproche de la quantification universelle.

Inconv´enient : ne s’inscrit pas bien dans un d´eveloppement `a la TDD.

(19)

Repousser les limites avec le property-based testing

Principe :

I utiliser comme oracle une propri´et´e toujours vraie

I g´en´ererautomatiquement etal´eatoirementun grand nombre deDT

I voire g´en´erer aussi al´eatoirement des sc´enarios de test

(20)

Int´egrer l’esprit des contrats dans les tests Post-conditions

Pre-conditions Invariants

Property-based testing

Property-based testing avec Hypothesis Quelles propri´et´es utiliser ?

Lien avec les parameterized tests et theories de JUnit

(21)

Historique

Biblioth`eque QuickCkeck d’Haskell (1999).

Portage pour divers langages :

I Hypothesis pour Python (2015 ?)

I junit-quickcheck pour JUnit (d´ebuts en 2010 via les th´eories) Les principes sont tr`es bien expliqu´es dans cet expos´e de Scott Wlaschin :

http://fsharpforfunandprofit.com/pbt/

(22)

4 principes

1. g´en´erer al´eatoirement les donn´ees de testvues comme des param`etres pour les tests

2. utiliser un oracletout le temps vrai

3. shrinking : en cas d’´echec du test, trouver une DT minimale qui fait aussi ´echouer le test et est plus facile `a comprendre 4. g´en´erer al´eatoirement des sc´enarios de test

(23)

Int´egrer l’esprit des contrats dans les tests Post-conditions

Pre-conditions Invariants

Property-based testing

Property-based testing avec Hypothesis Quelles propri´et´es utiliser ?

Lien avec les parameterized tests et theories de JUnit

(24)

Principes

Biblioth`eque tr`es riche.

J’ai rencontr´e des pbs avec le shrinking pour la strat´egiefloats:

I tr`es grandes valeurs retourn´ees `a l’utilisateur

I ex : 2.882303761517118e+17

I du coup erreurs dans les calculs et contrats qui ´echouent.

⇒g´en´erer des entiers.

(25)

G´ en´ eration al´ eatoires des donn´ ees de test

Letest est param´etr´e par les valeurs `a g´en´erer al´eatoirement.

Le d´ecorateurgiven pr´ecise la strat´egie`a utiliser lors de la g´en´eration.

from hypothesis import given

from hypothesis.strategies import text, floats

@given(text())

def test_decode_inverts_encode(s):

...

@given(somme=floats(min_value=0.0))#, allow_nan=False))

# par d´efaut si min ou max utilis´e

def test_le_solde_est_augmente_sans_filter(self, somme):

...

(26)

D´ efinition de strat´ egies

from hypothesis.strategies import floats strat_float_strict_positif =

floats(min_value=0.0, allow_infinity=False) .filter(lambda s: s > 0)

strat_float_strict_negatif =

floats(max_value=0.0, allow_infinity=False) .filter(lambda s: s < 0)

strat_float_negatif_ou_nul = floats(max_value=0.0)

@given(somme=strat_float_strict_positif)

def test_le_solde_est_augmente(self, somme):

...

(27)

D´ efinition de strat´ egies compliqu´ ees

D´ecorateur compositepour composer arbitraitement des strat´egies.

from collections import namedtuple from hypothesis import composite SommeDecouvertSolde =

namedtuple(’SommeDecouvertSolde’,

[’somme’, ’decouvert’, ’solde_initial’])

@composite

def strat_solde_somme_decouvert(draw):

somme = draw(strat_float_strict_positif) decouvert = draw(strat_float_strict_negatif) solde_initial =

draw(floats(min_value = somme + decouvert) .filter(lambda x : x > 0))

return SommeDecouvertSolde(somme=somme,

decouvert=decouvert,

(28)

Combien d’exemples s´ electionne Hypothesis ?

Par d´efaut 200, se change par @settings.

Hypothesis tente une valeur en utilisant la strat´egie, et ressaie si elle ne passe pas lefilter.

Se voit parpytest --hypothesis-show-statistics test ...

Attention `a ne pas trop contraindre : si pas ou trop peu de donn´ees s´electionn´ees on s’´eloigne de l’objectif !

(29)

Compte-rendu g´ en´ er´ e par Hypothesis

test_even_integers:

- 200 passing examples, 0 failing examples, 16 invalid examples - Typical runtimes: < 1ms

- Stopped because settings.max_examples=200 - Events:

* 30.56%, Retried draw from integers().filter(lambda x: x % 2 == 0) to satisfy filter

* 7.41%, Aborted test because unable to satisfy integers().filter(lambda x: x % 2 == 0)

(30)

Assume

Pour supprimer des valeurs non d´esir´ees g´en´er´ees par une strat´egie.

assume expr`a mettre en tˆete de test.

G´en`ere une exception r´ecup´er´ee par Hypothesis.

A utiliser avec pr´` ecaution : Hypothesis essaie de trouver des donn´ees qui passent leassumemais n’en trouve pas toujours.

Privil´egier lesfilter.

(31)

G´ en´ eration al´ eatoires de sc´ enarios de test

Oustateful testing.

Implant´e par desRule based state machines.

Principe :

I peupler une collection d’objets (Bundle) avec des valeurs g´en´er´ees comme pr´ec´edemment ;

I appliquer al´eatoire aux objets du Bundle une suite al´eatoire d’appels `a des m´ethodes dont les param`etres sont g´en´er´es comme pr´ec´edemment.

I pr´evoir une m´ethode qui inclut une propri´et´e

Ainsi la propri´et´e sera v´erifi´ee sur un objet issu d’un setUp al´eatoire.

(32)

Exemple de la doc Hypothesis

Exemple des arbres ´equilibr´es (mais qui ne le sont pas).

Rajouter la syntaxe ici.

(33)

Int´egrer l’esprit des contrats dans les tests Post-conditions

Pre-conditions Invariants

Property-based testing

Property-based testing avec Hypothesis Quelles propri´et´es utiliser ?

Lien avec les parameterized tests et theories de JUnit

(34)

Le property-based testing a l’air cool !

Mais ce n’est pas simple de trouver les propri´et´es adapt´ees ! Propri´et´es type pr´econis´ees par la communaut´e fonctionnelle (cf expos´e Scott Wlaschin).

Apr`es, il faut pratiquer pour s’entraˆıner.

(35)

Propri´ et´ es pr´ econis´ ees

Different paths, same destination (commutativit´e) : add 1puis add 2idem que add 2puis add 1

There and back again: addition/subtraction, write/read,

setProperty/getProperty, ou encore insert/contains, create/exists Some things never change : lesinvariants!

The more things change, the more they stay the same : idempotence

propri´et´es inductives pour structure de donn´ees r´ecursives

Hard to prove, easy to verify : ex si on concat`ene les tokens ´emis par un lexeur, on retrouve l’entr´ee

(36)

Questions sur le PBT objet

I Quelle int´egration avec le TDD ?

I Compl´ementaire du TDD ?

I Peut-on exprimer tout oracle en PBT de mani`ere simple ? Ou n’est-ce pas fait pour ¸ca ?

I Peut-on utiliser le PBT pour tester un invariant en g´en´erant al´eatoirement les sc´enarios de test ? par ex quand Spec# nous dit que l’invariant n’est pas v´erifi´e et qu’on ne comprend pas pourquoi ?

(37)

Exemple de test d’invariant

Reprise de l’ex du DS de test.

(38)

Int´egrer l’esprit des contrats dans les tests Post-conditions

Pre-conditions Invariants

Property-based testing

Property-based testing avec Hypothesis Quelles propri´et´es utiliser ?

Lien avec les parameterized tests et theories de JUnit

(39)

Parameterised test

I le test est appel´e de mani`ere r´ep´et´ee sur une collection de DT

I mais les DT sont fournies par l’utilisateur.

I pas de g´en´eration de DT

I syntaxe lourdingue

(40)

Theories

https://github.com/junit-team/junit4/wiki/Theories Mˆeme principe que le parameterized tests mais :

I la syntaxe est plus heureuse (@DataPoint)

I le assumeThatpermet de filtrer des DT

I possibilit´e d’´ecrire son propre fournisseur de valeurs

Références

Documents relatifs

Dans un second temps, nous nous efforce- rons de nous lib´ erer de la contrainte d’exploiter un mod` ele num´ erique d’´ el´ evation – sources disponibles gratuitement mais avec

Les trois fa¸ cons principales de calculer des ´ ecarts types et les intervalles de confiance pour les changements pr´ edits : par l’utilisation de la matrice variance-covariance

[r]

Programme des enseignements – Syst` emes d’information et conception d’entrepˆ ots de donn´ ees – Les principes et la d´ emarche du Data Mining (fouille de donn´ ees)

Puisque le temps d’ex´ ecution d’un algorithme sur une entr´ ee de taille constante est une constante, les r´ ecurrences sous-jacentes au calcul du temps d’ex´ ecution

Une exp´ erience par coloration a montr´ e qu’une rivi` ere souterraine alimente une r´ esurgence dans la vall´ ee. La rivi` ere souterraine a un d´ ebit tr` es sensible aux

Perdre ses photos de vacances : ¸ca n’a pas de

Interrogeons nous maintenant sur la fa¸con dont sont construits ces tests multidimensionnels, autrement dit sur la fa¸con dont sont obtenues les matrices E pour les erreurs du