Java TDD简介–第1部分

欢迎来到测试驱动开发 (TDD)系列的介绍。 我们将在TDD上下文中讨论Java和JUnit ,但这只是工具。 本文的主要目的是使您全面了解TDD,而无论使用哪种编程语言和测试框架。

如果您在项目中不使用TDD,那么您要么很懒,要么就是根本不知道TDD的工作方式。 关于缺乏时间的借口不适用于这里。

关于这篇文章

在这篇文章中,我将解释什么是TDD以及如何在Java中使用它。 在TDD中,单元测试应放在哪个位置。 单元测试必须涵盖的内容。 最后,为了编写良好而有效的单元测试,需要遵循哪些原则。

如果您已经了解Java中有关TDD的所有知识,但是对示例和教程感兴趣,那么我建议您跳过这一部分,继续下一部分(它将在这一部分发布后的一周内发布)。

什么是TDD?

如果有人要我用几句话来解释TDD,那么我说TDD是功能实现之前的测试开发。 您可以争辩:很难测试尚不存在的事物。 肯特·贝克(Kent Beck)可能会为此一巴掌。

那怎么可能呢? 可以通过以下步骤进行描述:

1.阅读并了解特定功能的要求。
2.您开发了一组测试功能的测试。 由于没有功能实施,所有测试均为红色。 3.开发功能,直到所有测试变为绿色。 4.重构代码。

BDD流

TDD需要不同的思维方式,因此,为了根据它开始工作,您需要忘记以前开发代码的方式。 这个过程很难。 如果您不知道如何编写单元测试,那就更难了。 但这是值得的。

使用TDD进行开发具有宝贵的优势:

1.您对实现的功能有更好的了解。
2.您具有功能完整性的可靠指标。
3.代码包含测试,并且被修复或新功能破坏的可能性较小。

这些优势的代价是很高的–与切换到新的开发方式有关的不便以及您花费在开发每个新功能上的时间。 这是质量的代价。

这就是TDD的工作方式–编写红色的单元测试,开始实现功能,使测试变为绿色,执行代码重构。

TDD中单元测试的位置

由于单元测试是测试自动化金字塔中最小的元素,因此TDD基于它们。 借助单元测试,我们可以检查任何类的业务逻辑。 如果您知道如何做,则编写单元测试很容易。 那么,您需要使用单元测试进行测试的内容以及该怎么做呢? 您知道这些问题的答案吗? 我将尝试以简洁的形式说明答案。

吡酰胺单元测试的地方

单元测试应尽可能小。 不,不不要考虑这一点,因为一项测试仅适用于一种方法。 当然,这种情况也是可能的。 但通常,一个单元测试意味着调用多种方法。 这称为行为测试。

让我们考虑Account类:

public class Account {

    private String id = RandomStringUtils.randomAlphanumeric(6);
    private boolean status;
    private String zone;
    private BigDecimal amount;

    public Account() {
        status = true;
        zone = Zone.ZONE_1.name();
        amount = createBigDecimal(0.00);
    }

    public Account(boolean status, Zone zone, double amount) {
        this.status = status;
        this.zone = zone.name();
        this.amount = createBigDecimal(amount);
    }

    public enum Zone {
        ZONE_1, ZONE_2, ZONE_3
    }

    public static BigDecimal createBigDecimal(double total) {
        return new BigDecimal(total).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("id: ").append(getId())
                .append("\nstatus: ")
                .append(getStatus())
                .append("\nzone: ")
                .append(getZone())
                .append("\namount: ")
                .append(getAmount());
        return sb.toString();
    }

    public String getId() {
        return id;
    }

    public boolean getStatus() {
        return status;
    }

    public void setStatus(boolean status) {
        this.status = status;
    }

    public String getZone() {
        return zone;
    }

    public void setZone(String zone) {
        this.zone = zone;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        if (amount.signum() < 0)
            throw new IllegalArgumentException("The amount does not accept negative values");
        this.amount = amount;
    }
}

该类中有4种getter方法。 要特别注意它们。 如果我们为每个getter方法创建一个单独的单元测试,则会得到太多的冗余代码行。 可以通过行为测试来处理这种情况。 想象一下,我们需要使用其构造函数之一来测试对象创建的正确性。 如何检查对象是否按预期创建? 我们需要检查每个字段的值。 因此,可以在这种情况下使用吸气剂。

创建小型快速的单元测试 ,因为它们应在每次提交到git存储库并将新的构建提交到服务器之前执行。 您可以考虑一个带有实数的示例,以了解单元测试速度的重要性。 假设一个项目有1000个单元测试。 他们每个人都需要100毫秒。 结果,所有测试的运行需要1分40秒。

实际上100ms对于单元测试来说太长了,因此您必须通过应用不同的规则和技术来减少运行时间,例如,不要在单元测试中执行数据库连接(根据定义,单元测试是隔离的)或在其中执行昂贵的对象的初始化。 @Before块。

为单元测试选择好名字 。 测试的名称可以是您想要的任何名称,但是它应该代表测试进行的验证。 例如,如果我需要测试Account类的默认构造函数,则将其命名为defaultConstructorTest 。 选择测试名称的另一个有用建议是在命名测试之前编写测试逻辑。 在开发测试时,您会了解其中发生的情况,因此名称的组成变得更加容易。

单元测试应该是可预测的 。 这是最明显的要求。 我将在示例中进行解释。 为了检查转帐操作(需支付5%的费用),您必须知道发送的金额以及输出的金额。 此测试方案可以实现为发送100美元和接收95美元。

最后应该对单元测试进行细化 。 在每个测试中放置一个逻辑场景时,您可以从测试中获得有用的反馈。 并且在发生单个故障的情况下,您不会丢失有关其余功能的信息。

单元测试原理

所有这些建议旨在改进单元测试设计。 但是,您还需要了解一件事-测试设计技术的基础知识。

测试设计技术基础

没有测试数据就不可能编写测试。 例如,当您测试汇款系统时,可以在汇款字段中设置一些金额。 在这种情况下,数量是测试数据。 那么您应该选择哪些值进行测试? 为了回答这个问题,我们需要经历最流行的测试设计技术。 测试设计技术的通用目的是简化测试数据的构成。

首先,让我们假设我们可以发送正整数的钱。 同样,我们发送的邮件不能超过1000。这可以表示为:

0 < amount <= 1000; amount in integer

我们所有的测试场景可以分为两组:正面和负面场景。 第一个用于系统允许的测试数据,并导致成功的结果。 第二种是所谓的“故障场景”,当我们使用不适当的数据与系统进行交互时。

根据等价技术类别,我们可以从(0; 1000]范围内选择一个随机整数。设为500。由于系统适用于500,因此对于该范围内的所有整数均适用。有效值,也可以从范围中选择无效的输入,可以是任何带浮点的数字,例如125.50

然后我们必须参考边界测试技术 。 根据它,我们必须从范围的左侧和右侧选择2个有效值。 在我们的例子中,我们以1为允许的最小正整数,从右边取1000。
下一步是在边界上选择2个无效值。 所以它是0和1001

因此,最后我们有6个值需要在单元测试中使用:

  • (1,500,1000)–对于积极的情况
  • (0,125.50,1001)–否定情况

摘要

在这篇文章中,我试图解释TDD的各个方面,并说明在TDD中单元测试的重要性。 因此,我希望经过如此详尽和长期的bla-bla理论,我们可以继续实践。 在下一篇文章中,我将演示如何在功能之前开发测试。 我们将从文档分析开始,到代码重构结束,逐步进行操作。

确保所有测试都是绿色的:)

翻译自: https://www.javacodegeeks.com/2015/11/introduction-in-java-tdd-part-1.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
测试驱动的编程是 XP 困扰程序员的一个方面。对于测试驱动的编程意味着什么以及如何去做,大多数人都做出了不正确的假设。这个月,XP 方面的讲师兼 Java 开发人员 Roy Miller 谈论了测试驱动的编程是什么,它为什么可以使程序员的生产力和质量发生巨大变化,以及编写测试的原理。请在与本文相随的 论坛中提出您就本文的想法,以飨笔者和其他读者。(您也可以单击本文顶部或底部的“讨论”来访问该论坛。) 最近 50 年来,测试一直被视为项目结束时要做的事。当然,可以在项目进行之中结合测试,测试通常并不是在 所有编码工作结束后才开始,而是一般在稍后阶段进行测试。然而,XP 的提倡者建议完全逆转这个模型。作为一名程序员,应该在编写代码 之前编写测试,然后只编写足以让测试通过的代码即可。这样做将有助于使您的系统尽可能的简单。 先编写测试 XP 涉及两种测试: 程序员测试和 客户测试。测试驱动的编程(也称为 测试为先编程)最常指第一种测试,至少我使用这个术语时是这样。测试驱动的编程是让 程序员测试(即单元测试 ― 重申一下,只是换用一个术语)决定您所编写的代码。这意味着您必须在编写代码之前进行测试。测试指出您 需要编写的代码,从而也 决定了您要编写的代码。您只需编写足够通过测试的代码即可 ― 不用多,也不用少。XP 规则很简单:如果不进行程序员测试,则您不知道要编写什么代码,所以您不会去编写任何代码。 测试驱动开发(TDD)是极限编程的重要特点,它以不断的测试推动代码的开发,既简化了代码,又保证了软件质量。本文从开发人员使用的角度,介绍了 TDD 优势、原理、过程、原则、测试技术、Tips 等方面。 背景 一个高效的软件开发过程对软件开发人员来说是至关重要的,决定着开发是痛苦的挣扎,还是不断进步的喜悦。国人对软件蓝领的不屑,对繁琐冗长的传统开发过程的不耐,使大多数开发人员无所适从。最近兴起的一些软件开发过程相关的技术,提供一些比较高效、实用的软件过程开发方法。其中比较基础、关键的一个技术就是测试驱动开发(Test-Driven Development)。虽然TDD光大于极限编程,但测试驱动开发完全可以单独应用。下面就从开发人员使用的角度进行介绍,使开发人员用最少的代价尽快理解、掌握、应用这种技术。下面分优势,原理,过程,原则,测试技术,Tips等方面进行讨论。 1. 优势 TDD的基本思路就是通过测试来推动整个开发的进行。而测试驱动开发技术并不只是单纯的测试工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值