Skip to content

Latest commit

 

History

History
236 lines (142 loc) · 11.5 KB

best-practices.md

File metadata and controls

236 lines (142 loc) · 11.5 KB

自动化最佳实践

背景

项目演进

业务价值和技术生产力的关系

多数情况下,我们验证 idea 可行后,才会投入更多的时间、精力去演化这个项目。项目在不同时期面临的主要挑战也不尽相同:

  • 短期:技术实践与业务进度的冲突。即我们在追赶业务进度的同时,如何实施好的技术实践。
  • 长期:人员能力增长、架构演进以及代码实践。

初期

  1. 技术准备期:进行探索技术、概念验证、第一轮迭代等,从搭建脚手架,到部署测试等等;
  2. 业务回补期:调配落后业务进度与先进生产力、与第三方协作磨合,通过技术实践业务来证明技术的价值。
  3. 成长优化期:持续地对项目的技术和业务进行优化,以实现开发及业务人员的诉求。

在面对技术不熟悉、业务又过急的情况下,测试往往是最先被抛弃的一环。这种代码质量、测试覆盖率和依赖技术升级等等技术债务长期的累积,很容易抵消先进技术生产力的收益。

成长优化期,自动化辅助的代码审查、测试和小步快跑式的代码重构一般会变成工作常态。

长期

提升开发体验

业务进一步实施,我们在堆砌业务代码过程中,如何解决大量的类重复性代码问题、保持先进的技术生产力?

常常使用的方法:

  1. 抽象 DSL 代码
  2. 自动化编写,如 UI层 Sketch2Code、逻辑和数据层 Java XML 编程等
  3. 垂直业务领域的视觉设计规范和组件库
  4. 落地生产力,赋能自身、外包和研发伙伴的快速业务实践

总结

综合项目演变过程,我们可以发现:对于一个长期稳定更新版本频繁用户量巨大,同时业务量级别也在很高层面的时候,自动化就从可有可无变成了一个不可或缺的地位

解决问题

主要解决手工的业务测试、国际化测试和交付时的产品验收过程中,存在的操作重合、回归测试周期长等问题。

支持技术债和代码重构过程的回归验证。

价值

  • 初期:自动化收益 = 迭代次数 * (全手动执行成本 - 维护成本) - 首次自动化成本
  • 长期:自动化收益 = 脚本创建成本 + 维护次数 x 维护调试成本 + 脚本失败次数 x 脚本排错成本

成本

自动化运营闭环

服务 问题域 分析测试结果 解域 缺陷处理推动
业务缺陷 标准化到测试环境,每日自动运行 2 次,并将自动测试结果以即时消息方式通知相关工作群 人工复现,手动创建 每日 9:00 自动推送最新动态,包括 每周 Action自动化测试脚本录制动态缺陷跟踪 个别缺陷的人工跟进和推动
国际化 标准化到测试环境,并将自动测试结果以即时消息方式通知国际化工作群 一键创建Issue 每天 9:00 点定时发送和 国际化缺陷跟踪 日报 个别缺陷的人工跟进和推动

自动化测试效果达成,有很多的因素。需注意下“前置准备”一节中的内容。

拓展应用场景边界

随产品生命周期和项目演进,渐进明细的需求。

应用场景 需求启始和演变 输出形态 解域影响 关注点
E2E 功能测试 自动化测试工具和服务 测试报告及缺陷列表 工作群通知 + 缺陷跟踪管理 + 人工推动
国际化 增值,国际化自动化测试服务 测试报告及缺陷列表 钉钉通知 + 缺陷跟踪管理 + 人工推动
交付时的验收工具 要有高效的验收? => 连接客户环境的验收服务 => 验收工具 => 与部署交付流程集成 部署简报(成功或失败)+ 报告 核心流程、覆盖模块、成本收益(效率提升)、服务稳定性

目标

自动化发现业务功能缺陷和国际化缺陷,追踪缺陷处理状态,并推动缺陷处理。

长期项目中,降低技术因素(比如人员能力增长、架构演进或代码实践等)对产品质量的影响。

前置准备

1. 什么项目适合自动化

如果符合短期变动频繁复用度较低的特征,那么是不适合自动化的。

2. 自动化的介入时间点

自动化测试的长远价值高于手工,所以如果自动化的性价比已经开始高于手工,就可以着手去做。项目后期和维护期,自动化介入为回归测试做准备,可以最大化自动化收益

3. 和团队、技能储备、基础设施与工具匹配的自动化策略

4. 管理层的理解程度和支持

5. 公司规章制度的限制

6. 自动化测试效果达成因素

要素

变量:被测产品业务流程片段

恒量:业务流程,即高可信度的自动化测试用例和脚本;稳定的测试数据

干扰:被测产品网络情况、接口性能等

发展阶段

1. 工具化

被测试环境

被测产品环境 自动化测试代码库 持续集成测试服务和报告 国际化测试报告
- - - -

测试用例、计划和缺陷管理

目标:直观有效地提升对业务的价值

确保测试服务稳定、问题原因快速定位和自动反馈机制,以提高缺陷准确、集中跟踪和管理

自动化测试工具

UI Recorder + F2eTest 、国际化测试的 Chrome 扩展等

2. 服务化

“UI Recorder + F2eTest + 持续集成引擎 + 国际化报告服务 + Hubot/钉钉机器人 + 健康大盘”

持续集成

持续集成(CI)服务、用例、测试计划、任务分派和缺陷管理

  1. 有项目测试计划问题、与国际化测试服务集成的友好度
  2. 测试报告中失败用例原因定位,转化成缺陷过程
  3. ChatOps 式自动反馈机制
  4. 对缺陷的优先级(/紧急程度)分类和处理状态跟踪

增值:国际化报告

完善的国际化全链路闭环,应该是:从开发过程文案抽取、持续集成阶段静态扫描、测试环境自动化监测和半自动化的人工检查,到线上用户反馈

国际化中,问题往往集中于布局,其他有:多语言混杂、标点全角/半角混用、时间或货币格式错误等

提效功能点有:一键从报告中创建缺陷、测试报告 NewsLetter 支持等

增值:健康大盘

  1. 多环境管理和快速切换的 Chrome 扩展。主要功能:各环境健康大盘、环境列表及帮助、当前环境和版本识别、切换调试模式、监测后端接口可用状态

3. 容器化

私有部署环境的自动化验收;与 DevOps 集成

Docker 技术

Kubernetes 技术

最佳实践

记住:分形是个好东西。

一个基本的自动化测试闭环是:在明确必须的核心功能后,协调准备最小业务数据,建立丰富测试脚本机制。最后,配合测试计划、缺陷管理、保障持续集成服务稳定和沉淀高可信度脚本。

循环上述闭环、分阶段推进,是确保期望达成的重要经验。

1. 明确核心的测试用例

核心就是关键功能。评估标准:1)用户关键常用功能、是必现路径;2)测试所有关键应用

  1. 可以复用手工测试过程中产出的冒泡用例
  2. 最好协调 PD 和测试同学标筛选出 “Core” 的测试用例

2. 有最小业务数据

可以和数据团队协作 benchmark 工具,实现自动初始化和重置的能力。

最小业务数据的作用:

  1. PD 等做产品演示使用和推广
  2. 交付客户时做用户培训
  3. 用于规范和统一基准测试、API 测试和功能测试等等数据依赖,降低脏数据干扰

3. 要建立丰富测试脚本的机制

  1. Todo

4. 测试计划和缺陷管理

  1. 为方便排查错误的测试脚本,需找到管理测试脚本(是否高可信)、测试用例(是否正常、覆盖的功能模块)、相关的缺陷、测试负责人、研发负责人(前端、后端和算法等)关系自动化关联的最佳方法。

    如通过 git hooks 将测试脚本和测试负责人关联起来等

  2. 用例关联的缺陷中标记 “自动测试脚本 xxx, 受影响脚本 xxx,xxx“,便于问题修复后执行测试脚本验证。在测试服务上验证通过后再更改缺陷状态

5. 服务稳定

  1. 多人共同管理测试服务、分派专人负责改进不同模块脚本的质量
  2. 明确会导致报告 fail 的不可避免的场景:被测 Web 宕机或公共接口失败、网络抖动等
  3. 如遇到上次 fail 时,建议手工运行一次,关注本次 fail 的脚本报告。必要时本地调试下,验证下是否有遗留的测试数据未清理成功
  4. 经常会遇到页面改版、组件调整、接口失败、依赖数据变动等情况,造成测试脚本失效、测试报告 Fail
    • 如页面改版、组件调整或脚本问题,则改进脚本,紧急情况可临时隔离脚本到 specs_bak ,重命名为 xx.spec-fail.js ,问题解决后恢复到 specs 目录
    • 如研发缺陷则隔离脚本到 specs_bak 重命名为 xx.spec-delay.js ,问题解决后恢复到 specs 目录
  5. 如本地正常仅测试服务报错,则隔离脚本到 specs_bak ,重命名为 xx.spec-fail.js ,问题解决后恢复到 specs 目录

6. 高可信度测试脚本

  1. 推荐免登账号,直达测试页面

  2. 推荐录制具有基本 CRUD 功能点的 “小而美“的脚本,复杂场景可通过依赖解决

  3. 为支持全球化测试,要禁用 text 选择器 和 value 选择器

  4. 解决名称重复问题,可通过定义随机字符串名称来解决。示例:

    // 生成长度为 10 的随机字符串
    const randomName = Math.random().toString(36).substr(3);
    module.exports = function () {
    ...
    it('click: Name ( #cn, 106, 26, 0 )', async function () {
        await driver.sleep(300).wait('#cn', 30000)
          .sleep(300).mouseMove(106, 26).click(0);
      });
      it(sendKeys: cn_${randomName}, async function () {
        await driver.sendKeys(cn_${randomName});
      });
    }
    ...
  5. 录制中可能会生成对数据依赖的选择器,推荐调整为较通用的选择器

  6. 资源管理:上传文件。解决方法,参考 How to record file upload?