如何使用测试驱动开发(TDD)来实现100%的测试覆盖率?

news2024/9/20 23:30:13
本文以 DDM 为例,简单地介绍一下如何用测试驱动开发(TDD, Test-Driven Development)的方法来驱动出这个函数库。

本文以DDM为例,简单地介绍一下如何用测试驱动开发(TDD, Test-Driven Development)的方法来驱动出这个函数库。

DDM简介

DDM是一个简洁的前端领域模型库,如我在《DDM: 一个简洁的前端领域模型库》一文中所说,它是我对于DDD在前端领域中使用的一个探索。

简单地来说,这个库就是对一个数据模型的操作——增、删 、改,然后生成另外一个数据模型。

如以Blog模型,删除Author,我们就可以得到一个新的模型。而实现上是因为我们需要RSS模型,我们才需要对原有的模型进行修改。

预先式设计

如果你对TDD有点了解的话,那么你可能会预先式设计有点疑问。

等等,什么是测试驱动开发?

> 测试驱动开发,英文全称Test-Driven Development,简称TDD,是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码,然后只编写使测试通过的功能代码,通过测试来推动整个开发的进行。这有助于编写简洁可用和高质量的代码,并加速开发过程。

流程大概就是这样的,先写个测试 -> 然后运行测试,测试失败 -> 让测试通过 -> 重构。 

换句简单的话来说,就是 红 -> 绿 -> 重构。

在DDM项目里,就是一个比较适合TDD的场景。我们知道我们所有的功能,我们也知道我们需要对什么内容进行测试,并且它很简单。因为这个场景下,我们已经知道了我们所需要的功能,所以我们就可以直接设计主要的函数:

export class DDM {
  constructor() {}
  from() {};
  get(array) {};
  to() {};
  handle() {};
  add() {};
  remove(field) {};
}

上面的就是我们的需要函数,不过在后来因为需要就添加了replacereplaceWithHandle方法。

然后,我们就可以编写我们的第一个测试了。

第一个驱动开发的测试

我们的第一个测试,比较简单,但是也比较麻烦——我们需要构建出基本的轮廓。我们的第一个测试就是要测试我们可以从原来的对象中取出title的值:

let ddm = new DDM();
var originObject = {
  title: 'hello',
  blog: 'fdsf asdf fadsf ',
  author: 'phodal'
};

var newObject = {};
ddm
  .get(['title'])
  .from(originObject)
  .to(newObject);

expect(newObject.title).toBe("hello");

对应的,为了实现这个需要基本的功能,我们就可以写一个简单的return来通过测试。

  from(originObject) {
    return this;
  };

  get(array) {
    return this;
  };

  to(newObject) {
    newObject.title = 'hello';
    return this;
  };

但是这个功能在我们写下一个测试的时候,它就会出错。

ddm
  .get(['title', 'phodal'])
  .from(originObject)
  .to(newObject);

expect(newObject.title).toBe("hello");
expect(newObject.author).toBe("phodal");

但是这也是我们实现功能要做的一步,下一步我们就可以实现真正的功能:

  • 在from函数里,复制originObject
  • 在get函数里,获取新的对象所需要的key
  • 最后,在to函数里,进行复制处理
  from(originObject) {
    this.originObject = originObject;
    return this;
  };

  get(array) {
    this.newObjectKey = array;
    return this;
  };

  to(newObject) {
    for (var key of this.newObjectKey) {
      newObject[key] = this.originObject[key];
    }
    return this;
  };

现在,我们已经完成了基本的功能。

一个意外的情况

在我实现的过程中,我发现如果我传给get函数的array如果是空的话,那么就不work了。于是,就针对这个情况写了个测试,然后实现了这个功能:

  get(keyArray) {
    if(keyArray) {
      this.newObjectKey = keyArray;
    } else {
      this.newObjectKey = [];
    }
    return this;
  };

  to(newObject) {
    if(this.newObjectKey.length > 0){
      for (var key of this.newObjectKey) {
        newObject[key] = this.originObject[key];
      }
    } else {
      // Clone each property.
      for (var prop in this.originObject) {
        newObject[prop] = clone(this.originObject[prop]);
      }
    }
    return this;
  };

在这个过程中,我还找到了一个clone函数,来替换from中的"="。

  from(originObject) {
    this.originObject = clone(originObject);
    return this;
  };

第三个驱动开发的测试
---

因为有了第一个测试的基础,我们要写下一测试变得非常简单:

```javascript
dlm.get(['title'])
  .from(originObject)
  .add('tag', 'hello,world,linux')
  .to(newObject);

expect(newObject.tag).toBe("hello,world,linux");
expect(newObject.title).toBe("hello");
expect(newObject.author).toBe(undefined);

在实现的过程中,我又投机取巧了,我创建了一个对象来存储新的对象的key和value:

  add(field, value) {
    this.objectForAddRemove[field] = value;
    return this;
  };

同样的,在to方法里,对其进行处理:

  to(newObject) {
    function cloneObjectForAddRemove() {
      for (var prop in this.objectForAddRemove) {
        newObject[prop] = this.objectForAddRemove[prop];
      }
    }

    function cloneToNewObjectByKey() {
      for (var key of this.newObjectKey) {
        newObject[key] = this.originObject[key];
      }
    }

    function deepCloneObject() {
      // Clone each property.
      for (var prop in this.originObject) {
        newObject[prop] = clone(this.originObject[prop]);
      }
    }

    cloneObjectForAddRemove.call(this);
    if (this.newObjectKey.length > 0) {
      cloneToNewObjectByKey.call(this);
    } else {
      deepCloneObject.call(this);
    }
    return this;
  };

在这个函数里,我们用cloneObjectForAddRemove函数来复制将要添加的key和value到新的对象里。

remove和handle函数

对于剩下的remove和handle来说,他们实现起来都是类似的:

  • 存储相应的对象操作
  • 然后在to函数里进行处理

编写测试:

    function handler(blog) {
      return blog[0];
    }

    ddm.get(['title', 'blog', 'author'])
      .from(originObject)
      .handle("blog", handler)
      .to(newObject);
    expect(newObject.blog).toBe('A');

然后实现功能:

  remove(field) {
    this.objectKeyForRemove.push(field);
    return this;
  };

  handle(field, handle) {
    this.handleFunction.push({
      field: field,
      handle: handle
    });
    return this;
  }

这一切看上去都很自然,然后我们就可以对其进行重构了。

100%的测试覆盖率

由于,我们先编写了测试,再实现代码,所以我们编写的代码都有对应的测试。因此,我们可以轻松实现相当高的测试覆盖率。

在这个Case下,由于业务场景比较简单,要实现100%的测试覆盖率就是一件很简单的事。

正在做测试的朋友可以进来交流,群里给大家整理了大量学习资料和面试题项目简历等等.... 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/659996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue-cli3的安装和项目创建

一 vue-cli3的安装 (注意:vue-cli3在安装之前,需要先删除旧版本,即vue-cli2) cnpm i -g vue/cli vue-cli3的卸载:cnpm uninstall -g vue/cli 然后用命令“vue -V”查看是否删除vue,如果没有删…

kafka原理架构深入

目录 1. 下载安装2. 命令行命令3. 概述3.1 定义3.2 基本架构 4. 架构深入4.1 生产者4.1.1 分区4.1.2 数据可靠性保证4.1.3 Exactly Once语义4.1.4 发送消息流程 4.2 broker4.2.1 日志结构4.2.2 存储策略4.2.3 Controller & ZooKeeper4.2.4 高效读写数据 4.3 消费者4.3.1 消…

模型-视图-控制器模式(MVC模式,10种常见体系架构模式之一)

、简介: 架构模式是一个通用的、可重用的解决方案,用于在给定上下文中的软件体系结构中经常出现的问题。架构模式与软件设计模式类似,但具有更广泛的范围。 模型-视图-控制器模式,也称为MVC模式。是软件工程中的一种软件架构模式&…

Word模板引擎poi-tl

文章目录 ◆ 方案对比◆ 版本◆ 特性◆ 模板◆ 数据◆ 输出◆ 数据模型◆ 标签1. 文本2. 图片3. 表格4. 列表5. 嵌套6. 区块对 ◆ SpingEL2. 单系列图标3. 多系列图标4. 组合图表 ◆ 配置1. 标签前后缀2. 标签类型3. 标签匹配值4. 标签值计算5. SpringEL6. 数据模型序列化7. 错…

设计模式之抽象工厂笔记

设计模式之抽象工厂模式笔记 说明Abstract Factory(抽象工厂)目录UML抽象工厂示例类图甜品抽象类甜品提拉米苏类甜品抹茶慕斯类 咖啡抽象类美式咖啡类拿铁咖啡类 甜品工厂接口美式风味的甜品工厂意大利风味的甜品工厂 测试类模式扩展 说明 记录下学习设计模式-抽象工厂模式的写…

吴恩达471机器学习入门课程3第1周——K-means

K-means 聚类 1 - 实现 K-means1.1 找到最近的质心练习11.2 计算质心均值练习2 2 - K-means在样本数据集上的应用3 - 随机初始化4 - K-means图像压缩4.1 数据集可视化处理数据 4.2图像像素上的 K-mean4.3 压缩图片 实现 K-means 算法,并将其用于图像压缩。 您将从一…

Autoware 跑 Demo(踩坑指南)

Autoware 跑 Demo(踩坑指南) 网上的博客和官方的教程,几乎都是一样的,但实际上跑不起来 Autoware 1.12学习整理–01–运行rosbag示例 Autoware入门学习(三)——Autoware软件功能使用介绍(1/3&a…

MySQL的IF(exp1, exp2, exp3)、IFNULL(exp1, exp2)函数的用法

本章主要是讲解一下mysql的常用方法if()和ifnull()的使用 1、if(exp1, exp2, exp3) 如果表达式exp1成立,则返回的结果是表达式exp2,否则返回的是表达式exp3 案例:现在有一个星印类型表xingyin_type 通过这个表来介绍一下这个函数的使用 sel…

轻松掌握Seata源码分析之AT模式整体大纲流程跟踪

如下为订单和库存的实例代码,在事务开启处即订单服务处使用GlobalTransactional即可。当添加了异常代码使订单无法加一,这时减库存服务也会回滚,根据的就是undolog。回滚完undolog记录会被释放删除。 AT模式整体大纲流程跟踪如下&#xff1…

第37步 深度学习图像识别:CNN建模(Tensorflow)

基于WIN10的64位系统演示 一、写在前面 (1)深度学习图像识别的原理 我们思考一下,当你看到一张椅子的图片,你的大脑会告诉你这是个椅子,但你有没有想过:为什么你知道这是椅子,你的大脑是怎么…

【Spring Cloud 系列】Eureka控制台参数说明

【Spring Cloud 系列】Eureka控制台参数说明 前面我们在《Eureka使用详解》一文中介绍了Eureka的使用。本文将介绍Eureka控制板面各参数: System Status 编号名称说明1Environment环境,默认为test,该参数在实际使用过程中,可以不…

单目标应用:Tiki-taka算法(TTA)求解太阳能光伏模型MATLAB

一、四种太阳能光伏模型 随着石油、煤炭、天然气等不可再生能源的快速枯竭,以及空气环境的严重污染,可持续、无污染的能源供应成为热点和关键问题。风能、太阳能、水能、潮汐能等可再生能源的开发利用,必然在未来的可持续发展中发挥至关重要…

德国企业数据统计分析【1】-基于pandas的GENESIS ONLINE数据简单统计与柱状图可视化

引言: 德国拥有很多年销售额不超过50亿美元的中小企业,但他们却是某些细分制造、工业领域的翘楚。并且隐身于大众视野之外。此处,隐形冠军指的就是细分领域行业处于绝对领先地位并且年销售额不超过50亿美元的中小企业。这一概念是由德国著名中小企业管理学家赫尔曼西蒙创立的…

电脑开机密码忘记了怎么办?使用优盘重装系统

大家可以在网上搜索,其他方法。尽量找回密码。我这是因为已经很久没有使用这个电脑,而且c盘也没有怎么重要资料的情况下。我才选择重装系统的。 请慎重。 前期准备: 1、准备一个4G以上的U盘 2、备份U盘重要文件,制作过程中会格式…

「深度学习之优化算法」(五)差分进化算法

1. 差分进化算法简介 (以下描述,均不是学术用语,仅供大家快乐的阅读) 差分进化算法(Differential Evolution Algorithm,DE)是一种基于群体的进化算法,它模拟了群体中的个体的合作与竞…

黑马点评短信登录功能

一、基于session实现短信登录 1、发送短信验证码 流程图如下: 1、实现UserController下的sendCode方法: /*** 发送手机验证码*/PostMapping("/code")public Result sendCode(RequestParam("phone") String phone, HttpSession se…

微博粉丝清理工具丨2023年最新粉丝批量清理_微博怎么批量清理粉丝

2023年最新微博怎么批量清理粉丝?可能还有不少小伙伴不太清楚 接下来就为大家带来微博批量清理僵尸粉方法 有需要的朋友可以来了解一下,希望下文可以帮到大家 第一种:客服界面清粉方法 然后在客服中心界面选择修正粉丝; 最后点击一下确认就…

const修饰的成员函数

const修饰的成员函数 问题: 哪里出现编译报错了, 如何修改? class A { public:const int get1() const{a1 10;return a1;}private: int a1 0; }; int main() {A a;a.get1();return 0; }当时以为是a是一个非const对象,调用了const成员函数导致编译错误…

关于guacamole项目中的一点感悟与理解

关于guacamole项目中的一点想法 前言一、guacd模块启动相关二、一些感悟与理解参考 前言 Guacamole 是基于 Web 的 VNC 客户端,使用它可以通过web浏览器访问远程服务器终端并进行操作。它的基本架构如下图所示。 巧合之下,前段时间了解了项目中guacd模块…

构建大数据环境:Hadoop、MySQL、Hive、Scala和Spark的安装与配置

前言 在当今的数据驱动时代,构建一个强大的大数据环境对于企业和组织来说至关重要。本文将介绍如何安装和配置Hadoop、MySQL、Hive、Scala和Spark,以搭建一个完整的大数据环境。 简介 安装Hadoop 首先,从Apache Hadoop的官方网站下载所需的…