Écrivez du code FizzBuzz piloté par les tests à l'aide de Python doctest.

introduction

J'ai écrit un programme FizzBuzz piloté par des tests en utilisant la bibliothèque doctest standard.

Qu'est-ce que doctest (citation)

http://docs.python.jp/2/library/doctest.html (Commencez à citer) Le module doctest recherche du texte qui ressemble à une session Python interactive, exécute le contenu de la session et voit s'il se comporte exactement comme il est écrit. doctest est souvent utilisé aux fins suivantes.

Vérifiez que le contenu de la docstring est à jour en vérifiant que tous les exemples d'exécution interactive dans la docstring (chaîne de documentation) du module fonctionnent comme écrit. Un test de régression est réalisé en vérifiant que les exemples d'exécution interactive dans le fichier de test ou l'objet de test fonctionnent comme prévu. Vous pouvez rédiger un document de didacticiel pour un package qui utilise de nombreux exemples d'entrée / sortie. Un document peut être un "test lisible" ou un "document exécutable", selon que vous vous concentrez sur des exemples d'entrée / sortie ou des commentaires. (Fin de la citation)

doctest semble être un excellent outil qui peut être utilisé pour les tests de régression lors de la vérification des documents (commentaires). Je n'ai pas d'autre choix que d'essayer ça.

Méthode de développement pilotée par les tests (devis)

http://www.atmarkit.co.jp/ait/articles/1403/05/news035.html (Commencez à citer (titre uniquement)) [1] Ecrire un code de test qui échoue [2] Écrivez le code à tester pour que le test passe de l'échec au succès [3] Ajoutez un code de test qui provoque l'échec du test [4] Écrivez le code à tester pour que le test passe de l'échec au succès [5] Refactoriser tout en maintenant le test réussi (Fin de la citation)

Cette fois, nous suivrons cette méthode.

Spécifications de cette fonction

J'ai décidé les spécifications de manière appropriée. Nom de la fonction: fizzbuzz (n) une fonction: Si la valeur d'entrée n est un multiple de 3, la chaîne 'Fizz' est renvoyée et Si la valeur d'entrée n est un multiple de 5, la chaîne "Buzz" est renvoyée et Si la valeur d'entrée n est un multiple de 15, la chaîne 'FizzBuzz' est renvoyée et Autre que cela, une fonction qui génère l'entier n.

n doit être un entier représenté par un type entier, un type entier long ou un type minoritaire à virgule flottante. (Pour le type minoritaire à virgule flottante, la partie fractionnaire doit être 0.) Si un petit nombre est entré, une exception InputError est renvoyée.

[1] Ecrire un code de test qui échoue

Tout d'abord, la mise en œuvre temporaire

def fizzbuzz(n):
  '''
Si la valeur d'entrée n est un multiple de 3'Fizz'Renvoie la chaîne
Si la valeur d'entrée n est un multiple de 5'Buzz'Renvoie la chaîne
Si la valeur d'entrée n est un multiple de 15'FizzBuzz'Renvoie la chaîne
Autre que cela, une fonction qui génère l'entier n.
Exemple:
  >>> fizzbuzz(3)
  'Fizz'
  
n doit être un entier représenté par un type entier, un type entier long ou un type minoritaire à virgule flottante.
(Pour le type minoritaire à virgule flottante, la partie fractionnaire doit être 0.)
Si un petit nombre est entré, InputError est renvoyé.
  '''
  
  return 'Fizz'

if __name__ == '__main__':
  import doctest
  doctest.testmod()

Exécuter (-v est une option pour une sortie détaillée). Si vous n'ajoutez pas -v, les informations ne seront générées que lorsque le test échoue.

python fizzbuzz_doctest.py -v 

Dans cet état, ok sort.

Essayez d'ajouter un cas de test

>>> fizzbuzz(5)
'Buzz'

L'erreur suivante est sortie.

File "fizzbuzz_doctest.py", line12, in __main__.fizzbuzz
Failed example:
    fizzbuzz(5)
Expected:
    'Buzz'
Got:
    'Fizz'
1 items had no tests:
    __main__

[2] Écrivez le code à tester pour que le test passe de l'échec au succès

Modifiez comme suit.

  if (n%3) == 0:
    return 'Fizz'
  elif (n%5) == 0:
    return 'Buzz'

[3] Ajoutez un code de test qui provoque l'échec du test

Répéter ce qui précède [1]

[4] Écrivez le code à tester pour que le test passe de l'échec au succès

Répéter ce qui précède [2]

Supplément

