Maison >développement back-end >Tutoriel Python >Création d'une calculatrice de chaînes avec le développement piloté par les tests (TDD) : un guide étape par étape

Création d'une calculatrice de chaînes avec le développement piloté par les tests (TDD) : un guide étape par étape

Barbara Streisand
Barbara Streisandoriginal
2025-01-15 18:09:48918parcourir

Building a String Calculator with Test-Driven Development (TDD): A Step-by-Step Guide

Nous implémenterons un calculateur de chaînes en Python en utilisant une approche de développement piloté par les tests (TDD). Cela signifie que nous écrirons des tests pour chaque fonctionnalité avant d'implémenter la fonctionnalité correspondante.

Vous pouvez vous référer au lien https://osherove.com/tdd-kata-1 comme points de contrôle pour la mise en œuvre de TDD. Le lien fournit des instructions étape par étape que vous pouvez suivre.

Commencer

Dans votre dossier de projet, créez deux fichiers : string_calculator.py et tests/test_string_calculator.py. Nous mettrons en œuvre les fonctionnalités étape par étape. Tout d’abord, nous devons créer une classe StringCalculator avec une méthode add.

Étape 1 : la chaîne vide doit renvoyer « 0 »

Écrivons le premier test de notre application en utilisant la bibliothèque unittest. Ouvrez le fichier tests/test_string_calculator.py et commencez avec le code suivant :

import unittest
from string_calculator import StringCalculator

class TestStringCalculator(unittest.TestCase):
    """Test suite for the StringCalculator class."""

    def setUp(self):
        """
        Create a new instance of StringCalculator for each test.
        Can use static method to avoid creating a new instance.
        """
        self.calculator = StringCalculator()

    def test_empty_string_returns_zero(self):
        """
        Test case: Adding an empty string should return 0.
        Input: "" 
        Expected Output: 0
        """
        self.assertEqual(self.calculator.add(""), 0)

Maintenant, implémentons la classe StringCalculator dans le fichier string_calculator.py :

class StringCalculator:
    def add(self, numbers:str):
        if not numbers:
            return 0

Pour exécuter les tests, suivez ces étapes :

  1. Assurez-vous que vous êtes dans le répertoire du projet où se trouvent vos fichiers string_calculator.py et tests/test_string_calculator.py.

  2. Ouvrez votre terminal ou votre invite de commande.

  3. Exécutez la commande suivante pour exécuter les tests :

python -m unittest discover tests

Cette commande découvrira et exécutera automatiquement tous les tests dans le dossier tests.

Résultat attendu :

Vous devriez voir quelque chose comme ceci si le test réussit :


----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Si tout est configuré correctement et que le scénario de test réussit, cela signifie que votre implémentation pour gérer une chaîne vide fonctionne comme prévu.

Étape 2 : L'ajout d'un ou deux nombres devrait renvoyer leur somme

Nous devons mettre à jour la méthode pour gérer le cas où il n'y a qu'un ou deux nombres dans la chaîne d'entrée, et elle doit renvoyer leur somme. Pour une chaîne vide, la méthode doit renvoyer 0.

Écrire le test

Ouvrez le fichier tests/test_string_calculator.py et ajoutez les cas de test suivants pour couvrir tous les scénarios :

    def test_add_single_number(self):
        """
        Test case: Adding a single number should return the number itself.
        Input: "1"
        Expected Output: 1
        """
        self.assertEqual(self.calculator.add("1"), 1)

    def test_add_two_numbers(self):
        """
        Test case: Adding two numbers should return their sum.
        Input: "1,2"
        Expected Output: 3
        """
        self.assertEqual(self.calculator.add("1,2"),3)

Mise en œuvre du code

Maintenant, mettez à jour la méthode add dans le fichier string_calculator.py pour gérer l'ajout d'un ou deux nombres :

class StringCalculator:
    def add(self, numbers:str):
        if not numbers:
            return 0
        '''
        Split the string by commas, convert each value to an integer, 
        and sum them up
        '''
        numbers_list = map(int,numbers.split(',')) 
        return sum(numbers_list)

Vous pouvez tester à nouveau le code en suivant les étapes précédentes.

Étape 3 : Gérer plusieurs numéros

Nous allons écrire un cas de test pour vérifier si la méthode peut gérer plusieurs nombres séparés par des virgules.

Écrire le test

Ouvrez le fichier tests/test_string_calculator.py et ajoutez un cas de test pour gérer plusieurs nombres :

import unittest
from string_calculator import StringCalculator

