Supposons que j'ai la fonction suivante et que j'ai besoin de la tester unitaire:
def move_files_to(files, path):
for file in files:
os.rename(file, path + "/" + file)
mes réflexions sur ce sujet:
Se moquer de os.rename ne mènerait à aucun résultat , d'un autre côté, avoir des fichiers et les renommer reviendrait à "faire des E / S", ce qui devrait être évité dans les tests unitaires. S'il vous plait corrigez moi si je me trompe. Les tests ont-ils un sens ici?
3 Réponses :
Ma recommandation serait de
créer un DirectoryTestCase (unittest.TestCase) avec
_tests sous tests / ) ii) crée un répertoire vide et iii) copie (tester) les fichiers. Deuxièmement, créez les tests sous ce cas de test. Vous pouvez tester le déplacement vers le même répertoire (renommer), vers un nouveau répertoire (sous le répertoire de test, doit-il créer s'il n'existe pas ou échouer?) Déplacer un lien symbolique, etc., le tout sous l'encapsulation du répertoire existant.
Si vous voulez que les tests s'exécutent en parallèle, donnez au répertoire un nom unique (aléatoire mais valide).
Exemple de code:
import unittest
import shutil
import os
import string
import random
class DirectoryTestCase(unittest.TestCase):
test_files = ['file.txt']
def setUp(self) -> None:
unique_string = ''.join(random.choices(string.digits, k=10))
self.path = os.path.join(os.path.dirname(__file__), '_temp' + unique_string)
shutil.rmtree(self.path, ignore_errors=True)
os.makedirs(self.path, exist_ok=True)
for file in self.test_files:
shutil.copy(file, self.path)
def tearDown(self) -> None:
shutil.rmtree(self.path, ignore_errors=True)
def test_basic(self):
# validate the existence of the file, not an actual test.
self.assertTrue(os.path.exists(os.path.join(self.path, 'file.txt')))
puisqu'il est difficile de simuler le module OS en python, vous pouvez ignorer pour écrire unitest
Mais le test unitaire signifie valider votre méthode unique avec quelques scénarios possibles, donc si vous pensez que cela doit valider à tout moment. alors un test unitaire est indispensable.
Il n'est pas nécessaire de tester os.rename , mais votre code doit être testé. Dans votre cas particulier, le moyen le plus simple est de patcher os.rename:
from unittest.mock import patch
def test_move_files():
files = ['a.txt', 'b.txt']
path = 'old'
expected = [(('a.txt', 'old/a.txt'),),
(('b.txt', 'old/b.txt'),)]
with patch('os.rename') as rename:
move_files_to(files, path)
assert rename.call_args_list == expected
Vous pouvez créer un fichier factice, le déplacer, faire un
os.path.existspour vous assurer qu'il a été déplacé puis le supprimer, toujours IO mais parfois ces tests peuvent être utiles pour attraper les exceptions que vous ne pouvez pas attraper avec monkeypatching.Si vous vous moquez de
os.rename (), vous pouvez toujours affirmer qu'il a été appelé avec les paramètres attendus. En général, je ne pense pas que ce type de test offre beaucoup de valeur, car vous devez essentiellement réimplémenter la fonction pour affirmer qu'elle fait les bons appels àos.rename (), mais cela aide toujours à assurez-vous que la fonction ne contient aucun identifiant mal saisi, etc.@SvenMarnach pourquoi ne postez-vous pas ceci comme réponse? Pour moi, cela semble être la solution la plus raisonnable
@SvenMarnach Je ferais également une vérification de
cheminpour m'assurer que les deux chemins fournis àos.renamesont valides.@David Je ne pense tout simplement pas qu'il y ait une «bonne» réponse ici. Dans de nombreux cas, je ne testerais pas personnellement cette fonction. C'est très simple, pylint détectera la plupart des fautes de frappe, et il existe peut-être un test d'intégration qui couvre cette fonction d'une manière ou d'une autre. Mais tout dépend du contexte, de la philosophie de test du projet et de vos préférences personnelles, j'ai donc préféré écrire ceci en commentaire.