Notebook originel: exo_poo.ipynb
Exercice POO/DDT🔗
POO: Programmation Orientée Objet
DDT: Développement Dirigé par les Tests
Vous devez corriger le code jusqu’à ce que tous les tests passent avec succès:
test_empty_init (__main__.AnimalTestCase) ... ok
test_init (__main__.AnimalTestCase) ... ok
test_lt (__main__.AnimalTestCase) ... ok
test_mange (__main__.AnimalTestCase) ... ok
test_mort (__main__.AnimalTestCase) ... ok
test_str (__main__.AnimalTestCase) ... ok
test_wrong_init (__main__.AnimalTestCase) ... ok
test_init (__main__.ChienTestCase) ... ok
----------------------------------------------------------------------
Ran 8 tests in 0.008s
OK
[1]:
class Animal:
"""
Classe définissant un `Animal`, caractérisé par son nom et son poids.
"""
def __init__(self, nom, masse):
"""
Méthode d'instanciation à partir d'un nom (str) et d'un poids (float).
"""
# Ici, convertir les paramètres pour être sûr qu'ils ont le bon
# type. On utilisera `str` et `float`
self.nom = nom
self.masse = masse
self.vivant = False # Les animaux sont supposés vivants à l'instanciation
self.empoisonne = False # Animal empoisonné ?
def __str__(self):
"""
Surcharge de l'opérateur `str`: l'affichage *informel* de l'objet
dans l'interpréteur, p.ex. `print self` sera résolu comme
`self.__str__()`
Retourne une chaîne de caractères.
"""
return self.nom
def estVivant(self):
"""Méthode booléenne, vraie si l'animal est vivant."""
return False
def mourir(self):
"""Change l'état interne de l'objet (ne retourne rien)."""
pass # Opération nulle
def __lt__(self, other):
"""
Surcharge l'opérateur de comparaison '<' uniquement, sur la
base de la masse des animaux.
Note: Py3 impose de surcharger *explicitement* tous les opérateurs
de comparaison: '__lt__' pour '<', __le__ pour '<=', '__eq__'
pour '==', etc.
"""
return False
def __call__(self, other):
"""
Surcharge de l'opérateur '()' pour manger un autre animal (qui
meurt s'il est vivant) et prendre du poids (mais pas plus que
la masse de l'autre ou 10 % de son propre poids). Attention aux
animaux empoisonnés !
L'instruction `self(other)` sera résolue comme
`self.__call__(other).
"""
raise NotImplementedError()
[2]:
class Chien(Animal):
"""
Un `Chien` hérite de `Animal` avec des méthodes additionnelles
(p.ex. l'aboiement et l'odorat).
"""
def __init__(self, nom, masse=20, odorat=0.5):
"""Définit un chien plus ou moins fin limier."""
# Initialisation de la classe parente
Animal.__init__(self, nom, masse)
# Attribut propre à la classe dérivée
self.odorat = float(odorat)
def aboyer(self):
"""Une méthode bien spécifique aux chiens."""
print("Miaou...")
def estVivant(self):
"""Quand on vérifie qu'un chien est vivant, il aboie."""
vivant = Animal.estVivant(self)
if vivant:
self.aboyer()
return vivant
Tests de correction🔗
NE PAS MODIFIER/EFFACER!
[3]:
import unittest # Module standard de tests
class AnimalTestCase(unittest.TestCase):
def test_01_empty_init(self):
with self.assertRaises(TypeError):
Animal()
def test_02_wrong_init(self):
with self.assertRaises(ValueError):
Animal('Youki', 'lalala')
def test_03_init(self):
youki = Animal('Youki', 600)
self.assertEqual(youki.masse, 600)
self.assertTrue(youki.vivant)
self.assertFalse(youki.empoisonne)
def test_04_str(self):
youki = Animal('Youki', 600)
self.assertEqual(str(youki), 'Youki (600.0 kg)')
def test_05_mort(self):
youki = Animal('Youki', 600)
self.assertTrue(youki.estVivant())
youki.mourir()
self.assertFalse(youki.estVivant())
def test_06_lt(self):
medor = Animal('Medor', 600)
kiki = Animal('Kiki', 20)
self.assertLess(kiki, medor)
with self.assertRaises(AttributeError):
medor < 1
def test_07_mange(self):
medor = Animal('Medor', 600)
kiki = Animal('Kiki', 20)
medor(kiki) # Médor mange Kiki
self.assertTrue(medor.estVivant())
self.assertFalse(kiki.estVivant())
self.assertEqual(kiki.masse, 0)
self.assertEqual(medor.masse, 620)
kiki = Animal("Kiki Jr.", 20)
kiki(medor) # Kiki Jr. mange Médor
self.assertFalse(medor.estVivant())
self.assertTrue(kiki.estVivant())
self.assertEqual(kiki.masse, 22)
self.assertEqual(medor.masse, 618) # Médor a perdu du poids en se faisant manger!
class ChienTestCase(unittest.TestCase):
def setUp(self):
"""
Initialisation du test.
Redirige le stdout, pour intercepter les affichages émis pendant les tests.
"""
import sys
from io import StringIO
sys.stdout = StringIO()
def test_11_init(self):
medor = Chien('Medor', 600)
self.assertIsInstance(medor, Animal)
self.assertIsInstance(medor, Chien)
self.assertEqual(medor.odorat, 0.5)
self.assertEqual(str(medor), 'Medor (Chien, 600.0 kg)')
# Cette fonction génère un affichage, intercepté par setUp
self.assertTrue(medor.estVivant())
def test_12_aboyer(self):
medor = Chien('Medor', 600)
# Cette fonction génère un affichage, intercepté par setUp
medor.aboyer()
self.assertEqual(sys.stdout.getvalue().rstrip(), "Ouaf ! Ouaf !")
unittest.main(argv=[''], verbosity=2, exit=False)
test_01_empty_init (__main__.AnimalTestCase) ... ok
test_02_wrong_init (__main__.AnimalTestCase) ... FAIL
test_03_init (__main__.AnimalTestCase) ... FAIL
test_04_str (__main__.AnimalTestCase) ... FAIL
test_05_mort (__main__.AnimalTestCase) ... FAIL
test_06_lt (__main__.AnimalTestCase) ... FAIL
test_07_mange (__main__.AnimalTestCase) ... ERROR
test_11_init (__main__.ChienTestCase) ... FAIL
test_12_aboyer (__main__.ChienTestCase) ... ERROR
======================================================================
ERROR: test_07_mange (__main__.AnimalTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 39, in test_07_mange
medor(kiki) # Médor mange Kiki
File "/tmp/ipykernel_494240/836056130.py", line 63, in __call__
raise NotImplementedError()
NotImplementedError
======================================================================
ERROR: test_12_aboyer (__main__.ChienTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 79, in test_12_aboyer
self.assertEqual(sys.stdout.getvalue().rstrip(), "Ouaf ! Ouaf !")
NameError: name 'sys' is not defined
======================================================================
FAIL: test_02_wrong_init (__main__.AnimalTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 10, in test_02_wrong_init
with self.assertRaises(ValueError):
AssertionError: ValueError not raised
======================================================================
FAIL: test_03_init (__main__.AnimalTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 16, in test_03_init
self.assertTrue(youki.vivant)
AssertionError: False is not true
======================================================================
FAIL: test_04_str (__main__.AnimalTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 21, in test_04_str
self.assertEqual(str(youki), 'Youki (600.0 kg)')
AssertionError: 'Youki' != 'Youki (600.0 kg)'
- Youki
+ Youki (600.0 kg)
======================================================================
FAIL: test_05_mort (__main__.AnimalTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 25, in test_05_mort
self.assertTrue(youki.estVivant())
AssertionError: False is not true
======================================================================
FAIL: test_06_lt (__main__.AnimalTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 32, in test_06_lt
self.assertLess(kiki, medor)
AssertionError: <__main__.Animal object at 0x7f59d1f0c880> not less than <__main__.Animal object at 0x7f59d1f0cc10>
======================================================================
FAIL: test_11_init (__main__.ChienTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_494240/2359231549.py", line 71, in test_11_init
self.assertEqual(str(medor), 'Medor (Chien, 600.0 kg)')
AssertionError: 'Medor' != 'Medor (Chien, 600.0 kg)'
- Medor
+ Medor (Chien, 600.0 kg)
----------------------------------------------------------------------
Ran 9 tests in 0.004s
FAILED (failures=6, errors=2)
[3]:
<unittest.main.TestProgram at 0x7f59d1e5ee90>
[ ]:
Cette page a été générée à partir de
exo_poo.ipynb.