class TestStringCalculator(unittest.TestCase):
    """Test suite for the StringCalculator class."""

    def setUp(self):
        """
        Create a new instance of StringCalculator for each test.
        Can use static method to avoid creating a new instance.
        """
        self.calculator = StringCalculator()

    def test_empty_string_returns_zero(self):
        """
        Test case: Adding an empty string should return 0.
        Input: "" 
        Expected Output: 0
        """
        self.assertEqual(self.calculator.add(""), 0)

La fonctionnalité a déjà été implémentée, nous pouvons donc procéder au test du code puis passer à l'étape suivante.

Étape 4 : Gestion des nouvelles lignes entre les nombres

Maintenant, nous devons améliorer la méthode add pour gérer les nouvelles lignes (n) comme séparateurs valides entre les nombres, en plus des virgules.

Écrire le test

Ouvrez le fichier tests/test_string_calculator.py et ajoutez un scénario de test pour vérifier si la méthode gère correctement les nouvelles lignes comme séparateurs :

class StringCalculator:
    def add(self, numbers:str):
        if not numbers:
            return 0

Mise en œuvre du code

Ensuite, mettez à jour la méthode add dans le fichier string_calculator.py pour gérer les nouvelles lignes (n) comme séparateurs. Nous pouvons modifier la méthode pour remplacer n par des virgules, puis diviser la chaîne par des virgules.

Voici le code mis à jour pour la méthode add :

python -m unittest discover tests

Vous pouvez tester à nouveau le code en suivant les étapes précédentes définies à l'étape 1.

Étape 5 : Gestion des délimiteurs personnalisés

Dans cette étape, nous améliorerons encore la fonctionnalité pour permettre des délimiteurs personnalisés. Par exemple, les utilisateurs devraient pouvoir spécifier un délimiteur personnalisé au début de la chaîne. Par exemple :

  • La chaîne d'entrée peut commencer par // suivi d'un délimiteur personnalisé, par exemple //;n1;2;3 doit renvoyer 6.
  • Nous prendrons en charge les délimiteurs comme //;n1;2;3.

Écrire le test

Ouvrez le fichier tests/test_string_calculator.py et ajoutez un scénario de test pour gérer la fonctionnalité de délimiteur personnalisé :


----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Mise en œuvre du code

Pour gérer les délimiteurs personnalisés, mettez à jour la méthode add pour rechercher le délimiteur dans la chaîne d'entrée. Le délimiteur doit être spécifié au début de la chaîne après //.

Voici la méthode d'ajout mise à jour :

    def test_add_single_number(self):
        """
        Test case: Adding a single number should return the number itself.
        Input: "1"
        Expected Output: 1
        """
        self.assertEqual(self.calculator.add("1"), 1)

    def test_add_two_numbers(self):
        """
        Test case: Adding two numbers should return their sum.
        Input: "1,2"
        Expected Output: 3
        """
        self.assertEqual(self.calculator.add("1,2"),3)

Étape 6 : Gestion des nombres négatifs

Dans cette étape, nous devons modifier la méthode add pour gérer les nombres négatifs. Lorsqu'un nombre négatif est transmis, il doit lever une exception avec le message « négatifs non autorisés » et inclure les nombres négatifs qui ont été transmis.

Écrire le test

Ouvrez le fichier tests/test_string_calculator.py et ajoutez un scénario de test pour gérer l'exception de nombre négatif :

class StringCalculator:
    def add(self, numbers:str):
        if not numbers:
            return 0
        '''
        Split the string by commas, convert each value to an integer, 
        and sum them up
        '''
        numbers_list = map(int,numbers.split(',')) 
        return sum(numbers_list)

Mise en œuvre du code

Maintenant, modifiez la méthode add pour vérifier les nombres négatifs et déclenchez une ValueError avec le message approprié.

Voici la méthode d'ajout mise à jour :

def test_add_multiple_numbers(self):
    """
    Test case: Adding multiple numbers should return their sum.
    Input: "1,2,3,4,5"
    Expected Output: 15
    """
    self.assertEqual(self.calculator.add("1,2,3,4,5"), 15)

Étape 7 : Comptage des appels de méthode d'ajout

Dans cette étape, nous ajouterons une méthode appelée GetCalledCount() à la classe StringCalculator qui renverra combien de fois la méthode add() a été invoquée. Nous suivrons le processus TDD en écrivant d'abord un test ayant échoué, puis en implémentant la fonctionnalité.

Écrire le test

Commencez par ajouter un scénario de test pour la méthode GetCalledCount(). Ce test doit vérifier que la méthode compte correctement le nombre de fois que add() est appelée.

