Dans cette mission, vous allez approfondir votre compréhension de concepts importants de la programmation orientée objets déjà abordés dans les deux missions précédentes, ainsi que quelques nouveaux concepts :
- les classes, objets, variables et méthodes instance ;
- les variables et méthodes de classe ;
- les variables et méthodes privés, les méthodes accesseurs et mutateurs ;
- la portée des variables d'instance ;
- l'héritage, la redéfinition et l'écrasement de méthodes, le polymorphisme ;
- la liaison dynamique et les subtilités de la sémantique de self et super().
Vous aurez également l'occasion d'écrire des tests unitaires pour vos programmes orientés objets.
Si vous n'avez pas encore eu le temps de relire en détail les différents chapitres de la partie Objects du syllabus en ligne, maintenant est venu le moment de rattraper votre retard. Le syllabus explique bien différents concepts, sur un autre exemple que les exemples utilisés dans le cours magistral :
On vous conseille également de tester et de jouer avec les différents exemples de code qui se trouvent dans les annexes suivantes, venant soit du syllabus en ligne soit correspondant aux exemples du cours magistral :
Dans cette mission, vous devrez également utiliser le framework unittest pour produire des classes de test. En préparation de cette mission, consultez donc la documentation de ce cadre de test, et essayez de faire quelques classes test simple en utilisant cet approche. Un bon tutoriel (en français) sur les tests unitaires avec unittest se trouve également ici Créez des tests unitaires avec unittest
Les questions à choix multiples de cette mission sont accessibles en ligne depuis https://inginious.info.ucl.ac.be/course/LSINF1101-PYTHON/Session10_2019_QCM
On vous donne le code suivant qui teste certaines fonctionnalités du module random.
import unittest import random class RandomTest(unittest.TestCase): """Clases de test utilisé pour tester les fonctions du module 'random'""" def setUp(self): """Initialisation des tests.""" self.l = list(range(10)) def test_choice(self): """Test de fonctionnement de la fonction random.choice""" e = random.choice(self.l) # Vérifie que 'e' est dans 'l' self.assertIn(e,self.l) def test_shuffle(self): """Test le fonctionnement de la fonction random.shuffle""" random.shuffle(self.l) self.l.sort() self.assertEqual(self.l, list(range(10))) def test_sample(self): """Test le fonctionnement de la fonction random.sample""" extrait = random.sample(self.l, 5) for element in extrait: self.assertIn(element,self.l) self.assertRaises(ValueError, random.sample, self.l, 20) # To automatically launch this test when executing this file if __name__ == '__main__': unittest.main()
Considérant cette classe, on vous demande de :
Expliquez cet extrait de code
if __name__ == '__main__': unittest.main()
Implémentez une classe de tests unitaires MyClassTest qui hérite de unittest.TestCase qui teste la fonction carre_parfait du module totest. (En mathématiques, un carré parfait est le carré d'un entier.)
Soit la fonction carre_parfait du module totest ayant pour spécifications :
def carre_parfait (x) : ''' retourne true si l'entier en argument est un carré parfait, false sinon ''' # CODE NON FOURNI
Complétez la classe de test ci-dessous :
import totest import unittest class MyClassTest(unittest.TestCase) : # todo if __name__ == '__main__': unittest.main()
Que donnent-vos tests unitaires pour les implémentations suivantes :
def carre_parfait (x) : return True
def carre_parfait (x) : return False
def carre_parfait (x) : cur = 0 while not cur*cur == x : cur += 1 return True
import math def carre_parfait (x) : root = math.sqrt(x) return root.is_integer()
import math def carre_parfait (x) : if x < 0 : return False root = math.sqrt(x) return root.is_integer()