【TDD】测试驱动开发

59 篇文章 1 订阅
1 篇文章 0 订阅

欢迎关注微信公众号“Python小灶,和我一起每天学习Python新知识”,还可添加博主Vx:yf03064131,方便一起交流学习。
在这里插入图片描述
或者B站搜索 有只小新

原视频地址链接:点击这里
代码地址:点击这里
本文为大致翻译以及操作实践。

测试驱动开发概念

测试驱动开发,也称为红绿重构,英文全称Test-Driven Development,简称TDD,是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过测试来推动整个开发的进行。

测试驱动开发的五个步骤

  • step1
    编写测试,编写功能代码前,先编写在满足功能规范时才能通过的测试开始
  • step2
    运行测试,并确保它Fail,此时意味着你的测试生效(预期就是fail)
  • step3
    编写最简单的代码,以便测试可以通过,但是不必在此步骤做的完美
  • step4
    确保所有测试可以通过,包括旧的测试项,确保新功能符合规范,并且不会对其它东西造成破坏
  • step5
    重构和改进代码

代码实例讲解

我们按照上述的五个步骤,依次讲解

step1:想实现一个支付员工工资的功能,先不实现这个功能,把大体结构写出来:

关于dataclass的用法,看我文章:每日Python小技巧–dataclass

"""
Very advanced Employee management system.
"""
from dataclasses import dataclass


@dataclass
class Employee:
    """Basic representation of an employee."""

    name: str
    employee_id: int
    pay_rate: float = 100.0
    hours_worked: float = 0.0
    employer_cost: float = 1000.0
    has_commission: bool = True
    commission: float = 100.0
    contracts_landed: int = 0

    def compute_payout(self) -> float:
        """Compute how much the employee should be paid."""
        raise NotImplementedError()

step2:编写测试并运行,此时运行应该都是失败的,因为功能没有实现:

"""
Employee class tests.
"""
import unittest

from employee import Employee

NAME: str = "Arjan"
EMPLOYEE_ID: int = 12345


class TestEmployeeComputePayout(unittest.TestCase):
    """Test the compute_payout method of the Employee class."""

    def setUp(self):
        """Set up test fixtures."""
        self.arjan = Employee(name=NAME, employee_id=EMPLOYEE_ID)

    def test_employee_payout_returns_a_float(self):
        """Whether payout returns a float."""
        self.assertIsInstance(self.arjan.compute_payout(), float)

    def test_employee_payout_no_commission_no_hours(self):
        """Whether payout is correctly computed in case of no commission and no hours worked."""
        self.assertAlmostEqual(self.arjan.compute_payout(), 1000.0)

    def test_employee_payout_no_commission(self):
        """Whether payout is correctly computed in case of no commission and 10 hours worked."""
        self.arjan.hours_worked = 10.0
        self.assertAlmostEqual(self.arjan.compute_payout(), 2000.0)

    def test_employee_payout_with_commission(self):
        """
        Whether payout is correctly computed in case of
        10 contracts landed and 10 hours worked.
        """
        self.arjan.hours_worked = 10.0
        self.arjan.contracts_landed = 10
        self.assertAlmostEqual(self.arjan.compute_payout(), 3000.0)

    def test_employee_payout_commission_disabled(self):
        """
        Whether payout is correctly computed in case of
        10 contracts landed and 10 hours worked,
        but commission is disabled.
        """
        self.arjan.hours_worked = 10.0
        self.arjan.contracts_landed = 10
        self.arjan.has_commission = False
        self.assertAlmostEqual(self.arjan.compute_payout(), 2000.0)


if __name__ == "__main__":
    unittest.main()

step3:实现最基础的功能,部分case可以通过测试:

"""
Very advanced Employee management system.
"""
from dataclasses import dataclass


@dataclass
class Employee:
    """Basic representation of an employee."""

    name: str
    employee_id: int
    pay_rate: float = 100.0
    hours_worked: float = 0.0
    employer_cost: float = 1000.0
    has_commission: bool = True
    commission: float = 100.0
    contracts_landed: int = 0

    def compute_payout(self) -> float:  # pass 1 fail 4
        """Compute how much the employee should be paid."""
        
        payout = self.pay_rate * self.hours_worked
        return payout

step4:逐步完善:

    def compute_payout(self) -> float: # pass 4 fail 1
        """Compute how much the employee should be paid."""
        
        payout = self.pay_rate * self.hours_worked + self.employer_cost
        return payout

    def compute_payout(self) -> float: # pass 5 fail 0
        """Compute how much the employee should be paid."""
        
        payout = self.pay_rate * self.hours_worked + self.employer_cost
        if self.has_commission:
            payout += self.commission * self.contracts_landed
        return payout

step5:重构代码,此时我更改一些条件,修改相应的计算公式,那么所有的测试case都可以直接复用,高效准确:

注意和上面的差别:employer_cost这个费用,给改成了更细致的三项,但是测试结果依然是pass

"""
Very advanced Employee management system.
"""
from dataclasses import dataclass


@dataclass
class Employee:
    """Basic representation of an employee."""

    name: str
    employee_id: int
    pay_rate: float = 100.0
    hours_worked: float = 0.0
    # employer_cost: float = 1000.0
    employer_office_costs: float = 200.0
    employer_401k_costs: float = 400.0
    employer_suppoer_costs: float = 400.0
    has_commission: bool = True
    commission: float = 100.0
    contracts_landed: int = 0

    def compute_payout(self) -> float:
        """Compute how much the employee should be paid."""
        employer_cost = self.employer_office_costs + self.employer_401k_costs + self.employer_suppoer_costs
        payout = self.pay_rate * self.hours_worked + employer_cost
        if self.has_commission:
            payout += self.commission * self.contracts_landed
        return payout
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
测试驱动开发TDD)是一种软件开发的方法论,它强调在编写功能代码之前先编写测试代码。通过首先定义测试用例,开发人员可以准确地了解所需的功能,并更好地理解问题的规模和需求。这种开发方式的核心理念是“先测试,后开发”,因此测试用例成为了开发驱动力。 肯特·贝克(Kent Beck)是TDD方法的主要倡导者之一。他是一位著名的软件工程师,他在实践和推广敏捷开发领域做出了重要贡献。贝克提出了TDD的概念,并以其丰富的实践经验和独特的视角推动了该方法的发展。 贝克Kindle是一款由贝克开发的Kindle电子书阅读器。作为一名软件开发者和TDD的倡导者,贝克对于构建高质量、可测试的软件非常重视。他可能使用了TDD方法来开发贝克Kindle,也许在每个功能的开发过程中,他会先编写相应的测试用例,然后再编写实际的功能代码。 使用TDD开发贝克Kindle可以带来许多好处。首先,测试用例可以确保每个功能的正确性,这有助于减少错误和缺陷。其次,测试用例的存在可以提高代码的可读性和可维护性,因为它们作为文档清晰地说明了每个功能的预期行为。最后,TDD也可以促进开发过程中的快速反馈,开发人员可以通过运行测试驱动开发代码,并及时发现和解决问题。 总之,贝克Kindle的开发可能受到了贝克所倡导的TDD方法的影响。通过使用TDD开发,贝克可以确保贝克Kindle具有高质量、可靠性和可维护性,并且能够快速响应用户需求和变化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值