Les tests d'exception semblent nécessiter de commencer par Traceback. De plus, vous pouvez omettre la ligne médiane avec ....

  >>> fizzbuzz(5.5)
  Traceback (most recent call last):
      ...
  ValueError: n must be integer. n: 5.500000

Code (étape intermédiaire)

# coding: utf-8

def fizzbuzz(n):
  '''
Si la valeur d'entrée n est un multiple de 3'Fizz'Renvoie la chaîne
Si la valeur d'entrée n est un multiple de 5'Buzz'Renvoie la chaîne
Si la valeur d'entrée n est un multiple de 15'FizzBuzz'Renvoie la chaîne
Autre que cela, une fonction qui génère l'entier n.
Exemple:
  >>> fizzbuzz(3)
  'Fizz'
  
  >>> fizzbuzz(36)
  'Fizz'
  
  >>> fizzbuzz(5)
  'Buzz'
  
  >>> fizzbuzz(50)
  'Buzz'
  
  >>> fizzbuzz(15)
  'FizzBuzz'
  
  >>> fizzbuzz(45)
  'FizzBuzz'
  
  >>> fizzbuzz(2)
  2
  
  >>> fizzbuzz(49)
  49
  
n doit être un entier représenté par un type entier, un type entier long ou un type minoritaire à virgule flottante.
(Pour le type minoritaire à virgule flottante, la partie fractionnaire doit être 0.)
Si un petit nombre est entré, ValueError est renvoyé.
  
  >>> fizzbuzz(1.0)
  1

  >>> fizzbuzz(5.0)
  'Buzz'
  
  >>> fizzbuzz(5.5)
  Traceback (most recent call last):
      ...
  ValueError: n must be integer. n: 5.500000
  
  '''
  if n != int(n):
    raise ValueError( 'n must be integer. n: %f' % n )
  n = int(n)

  if (n%15) == 0:
    return 'FizzBuzz'
  elif (n%3) == 0:
    return 'Fizz'
  elif (n%5) == 0:
    return 'Buzz'
  else:
    return n

if __name__ == '__main__':
  import doctest
  doctest.testmod()

[5] Refactoriser tout en maintenant le test réussi

Il semble que le code final puisse être obtenu par refactoring tout en assurant le fonctionnement par des tests.

Par exemple, vous pouvez apporter les modifications suivantes: Afin de réduire le coût de référence de l'instruction if, créez une liste avec le reste divisé par 15 de 1 à 15 à l'avance, et déterminez la chaîne de caractères à renvoyer en vous référant à cette liste.

  '''
  if (n%15) == 0:
    return 'FizzBuzz'
  elif (n%3) == 0:
    return 'Fizz'
  elif (n%5) == 0:
    return 'Buzz'
  else:
    return n
  '''
  
  fizzbuzz_list = []
  for i in range(15):
    if (i%15) == 0:
      fizzbuzz_list.append('FizzBuzz')
    elif (i%5) == 0:
      fizzbuzz_list.append('Buzz')
    elif (i%3) == 0:
      fizzbuzz_list.append('Fizz')
    else:
      fizzbuzz_list.append(0)
  r = int(n%15)
  return fizzbuzz_list[r] if fizzbuzz_list[r] else n

Vous pouvez effectuer un test de régression avec la commande suivante sans écrire de nouveau test.

python fizzbuzz_doctest.py -v

Changeons encore l'algorithme.

  '''
  if (n%15) == 0:
    return 'FizzBuzz'
  elif (n%3) == 0:
    return 'Fizz'
  elif (n%5) == 0:
    return 'Buzz'
  else:
    return n

  
  fizzbuzz_list = []
  for i in range(15):
    if (i%15) == 0:
      fizzbuzz_list.append('FizzBuzz')
    elif (i%5) == 0:
      fizzbuzz_list.append('Buzz')
    elif (i%3) == 0:
      fizzbuzz_list.append('Fizz')
    else:
      fizzbuzz_list.append(0)
  '''

  fizzbuzz_list =  ['FizzBuzz', 0, 0, 'Fizz', 0, 'Buzz', 'Fizz', 0, 0, 'Fizz', 'Buzz', 0, 'Fizz', 0, 0 ]
  r = n%15
  return fizzbuzz_list[r] if fizzbuzz_list[r] else n

Vous pouvez exécuter le test de régression avec la commande suivante comme auparavant.

python fizzbuzz_doctest.py -v

Code final

Non seulement le code mais aussi la documentation sont complets.

# coding: utf-8

def fizzbuzz(n):
  '''
Si la valeur d'entrée n est un multiple de 3'Fizz'Renvoie la chaîne
Si la valeur d'entrée n est un multiple de 5'Buzz'Renvoie la chaîne
Si la valeur d'entrée n est un multiple de 15'FizzBuzz'Renvoie la chaîne
Autre que cela, une fonction qui génère l'entier n.
Exemple:
  >>> fizzbuzz(3)
  'Fizz'
  
  >>> fizzbuzz(36)
  'Fizz'
  
  >>> fizzbuzz(5)
  'Buzz'
  
  >>> fizzbuzz(50)
  'Buzz'
  
  >>> fizzbuzz(15)
  'FizzBuzz'
  
  >>> fizzbuzz(45)
  'FizzBuzz'
  
  >>> fizzbuzz(2)
  2
  
  >>> fizzbuzz(49)
  49
  
n doit être un entier représenté par un type entier, un type entier long ou un type minoritaire à virgule flottante.
(Pour le type minoritaire à virgule flottante, la partie fractionnaire doit être 0.)
Si un petit nombre est entré, ValueError est renvoyé.
  
  >>> fizzbuzz(1.0)
  1
  
  >>> fizzbuzz(5.0)
  'Buzz'
  
  >>> fizzbuzz(5.5)
  Traceback (most recent call last):
      ...
  ValueError: n must be integer. n: 5.500000
  
  '''
  if n != int(n):
    raise ValueError( 'n must be integer. n: %f' % n )
  n = int(n)

  fizzbuzz_list = ['FizzBuzz', 0, 0, 'Fizz', 0, 'Buzz', 'Fizz', 0, 0, 'Fizz', 'Buzz', 0, 'Fizz', 0, 0 ]
  r = n%15
  return fizzbuzz_list[r] if fizzbuzz_list[r] else n

if __name__ == '__main__':
  import doctest
  doctest.testmod()

Conclusion

Il semble facile à utiliser car vous pouvez tester et créer des documents à la fois. Il a été souligné que le code devient difficile à lire car les commentaires sont longs, mais les deux avantages sont que quitter le document améliore la maintenabilité et que la qualité peut être garantie en exécutant le test de régression. se sentir comme.

Recommended Posts

Écrivez du code FizzBuzz piloté par les tests à l'aide de Python doctest.
Écrivez FizzBuzz sans utiliser "="
Ecrire le code de test du sélénium en python
Vérifiez le style de code python à l'aide de pep8
Écrivez le code de contrat Ethereum en utilisant Serpent
Exécuter du code Python sur C ++ (en utilisant Boost.Python)
Obtenez des métriques de code source Python à l'aide de radon
Ecrire FizzBuzz en utilisant map (), reduction (), filter (), récursif
Ecrire un module python dans fortran en utilisant f2py
python setup.py tester le code en utilisant le multiprocessus
FizzBuzz en Python3
Écrire du code de type python
Écrivons FizzBuzz avec une erreur: Version Python
Déboguer avec VS Code en utilisant Boost Python Numpy
Commencez à utiliser Python
code de caractère python
FizzBuzz en Python
[Python] Code conscient des algorithmes
Scraping à l'aide de Python
Je veux écrire en Python! (1) Vérification du format de code
Structure de répertoire pour le développement piloté par les tests à l'aide de pytest en python
[Python] J'ai immédiatement essayé d'utiliser l'extension VS Code de Pylance.
Écrivons du code python qui analyse le code go et génère du code go
Comment créer un package Python à l'aide de VS Code
Écrire des données dans KINTONE à l'aide du module de requêtes Python
Lire et écrire des balises NFC avec python en utilisant PaSoRi
Écrire du code dans UnitTest une application Web Python
[Introduction à Python] Comment écrire des instructions répétitives à l'aide d'instructions for
Écrire du code semblable à Python (dictionnaire)
Manipuler Redmine à l'aide de Python Redmine
Séquence de Fibonacci utilisant Python
Réécrire le code Python2 en Python3 (2to3)
infomap code de dessin Python
Avant d'écrire du code Python
Ecrire Python dans MySQL
Nettoyage des données à l'aide de Python
Utilisation des packages Python #external
Câblage Communication Pi-SPI avec Python
Calcul de l'âge à l'aide de python
Rechercher sur Twitter avec Python
Identification de nom à l'aide de python
Code d'état des requêtes Python
Notes sur l'utilisation de sous-processus Python
J'ai essayé d'utiliser doctest
Essayez d'utiliser Tweepy [Python2.7]
[Introduction à Python] Comment écrire des branches conditionnelles en utilisant des instructions if
[Python] Chapitre 01-03 À propos de Python (Ecrire et exécuter un programme à l'aide de PyCharm)