deju / front-end-test-guide

Front End test guide

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

前端TDD

前端单元测试浅谈

TDD中,要求开发者编写良好的测试。从<<测试驱动开发的艺术>>一书中,探索了如何真正开展的TDD工作,然而实际开展确实有一些困难。当然阅读其他开源项目的测试也能给予一些帮助。

就前端而言,单元测试可操作性相比集成测试等各种测试写起来更容易。所以可以从单测来开始TDD之路。

简单的区分单元测试

  • 需要访问数据库的测试不是单测
  • 需要访问网络的测试不是单测
  • 需要访问文件系统的测试不是单测

良好的代码片段要规避哪些

良好的代码片段是单测的重点,那脏代码又是些什么呢?

  • 条件逻辑过多
  • 构造函数逻辑过多
  • 全局变量过多
  • 静态方法过多
  • 不必要的代码、逻辑
  • 外部依赖过多

TDD的要求

  • 测试要快。快速运行,快速编写。 运行要足够快,否则会降低效率。比如说代码片段要求10行,超过10行就可以考虑进行分拆。每条测试运行在30ms左右。每个代码片段开发在几十秒至几分钟内(当然也有例外)
  • 不可忽略失败的测试 保证测试必定通过
  • 必须要重构 TDD的逻辑是红灯(测试挂) -> 绿灯(测试通过) -> 重构(优化代码),在第二步的时候允许烂代码,甚至返回硬编码

如何做

  • 需求分析,思考实现,进行需求分拆(分拆成测试点,而不是子任务)。此时是需要考虑如何使用,考虑如何“使用”产品代码,是一个实例方法还是一个类方法,是从构造函数传参还是从方法调用传参,方法的命名,返回值等。这时其实就是在做设计,而且设计以代码来体现。此时测试为红
  • 实现代码让测试用例通过,此时为绿
  • 重构,然后让测试通过
  • 最终达到如下状态:
    • 每个概念都被清晰的表达
    • 不允许重复代码
    • 不允许脏代码
    • 通过测试

TDD的工作流

最终目标如下:

  • 一个父单元,依赖两个子单元实现逻辑功能
  • 两个子单元,每个都有单元测试描述他们的各自职责
  • 父单元的测试,描述了两个子单元的交互

其流程可描述为:

  • 1,接手一个新的特性需求 此时可以根据需求描述,制定集成测试的Todo-List,然后来做集成测试的编写(建议集成、单元测试分开进行)

  • 2,分解需求,分成Todo-List(需求拆分、拆分成细小的单元),这个过程需要思考怎么将需求进行拆解以及归纳(如合并到同一个单元)

  • 3,为每个Todo-List制定Test-List

  • 4,按照Test-List编写单元测试,此时不需要立刻解决问题,延迟逻辑实现的编写时间 使用小型、单功能的单元

  • 5,编写代码让上述Test-List通过

  • 6,在保证测试通过的情况下优化、重构代码逻辑

  • 7,对Todo-List中的每个Todo都进行3,4,5,6这几步操作

          // 流程图  
                        新需求 (对应步骤1)
                          |
                          |
              +------+--------+--------+  (步骤2)
            需求1   需求2     需求3     需求4
                              |
                              |
                  +------+---------+--------+   (步骤3)
                测试点1  测试点2   测试点3   测试点4
                         |
                         |
                       编写代码   (步骤4)
                         |
                         |
                       测试通过   (步骤5)
                         |
                         |
                       重构代码   (步骤6)
    

举例:

需求为:做个todolist page,并使用localStorage来进行数据存储(即不需要网络的处理)参考项目

我们对以上的需求进行拆解,可大致得到如下子需求,此过程认为是单元拆解(也就是我们自身的Todo-List) 子需求:

  • 1, 标题部分文字为todos
  • 2, 输入框新增事项
  • 3, 正文区为列表区
  • 4, 列表默认列出所有事项
  • 5, 列表可进行分类列出
  • 6, 每项可以标记为已完成、或者删除
  • 7, 操作区分别展示事项总数、展示的分类、清空操作
  • 8, 页面载入时从localStorage中载入
  • 9, 每项的操作同步更新至localStorage中

上述子需求是在初步拆解后,此时还需要规整下,规整后按照单元来:

  • Header单元
    • 1, 标题部分文字为todos
  • Input单元
    • 2, 输入框新增事项
  • List单元
    • 3, 正文区为列表区
    • 4, 列表默认列出所有事项
    • 5, 列表可进行分类列出
  • ListItem单元
    • 6, 每项可以标记为已完成、或者删除
  • ListControl单元
    • 7, 操作区分别展示事项总数、展示的分类、清空操作
  • LocalStorage单元
    • 8, 页面载入时从localStorage中载入
    • 9, 每项的操作同步更新至localStorage中

将上述的增加测试用例:

  • Header单元

    • 1, 标题部分文字为todos

        a, 标题为todos
      
  • Input单元

    • 2, 输入框新增事项

        a, 用户输入"job",按下Enter, 则返回"job"
        b, 用户不输入,按下Enter,此时不返回
      
  • List单元

    • 3, 正文区为列表区

        a, 无数据时,则显示为空
        b, 有10条数据,则显示10条记录
      
    • 4, 列表默认列出所有事项

        a, 初始有10条数据,全部为未完成,显示10条数据
        b, 有10条数据,5条为已完成,则显示10条数据
        c, 共10条数据,全部为已完成,则显示10条数据
      
    • 5, 列表可进行分类列出

        a, 分类为All,则展示所有事项
            10条数据,全部为已完成,则显示10条数
            10条数据,3条为已完成,则显示10条数据
            10条数据,全部为未完成,则显示10条数据
        b, 分类为Active,则展示未完成事项
            10条数据,全部为已完成,则展示0条数据
            10条数据,全部为未完成,则展示10条数据
            10条数据,3条为已完成,则显示7条数据
        c, 分类为Complete, 则展示已完成事项
            10条数据,全部为已完成,则展示10条数据
            10条数据,全部为未完成,则展示0条数据
            10条数据,3条为已完成,则展示3条数据
      
  • ListItem单元

    • 6, 每项可以标记为已完成、或者删除

        a, 点击删除,则触发删除该项操作
        b, 已完成标记,则触发该项完成操作
      
  • ListControl单元

    • 7, 操作区分别展示事项总数、展示的分类、清空操作

        a, 展示当前事项数量,如4
        b, 展示当前的分类,如All, Active, Complete
        c, 清空操作触发清空操作
        d, 分类切换触发分类改变操作
            点击All, 触发分类All回调
            点击Active,触发分类All回调
            点击Complete,触发Complete回调
      
  • LocalStorage单元

    • 8, 页面载入时从localStorage中载入

        a, localStorage无数据,获取的数据为空列表
        b, localStorage数据为10条,则获取10条数据
      
    • 9, 每项的操作同步更新至localStorage中

        a, localStorage原有0条,增加一条,则为1条
        b, localStorage原有10条,增加一条,则为11条
        c, localStorage原有10条,删除后,为0条
        d, localStorage原有0条,删除后,为0条
      

参考

About

Front End test guide