Voici l'article sur le 10ème jour de Inatatsu Adcare.
Dans la continuité de la dernière fois, cette fois est la note de participation de Do Mob Programming in Kansai ~ Hin ??.
Cette fois, j'écrirai à quoi ressemble le TDD en fonction des faits (légèrement modifiés) du flux lors de l'exécution du TDD pour la première fois.
Démarrez pytest, FizzBuzz de la même manière que Article précédent. Si vous pouvez le tester et vous mettre en colère, mettez-le en œuvre pour ne pas vous mettre en colère.
Le test a réussi et il est devenu vert. Jusqu'à ce point, c'est la même chose que la dernière fois.
Vous avez maintenant confirmé que le test réussit s'il répond à vos exigences.
Maintenant que hiker est obsolète, réécrivons hiker.py et test_hiker.py en fizzbuzz pour répondre à cette demande.
Il n'y a pas de module comme randonneur! J'étais faché. Réécrivons-le correspondant à divers fizzbuzz.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
test_fizzbuzz.py
import fizzbuzz
def test_life_the_universe_and_everything():
'''a simple example to start you off'''
douglas = fizzbuzz.FizzBuzz()
assert douglas.answer() == 42
Exécutez le test en tant que. Le test a réussi! !! C'est une délicieuse découverte du siècle (exagérée), et tout le monde est ravi de se sentir heureux pour le moment.
L'état est passé du rouge au vert, le prochain est donc la refactorisation.
Pour le moment, facilitons la suppression des commentaires qui datent du début. Et j'ai également nettoyé la zone d'importation du code de test.
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_life_the_universe_and_everything():
douglas = FizzBuzz()
assert douglas.answer() == 42
Le programme a été un peu remanié. J'ai réécrit le programme, donc je vais le tester. Ce serait un problème si les tests réussis n'étaient pas réussis. Vous avez réussi le code de test.
Maintenant que je comprends le flux de TDD, je vais continuer avec FizzBuzz. Tout d'abord, décomposons les exigences de FizzBuzz en une granularité appropriée.
Pour réfléchir au plus petit scénario de FizzBuzz, identifiez d'abord les éléments nécessaires pour FizzBuzz.
--Lorsque l'argument est 1, la valeur de retour est 1. --Lorsque l'argument est 2, la valeur de retour est 2. --Lorsque l'argument est 3, la valeur de retour est Fizz --Lorsque l'argument est 5, la valeur de retour est Buzz --Lorsque l'argument est 6, la valeur de retour est Fizz --Lorsque l'argument est 10, la valeur de retour est Buzz --Lorsque l'argument est 15, la valeur de retour est FizzBuzz --Lorsque l'argument est 30, la valeur de retour est FizzBuzz
Est-ce quelque chose comme ça? Pour le plus petit scénario, cette fois, la «valeur de retour est 1 lorsque l'argument est 1».
À l'origine, nous devrions séparer et identifier les exigences de cette manière, mais comme c'était la première fois, nous l'avons omis.
TDD écrit d'abord le code de test. Pour la méthode qui fait fizzbuzz, testons la valeur de retour de l'argument avec fizzbuzz.
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_life_the_universe_and_everything():
douglas = FizzBuzz()
assert douglas.answer() == 42
def test_Lorsque l'argument est 1, la valeur de retour est 1.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(1) == "1"
Lorsque je lance le test, il n'y a pas de méthode fizzbuzz! Je suis en colère, mais j'ai hâte de me mettre en colère et de passer le test.
C'est arrivé. Comme prévu.
Maintenant, implémentons fizzbuzz.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(i):
return "1"
Cela passera le test! D'accord, c'est un test! !!
Eh bien, j'ai eu une erreur disant que le nombre d'arguments est étrange.
Faisons le tour.
Apparemment, vous devez vous remettre. Il semble que ce soit le nom de soi.
Modifions maintenant le programme.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, i):
return '1'
Si vous regardez de plus près, vous pouvez voir que l'argument de la réponse a aussi le soi. Suite à cela, le soi a été donné comme argument.
Oh, cela a passé le test.
Vous avez effacé avec succès "La valeur de retour est 1 lorsque l'argument est 1". Le double revêtement et le revêtement simple sont mélangés dans le refactoring, nous allons donc unifier à un seul revêtement.
Maintenant que le scénario minimum a été effacé avec succès, il est livré! !!
Non, eh bien, je n'ai testé qu'à 1, donc je pense que ça va, mais faisons un test à 2, alors testons à 2.
Comme précédemment, écrivez le test du cas 2.
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_life_the_universe_and_everything():
douglas = FizzBuzz()
assert douglas.answer() == 42
def test_Lorsque l'argument est 1, la valeur de retour est 1.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(1) == '1'
def test_Lorsque l'argument est 2, la valeur de retour est 2.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(2) == '2'
Quelque chose comme ça. Ajout d'un test pour renvoyer 2 quand 2. Très bien, testons.
C'est une erreur. Je suis content de ne pas l'avoir livré tel quel ...
Le contenu de l'erreur est que je veux 2 mais je ne veux pas emménager.
J'étais troublé. Que faire maintenant? Un programmeur avisé a dit ici. "Rendons l'argument tel quel" Le dactylo réécrit le code comme on lui dit.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, i):
return i
Oups? J'ai deux erreurs. Puisque je vérifiais la correspondance entre la chaîne de caractères et le nombre, je convertirai l'argument en chaîne de caractères et le retournerai pour le moment.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, i):
return str(i)
Testons-le.
Le test a réussi. Soyons très heureux.
--Lorsque l'argument est 1, la valeur de retour est 1. --Lorsque l'argument est 2, la valeur de retour est 2.
J'ai pu effacer les deux éléments.
C'est du refactoring.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
return str(arg)
L'argument i est difficile à comprendre, appelons-le donc arg.
Il est temps d'écrire un test pour vérifier les erreurs.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg == 3):
return 'Fizz'
return str(arg)
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_life_the_universe_and_everything():
douglas = FizzBuzz()
assert douglas.answer() == 42
def test_Lorsque l'argument est 1, la valeur de retour est 1.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(1) == '1'
def test_Lorsque l'argument est 2, la valeur de retour est 2.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(2) == '2'
def test_Lorsque l'argument est 3, la valeur de retour est Fizz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(3) == 'Fizz'
Cela a bien fonctionné dans le cas 3.
Maintenant, vérifions les spécifications.
readme.txt
Write a program that prints the numbers from 1 to 100.
But for multiples of three print "Fizz" instead of the
number and for the multiples of five print "Buzz". For
numbers which are multiples of both three and five
print "FizzBuzz".
Sample output:
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
... etc up to 100
Même dans le cas de 6, si Fizz est affiché, il est écrit dans les spécifications.
Créons et testons un test lorsque l'argument est 6 et que la valeur de retour est Fizz.
6 est la valeur de retour. Ne faites pas cela.
Tenez compte des spécifications.
Il s'avère que je souhaite afficher Fizz lorsqu'il est divisible par 3.
Et Mob dit: «Veuillez réécrire l'instruction if afin qu'elle s'affiche sous la forme Fizz lorsque le reste de 3 est égal à 0». La dactylo met en œuvre comme une machine.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg % 3 == 0):
return 'Fizz'
return str(arg)
Il a été réécrit à la condition du reste.
J'ai pu afficher le pétillement en toute sécurité lorsqu'il était un multiple de 3.
Jetons un coup d'œil au code de test actuel.
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_life_the_universe_and_everything():
douglas = FizzBuzz()
assert douglas.answer() == 42
def test_Lorsque l'argument est 1, la valeur de retour est 1.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(1) == '1'
def test_Lorsque l'argument est 2, la valeur de retour est 2.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(2) == '2'
def test_Lorsque l'argument est 3, la valeur de retour est Fizz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(3) == 'Fizz'
def test_Lorsque l'argument est 6, la valeur de retour est Fizz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(6) == 'Fizz'
Avez-vous besoin de tant de tests? Dans ce refactoring, nous supprimerons les tests inutiles.
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_Lorsque l'argument est 2, la valeur de retour est 2.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(2) == '2'
def test_Lorsque l'argument est 6, la valeur de retour est Fizz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(6) == 'Fizz'
Tant que ces deux sont utilisés, il est possible de traiter avec des multiples au lieu de valeurs fixes.
La suppression des cas de test inutiles est également une bonne refactorisation.
Depuis que j'ai vérifié les spécifications plus tôt, il est évident que c'est aussi un multiple de 5, donc je vais écrire le code de test pour les cas 5 et 10 et l'implémenter.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg % 3 == 0):
return 'Fizz'
if (arg % 5 == 0):
return 'Buzz'
return str(arg)
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_Lorsque l'argument est 2, la valeur de retour est 2.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(2) == '2'
def test_Lorsque l'argument est 6, la valeur de retour est Fizz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(6) == 'Fizz'
def test_Lorsque l'argument est 5, la valeur de retour est Buzz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(5) == 'Buzz'
def test_Lorsque l'argument est 10, la valeur de retour est Buzz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(10) == 'buzz'
Oups erreur, ce cas de test est incorrect. Fixons-le.
Supprimons le code de test inutile h. Supprimer 5 cas.
Depuis que j'ai vérifié les spécifications plus tôt, il est évident qu'il s'agit également d'un multiple de 15, donc je vais écrire le code de test pour les cas 15 et 30 et l'implémenter.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg % 3 == 0):
return 'Fizz'
if (arg % 5 == 0):
return 'Buzz'
if (arg % 15 == 0):
return 'FizzBuzz'
return str(arg)
test_fizzbuzz.py
from fizzbuzz import FizzBuzz
def test_Lorsque l'argument est 2, la valeur de retour est 2.():
douglas = FizzBuzz()
assert douglas.fizzbuzz(2) == '2'
def test_Lorsque l'argument est 6, la valeur de retour est Fizz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(6) == 'Fizz'
def test_Lorsque l'argument est 10, la valeur de retour est Buzz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(10) == 'Buzz'
def test_Lorsque l'argument est 15, la valeur de retour est FizzBuzz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(15) == 'FizzBuzz'
def test_Lorsque l'argument est 30, la valeur de retour est FizzBuzz():
douglas = FizzBuzz()
assert douglas.fizzbuzz(30) == 'FizzBuzz'
Il semble qu'il soit affiché comme Fizz. Il semble que les multiples de 3 ont réagi en premier. C'est également le cas, car la confirmation des multiples de 3 est confirmée dans l'ordre de confirmation des multiples de 5 et de confirmation des multiples de 15.
Changeons l'ordre.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
if (arg % 3 == 0):
return 'Fizz'
if (arg % 5 == 0):
return 'Buzz'
return str(arg)
Cela a fonctionné, et vous pouvez maintenant le livrer. La scène est une grande joie.
Maintenant, pour le refactoring final.
Il est désagréable d'avoir des déclarations si alignées, alors utilisez fermement les autres, etc.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
else if (arg % 3 == 0):
return 'Fizz'
else if (arg % 5 == 0):
return 'Buzz'
return str(arg)
Apparemment, sinon, si cela ne sert à rien, python semble créer une branche conditionnelle avec elif. Au fait, mettons le cas qui produit des nombres dans else
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else
return str(arg)
Je vais le tester. Avec ça, ...
Je ne l'ai pas fait. .. .. ..
Vous avez complètement oublié le côlon.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else:
return str(arg)
Cette fois, c'est fait.
Il est enfin livré! Applaudissements Aujourd'hui sera une fête pour boire. Je n'ai pas de fête pour boire.
Le flux global lorsque j'ai essayé TDD avec MobPro pour la première fois et les détails de l'échec ont été livrés tels quels (pas tellement).
Comme ça
Le TDD est réalisé en tournant le cycle de, mais c'était très intéressant de pouvoir le faire avec un sentiment légèrement différent en le faisant avec MobPro. Le résultat du test était facile à comprendre, j'ai essayé de l'exécuter pour le moment, et quand je me mettais en colère, je cherchais toujours sur Google, puis j'écrivais le code, donc c'était très rafraîchissant.
Mob Pro, faisons-le
** Dernière et dernière refactorisation **
Quelqu'un a dit. "Le langage que j'utilise a un opérateur ternaire, mais qu'en est-il de python?"
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz_bu(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else:
return str(arg)
def fizzbuzz (self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else:
return str(arg)
Pour le moment, je vais le réécrire dans la version opérateur ternaire en quittant le programme terminé.
Premièrement, il y avait une commande pour remplacer uniquement le cas des multiples de 5 par l'opérateur ternaire.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz_bu(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else:
return str(arg)
def fizzbuzz (self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
arg = 'Buzz' if arg % 5 == 0 else arg
return str(arg)
La refactorisation est réussie car vous pouvez confirmer que le test a réussi. Remplaçons un autre cas,
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz_bu(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else:
return str(arg)
def fizzbuzz (self, arg):
arg = 'FizzBuzz' if arg % 15 == 0 else arg
arg = 'Fizz' if arg % 3 == 0 else arg
arg = 'Buzz' if arg % 5 == 0 else arg
return str(arg)
J'ai eu beaucoup d'erreurs. C'est aussi naturel. J'essaye d'obtenir le reste de la chaîne.
Alors qu'en est-il d'un seul opérateur ternaire? J'ai donc essayé d'effacer le contenu de else et la substitution.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz_bu(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else:
return str(arg)
def fizzbuzz (self, arg):
arg = 'FizzBuzz' if arg % 15 == 0 else
'Fizz' if arg % 3 == 0 else
'Buzz' if arg % 5 == 0 else
return str(arg)
Je vais tester en disant "ça va marcher !!!".
Ne faites pas cela.
Je me demande si les sauts de ligne ne sont pas bons, et quand j'ai expliqué comment diviser un programme de longues phrases en plusieurs lignes, il y avait une voix disant que je pourrais utiliser une barre oblique inverse, alors je vais l'ajouter.
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz_bu(self, arg):
if (arg % 15 == 0):
return 'FizzBuzz'
elif (arg % 3 == 0):
return 'Fizz'
elif (arg % 5 == 0):
return 'Buzz'
else:
return str(arg)
def fizzbuzz (self, arg):
arg = 'FizzBuzz' if arg % 15 == 0 else \
'Fizz' if arg % 3 == 0 else \
'Buzz' if arg % 5 == 0 else \
arg
return str(arg)
Hourra! C'est un succès! !! Les acclamations augmenteront dès qu'il sera terminé. Maintenant que nous avons une version d'opérateur ternaire, supprimez la sauvegarde et il est temps de livrer! !! !! !! !! !! !!
fizzbuzz.py
class FizzBuzz:
def answer(self):
return 6 * 7
def fizzbuzz (self, arg):
arg = 'FizzBuzz' if arg % 15 == 0 else
'Fizz' if arg % 3 == 0 else
'Buzz' if arg % 5 == 0 else
return str(arg)
Recommended Posts