Ouvrez le fichier tests/test_string_calculator.py et ajoutez le test suivant :

import unittest
from string_calculator import StringCalculator

class TestStringCalculator(unittest.TestCase):
    """Test suite for the StringCalculator class."""

    def setUp(self):
        """
        Create a new instance of StringCalculator for each test.
        Can use static method to avoid creating a new instance.
        """
        self.calculator = StringCalculator()

    def test_empty_string_returns_zero(self):
        """
        Test case: Adding an empty string should return 0.
        Input: "" 
        Expected Output: 0
        """
        self.assertEqual(self.calculator.add(""), 0)

Mise en œuvre du code

Maintenant, implémentez la méthode GetCalledCount() dans la classe StringCalculator. Cette méthode devra garder une trace du nombre de fois que add() a été invoquée.

Voici la classe StringCalculator mise à jour :

class StringCalculator:
    def add(self, numbers:str):
        if not numbers:
            return 0

Étapes 8 et 9 : ignorez les nombres supérieurs à 1 000 et gérez les délimiteurs personnalisés de n'importe quelle longueur

Dans cette étape, nous mettrons en œuvre deux exigences :

  1. Les nombres supérieurs à 1000 doivent être ignorés dans la somme.
  2. Les délimiteurs personnalisés peuvent être de n'importe quelle longueur, au format //[delimiter]n, et la méthode doit les gérer.

Nous allons d'abord écrire les tests pour ces deux exigences, puis implémenter la fonctionnalité dans la classe StringCalculator.

Écrire les tests

Ajoutez les tests suivants à la fois pour les nombres ignorés supérieurs à 1 000 et pour la gestion des délimiteurs personnalisés de n'importe quelle longueur. Ouvrez le fichier tests/test_string_calculator.py et ajoutez ce qui suit :

python -m unittest discover tests

Mise en œuvre du code

Maintenant, implémentez la fonctionnalité dans la classe StringCalculator. Cela comprendra :

  1. Ignorer les nombres supérieurs à 1000.
  2. Gestion des délimiteurs personnalisés de n'importe quelle longueur.

Voici la classe StringCalculator mise à jour :


----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

Étape 10 : Prise en charge de plusieurs délimiteurs

Dans cette étape, nous modifierons la méthode add() pour prendre en charge plusieurs délimiteurs de n'importe quelle longueur. Cela nous permettra de gérer les cas où il y a plusieurs délimiteurs au format //[delimiter1][delimiter2]n.

Écrire le test

Commencez par ajouter un scénario de test pour vérifier plusieurs délimiteurs. Ouvrez le fichier tests/test_string_calculator.py et ajoutez le test suivant :

    def test_add_single_number(self):
        """
        Test case: Adding a single number should return the number itself.
        Input: "1"
        Expected Output: 1
        """
        self.assertEqual(self.calculator.add("1"), 1)

    def test_add_two_numbers(self):
        """
        Test case: Adding two numbers should return their sum.
        Input: "1,2"
        Expected Output: 3
        """
        self.assertEqual(self.calculator.add("1,2"),3)

Mise en œuvre du code

Maintenant, modifiez la méthode add() pour gérer plusieurs délimiteurs. Les délimiteurs seront passés à l'intérieur de [], et nous devons prendre en charge la gestion de plusieurs délimiteurs au format //[delimiter1][delimiter2]n.

Voici la classe StringCalculator mise à jour pour prendre en charge cela :

class StringCalculator:
    def add(self, numbers:str):
        if not numbers:
            return 0
        '''
        Split the string by commas, convert each value to an integer, 
        and sum them up
        '''
        numbers_list = map(int,numbers.split(',')) 
        return sum(numbers_list)

Le tester

Relancez les tests pour vérifier que tout fonctionne, y compris la rétrocompatibilité avec l'ancien format et la prise en charge du nouveau format à délimiteurs multiples :

def test_add_multiple_numbers(self):
    """
    Test case: Adding multiple numbers should return their sum.
    Input: "1,2,3,4,5"
    Expected Output: 15
    """
    self.assertEqual(self.calculator.add("1,2,3,4,5"), 15)

Résultat attendu

Les tests doivent réussir pour les anciens et les nouveaux formats :

def test_add_numbers_with_newlines(self):
    """
    Test case: Adding numbers separated by newlines should return their sum.
    Input: "1\n2\n3"
    Expected Output: 6
    """
    self.assertEqual(self.calculator.add("1\n2\n3"), 6)

Merci de suivre cette série TDD ! J'espère que vous l'avez trouvé utile.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn