首页 >后端开发 >Python教程 >使用测试驱动开发 (TDD) 构建字符串计算器:分步指南

使用测试驱动开发 (TDD) 构建字符串计算器:分步指南

Barbara Streisand
Barbara Streisand原创
2025-01-15 18:09:48918浏览

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

我们将使用测试驱动开发 (TDD) 方法在 Python 中实现字符串计算器。这意味着我们将在实现相应功能之前为每个功能编写测试。

您可以参考链接 https://osherove.com/tdd-kata-1 作为实施 TDD 的检查点。该链接提供了您可以遵循的分步说明。

入门

在项目文件夹中,创建两个文件:string_calculator.py 和tests/test_string_calculator.py。我们将逐步实现这些功能。首先,我们需要创建一个带有 add 方法的 StringCalculator 类。

第 1 步:空字符串应返回“0”

让我们使用单元测试库为我们的应用程序编写第一个测试。打开tests/test_string_calculator.py 文件并从以下代码开始:

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)

现在,让我们在 string_calculator.py 文件中实现 StringCalculator 类:

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

要运行测试,请按照以下步骤操作:

  1. 确保您位于 string_calculator.py 和tests/test_string_calculator.py 文件所在的项目目录中。

  2. 打开终端或命令提示符。

  3. 运行以下命令来执行测试:

python -m unittest discover tests

此命令将自动发现并运行测试文件夹中的所有测试。

预期输出:

如果测试通过,您应该会看到类似这样的内容:


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

OK

如果一切设置正确并且测试用例通过,则意味着您处理空字符串的实现正在按预期工作。

第 2 步:将一两个数字相加应返回其总和

我们需要更新方法来处理输入字符串中只有一个数字或两个数字的情况,并且它应该返回它们的总和。对于空字符串,该方法应返回 0。

编写测试

打开tests/test_string_calculator.py 文件并添加以下测试用例以覆盖所有场景:

    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)

实施准则

现在,更新 string_calculator.py 文件中的 add 方法来处理一两个数字的加法:

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)

您可以按照前面的步骤再次测试代码。

第 3 步:处理多个号码

我们将编写一个测试用例来检查该方法是否可以处理用逗号分隔的多个数字。

编写测试

打开tests/test_string_calculator.py 文件并添加一个测试用例来处理多个数字:

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)

功能已经实现,我们可以继续测试代码,然后继续下一步。

步骤 4:处理数字之间的换行符

现在,我们需要增强 add 方法来处理除逗号之外的新行 (n) 作为数字之间的有效分隔符。

编写测试

打开tests/test_string_calculator.py 文件并添加一个测试用例来检查该方法是否正确处理新行作为分隔符:

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

实施准则

接下来,更新 string_calculator.py 文件中的 add 方法以将新行 (n) 作为分隔符处理。我们可以修改方法,将n替换为逗号,然后用逗号分割字符串。

这是 add 方法的更新代码:

python -m unittest discover tests

您可以按照step1.

中定义的先前步骤再次测试代码

第 5 步:处理自定义分隔符

在此步骤中,我们将进一步增强功能以​​允许自定义分隔符。例如,用户应该能够在字符串的开头指定自定义分隔符。例如:

  • 输入字符串可以以 // 开头,后跟自定义分隔符,例如 //;n1;2;3 应返回 6。
  • 我们将支持 //;n1;2;3 等分隔符。

编写测试

打开tests/test_string_calculator.py 文件并添加一个测试用例来处理自定义分隔符功能:


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

OK

实施准则

要处理自定义分隔符,请更新 add 方法以在输入字符串中查找分隔符。分隔符应在 //.

之后的字符串开头指定

这是更新后的添加方法:

    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)

第 6 步:处理负数

在这一步中,我们需要修改add方法来处理负数。当传递负数时,它应该抛出异常,并显示消息“不允许使用负数”,并包含传递的负数。

编写测试

打开tests/test_string_calculator.py文件并添加一个测试用例来处理负数异常:

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)

实施准则

现在,修改 add 方法以检查负数并使用适当的消息引发 ValueError。

这是更新后的添加方法:

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)

第 7 步:计算 Add 方法调用次数

在此步骤中,我们将向 StringCalculator 类添加一个名为 GetCalledCount() 的方法,该方法将返回 add() 方法被调用的次数。我们将遵循 TDD 流程,首先编写失败的测试,然后实现该功能。

编写测试

首先为 GetCalledCount() 方法添加一个测试用例。此测试应检查该方法是否正确计算调用 add() 的次数。

打开tests/test_string_calculator.py 文件并添加以下测试:

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)

实施准则

现在,在 StringCalculator 类中实现 GetCalledCount() 方法。此方法需要跟踪 add() 被调用的次数。

这是更新后的 StringCalculator 类:

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

步骤 8 和 9:忽略大于 1000 的数字并处理任意长度的自定义分隔符

在这一步中,我们将实现两个要求:

  1. 总和中应忽略大于 1000 的数字。
  2. 自定义分隔符可以是任意长度,格式为 //[delimiter]n,并且该方法应该处理它们。

我们将首先针对这两个要求编写测试,然后在 StringCalculator 类中实现功能。

编写测试

为忽略大于 1000 的数字和处理任意长度的自定义分隔符添加以下测试。打开tests/test_string_calculator.py 文件并添加以下内容:

python -m unittest discover tests

实施准则

现在,实现 StringCalculator 类中的功能。这将包括:

  1. 忽略大于 1000 的数字。
  2. 处理任意长度的自定义分隔符。

这是更新后的 StringCalculator 类:


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

OK

步骤 10:多个分隔符支持

在这一步中,我们将修改 add() 方法以支持任意长度的多个分隔符。这将使我们能够处理格式为 //[delimiter1][delimiter2]n.

的多个分隔符的情况

编写测试

首先添加一个测试用例来检查多个分隔符。打开tests/test_string_calculator.py 文件并添加以下测试:

    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)

实施准则

现在,修改 add() 方法以处理多个分隔符。分隔符将在 [] 内部传递,我们需要支持处理 //[delimiter1][delimiter2]n.

格式的多个分隔符

这是支持此功能的更新后的 StringCalculator 类:

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)

测试它

再次运行测试以验证一切正常,包括与旧格式的向后兼容性以及对新的多个分隔符格式的支持:

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)

预期输出

旧格式和新格式的测试都应该通过:

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)

感谢您关注这个 TDD 系列!我希望你觉得它有用。

以上是使用测试驱动开发 (TDD) 构建字符串计算器:分步指南的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn