测试工程师做好缺陷预防,居然可以避免50%的错误!

这是一张在不同阶段修复Bug所需要的成本演示图,随着时间推移修复Bug的成本将越来越高。所以作为测试团队,如果能将软件Bug在前期就发现并推进修复,将大大降低之后的软件开发成本,也会降低因为后期修复过程中导致二次Bug的概率。

缺陷预防,可以帮助测试工程师减少不小的工作量。

什么是缺陷预防

缺陷预防是指在各种错误遗留到后续开发阶段之前,运用各种技术和过程来发现和避免这些错误。

缺陷预防工作在需求阶段的效率最高,此时修正缺陷所需的改动最小:需要改动的仅仅是需求文档,可能还需要相应地修改此阶段制定的测试计划。如果测试人员(和其他涉众一起)从开发生命周期之初就开始参与项目,那么他们就能够协同发现遗漏、矛盾、含糊的地方和一些其他问题,这些问题可能会影响项目需求的可测试性、正确性以及其他测试质量。

缺陷预防的灵魂——测试思维

正如我们在第一篇文章提到的,测试活动贯穿在软件开发过程的始终。测试人员在各个环节根据自己的经验,对需求的理解,测试技术等提出测试点来帮助产品规避错误的设计,帮助开发Hold住异常的场景,这些依据就是测试思维

什么是测试思维?

我认为,能够站在不同角度(用户角度,开发角度,系统角度等)来思考软件如何运作,如何使用的思维就是测试思维。

测试思维的几个阶段

1、初级: 根据常见的测试用例编写方法设计测试用例,能够站在用户的角度去思考用户如何使用被测试的程序,提出一些异常场景。

2、中级: 知识体系的完善,能站在开发的角度或者系统角度等来对业务流/数据流进行分析和设计用例,深入理解产品需求和实现,理解产品质量。

3、高级:作为测试工程师的目的帮助产品利益最大化,作为软件流水线的最后一道关卡,我们需要更加宏观全面的看待问题:

  • 用户的体验(数据驱动产品):对埋点数据采集的数据分析,对产品的设计有建设性的 意见
  • 项目的进度和质量把控:能够把控时间节点和对应的产出质量
  • 效率提升:引入工具或者开发工具来提升测试效率

4、再高级: 将测试过程标准化,流程化,思考对产品对测试团队的增益。引入软件产品质量模型,将产品的质量划分为不同的维度进行测试,细化测试内容和更加容易的衡量产品质量。

如何培养测试思维?

根据我们列出的测试思维的几个阶段,可以发现一个关键词: 角度。能够站在不同的角度看待问题,需要理论和技术的支撑:

1、丰富软件知识和开发技能,能够理解产品的实现逻辑和如何运作的,从而可以在产品的各个实现环节进行测试设计;

2、产品设计的驱动是基于市场动向,公司发展方向,和用户数据等信息的,所以可以多多关注这几方面的信息跳出测试范畴看待被测程序。

除了这些知识技术的储备之外,还要引入一些先进的测试理念,比如接下来要介绍的探索式测试。

探索式测试助力

探索性测试可以说是一种测试思维技术。它没有很多实际的测试方法、技术和工具,但是却是所有测试人员都应该掌握的一种测试思维方式。探索性强调测试人员的主观能动性,抛弃繁杂的测试计划和测试用例设计过程,强调在碰到问题时及时改变测试策略。

组内推进这种测试方式通过以下两种方式:

1、分享探索式测试的思维方法,将探索式测试的方法内化到每个人的测试思维中。

2、举个例子: 我们会在应用上线前2-3天,集中5-8个测试人员进行30分钟左右的测试。在这个过程中我们使用各种测试方法来弥补测试盲区,记录问题并跟进修改和回测。

缺陷预防的利器——代码静态检查

什么是代码静态检查?

代码静态检查是指在不运行代码的方式下,通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描,验证代码是否满足规范性、安全性、可靠性、可维护性等指标的一种代码分析技术。

在软件开发过程中,静态代码分析往往先于动态测试之前进行,同时也可以作为制定动态测试用例的参考。统计证明,在整个软件开发生命周期中,30% 至 70% 的代码逻辑设计和编码缺陷是可以通过静态代码分析来发现和修复的。

代码静态检查工具我们使用的是SonarQube. SonarQube是开源的静态代码检查平台,支持多达20种语言,支持从7个维度检查代码:

  • Architecture Design: 架构设计
  • Comments: 注释
  • Coding Rules: 代码规则
  • Potential Bugs: 潜在Bug
  • Complexity: 复杂度
  • Unit Tests: 单元测试
  • Duplications: 重复性

我们选择了自己搭建这个平台是为了更快速的响应规则修改以及提供给每个组员学习使用的权限和机会。

如何顺利的开展代码静态检查?

如果有使用过代码静态检查工具的同学可能很快会发现,在实际的项目中该检查很难顺利的开展下去。一般来说,难以开展的原因主要有两个:

1、静态检查规则的不准确。

2、编码时间紧张,代码静态检查占用大量时间。

我们团队在使用代码静态检查的初期也遇到过这几个问题,下面将为大家抛砖引玉介绍下是如何解决的。

规则制定

1、在代码静态检查初期,我们使用原始的规则对代码进行扫描。但是只针对三个级别的Issue和开发人员进行沟通。这三个级别分别是: Blocker, Critical 和 Major。

  • Blocker: Operational/security risk: This issuemight make the whole application unstable in production. 比如内存泄露,未关闭的JDBC连接等等,Issue需要被立刻修改。
  • Critical: Operational/security risk: This issuemight lead to an unexpected behavior in production without impacting theintegrity of the whole application. 比如未处理的异常,可能的SQL注入等,代码需要被Review进行确认。
  • Major: This issue might have a substantialimpact on productivity. 质量缺陷对开发者生产力有一定影响,比如未覆盖的代码、重复的块、未使用的参数等。

2、拿到原始规则的扫描结果后,我们和开发团队进行了进一步的沟通。沟通的主要目的是:

  • 确认扫描结果的准确性: 针对项目的特点和编码习惯, 我们禁用掉不适用的规则。
  • 确认规则的优先级: 提升或者降低一些规则的优先级,从而在修改Issue的时候能够有的放矢。

3、试运行定制后的规则,并进一步进行修改。下图是我们和iOS开发人员沟通后的邮件确认:

自动化执行代码静态检查

为了能减少代码静态检查执行占用的人工时间,我们从三个方向进行了优化。

1、配置Jenkins定期进行代码静态检查。通过定时任务或者代码提交出发的方式,进行静态检查。

2、使用GitHook的方式在提交代码的时候出发代码静态检查。

  • 什么是GitHook? Git Hooks是指在使用Git的过程中某些特殊的事件发生后,将会触发系统执行特定的脚本,这些脚本统称Git Hooks。 Git Hooks通常存储在Git_Dir/hooks/中,下图是系统预装的Git Hooks, 通常情况下这些脚本不会被自动执行,因为他们默认的后缀是.sample。如果我们希望这些脚本生效,只需要去掉.sample的后缀即可。
  • Git Hooks的简单分类 Git Hooks可以简单的分成两类,客户端Hooks(Local Hooks)和服务端Hooks(Server-side Hooks)。Local Hooks 包括: pre-commit,prepare-commit-msg, commit-msg, post-commit, post-checkout和pre-rebase。 Server-side Hooks包括: pre-receive, update和post-receive。
  • Git Hooks的基本使用 因为在代码静态检查中我们只用到了pre-commit,所以这里简单介绍下该脚本的使用。pre-commit的触发的条件是:每次执行命令git commit之后且在Git要求输入commit message或生成commit之前。实际中,通常可以在这段脚本中执行代码的静态检查或自动化测试用例,来保证提交的代码的质量以及不影响已经存在的功能。 1、为了不影响系统自带的Hooks脚本,我们首先将pre-commit.sample 复制成pre-commit,这样该脚本就会生效并起到了备份的作用。 2、编辑文件pre-commit,在脚本的起始位置添加一行语句echo "I am called by 'pre-commit' "。

3、在Demo项目中触发提交git commit -m xxx,查看执行结果:

  • 代码静态检查和Git Hooks 结合 编写hook脚本之前,我们需要明确它的两个核心点: 1、用什么工具扫描? SonarQube的可执行扫描工具是 Sonar Runner, Android 可以使用的是 lint , iOS可以使用的是 oclint. 诸如此类的工具比较多,感兴趣的同学可以自行查询。 2、扫描什么代码?在执行commit操作的时候对所有的代码进行静态扫描明显是不合适的,我们只需要对要提交修改的代码进行扫描即可,所以这里我们用到git diff --name-only HEAD^ 的命令获取修改的代码文件。 3、下面是我们编写的Demo脚本,可以对提交中的Java文件进行静态扫描,使用的是Google Lint。
1. #!/usr/bin/python
2. #coding=utf-8
3. import os
4. importcommands
5. import sys
6.  
7. #本机的环境变量放在~/.bash_profile中,所以每次运行需要执行source ~/.bash_profile。如果配置了全局变量,则不需要
8. (status_bin,output_bin)= commands.getstatusoutput('source /Users/lvchongen/.bash_profile')
9.  
10.#获取当前的脚本路径
11.script_path = os.getcwd()
12. 
13.#获取当前repo的路径
14.(status1,output1) =commands.getstatusoutput('cd ' + script_path)
15.(status2,output2) =commands.getstatusoutput('cd ..')
16.(status3,output3) =commands.getstatusoutput('pwd')
17.repo_path = output3
18. 
19.#设置代码静态检查的工作目录
20.lint_workspace ="/Users/lvchongen/Desktop/Lint"
21. 
22.#设置存储本次commit信息的文件
23.commitLog = lint_workspace +"/commit.log"
24.reportPath = lint_workspace +"/report.html"
25. 
26.#执行shell命令,将本次commit信息写入log中
27.(status, output) =commands.getstatusoutput('git diff --name-only HEAD^ >' + commitLog)
28. 
29.#过滤文件非java文件
30.def getJavaFiles():
31.   sourceFiles = []
32.   commitFile = open(commitLog)
33.   lines = commitFile.readlines()
34.    forline in lines:
35.       result = line.find(".java")
36.       if result != -1 :
37.           fullPath = repo_path + "/" + line
38.           sourceFiles.append(fullPath)
39.   return sourceFiles
40. 
41.#调用Android Lint执行代码静态检查(也可以安装findBugs,CheckStyle,PMD等工具进行代码检查)
42.def analyzeFiles():
43.   sourceFiles = getJavaFiles()
44.   allFiles = ""
45.    foritem in sourceFiles:
46.       allFiles = " " + allFiles.rstrip('\n') +" " +"".join(item)
47. 
48.   lintCommand = 'lint ' + allFiles.rstrip('\n') + ' --disable LintError--nowarn --html ' + reportPath
49. 
50.   print lintCommand
51.   (status_analyze, output_analyze) = commands.getstatusoutput(lintCommand)
52. 
53.   print output_analyze
54. 
55.   result = output_analyze.find("0 errors")   
56.    ifresult == -1:
57.       print "====="
58.       sys.exit(1)
59. analyzeFiles()

当执行完成代码静态检查之后如果存在Issue,将会阻塞代码的提交操作,直到修改完成之后才可以进行提交。当然在本地做代码静态检查的时候也涉及到规则的制定,这里就不详细介绍了。开发移动App的主要两个IDE是Android Studio 和 Xcode

4、IDE插件执行代码静态检查

  • Android Stuidio Android Studio可以安装插件的方式对代码进行静态检查。 在插件管理中搜索Sonar可以找到对应的插件并安装,通过连接SonarQube将本地的项目和SonarQube的Project进行绑定即可。

Android Studio 也可以使用自带的Lint进行代码静态检查:

具体的使用方法可以参考官网:https://developer.android.com/studio/write/lint

  • Xcode Xcode可以通过菜单【Product】中找到选项【Analyze】来对代码进行分析。分析的结果会在左侧的菜单中展示:

所以有以上的几种运行代码静态检查的方式,开发团队和测试团队通过沟通后选择适合自己的方式来对代码质量的提升做出贡献。

质量/效果跟进

SonarQube的Dashboard没有办法完全满足我们的数据统计需求,所以我们自己编写了报告平台,来根据需求采集代码静态检查的结果数据,并定期发送邮件给开发团队。

  • 支持所有项目数据,类项目等方式的统计
  • 支持单个项目的详细数据查询和历史数据的统计

培训与分享

有了这套完备的代码静态检查系统,我们鼓励每个人都学习使用,并对自己的项目进行缺陷预防推进,所以定期的培训必不可少, 不仅对测试内部人员进行分享,还分享给开发团队,大家共同学习进步,提升工程质量。

总结

如果能在测试开始前就将Bug防患于未然,将大大提升产品的质量。我们团队通过提升每个测试工程师的测试思维,并使用SonarQube进行代码静态检查来进行缺陷预防。

我们认为所有能够帮助在Bug未形成之前就解决的手段都是缺陷预防,所以要善于在开发流程中观察不足之处并进行优化,在每次上线之后积极复盘找到优化的方案,这些才是测试工程师保证质量的根本。

下面的内容同样精彩

点击图片即可阅读

移动测试避坑指南(第一篇):从流程到技术的知识概要

新世纪Nerv战士 - 京东首页补完计划

京东技术 ∣关注技术的公众号

原文发布于微信公众号 - 京东技术(jingdongjishu)

原文发表时间:2018-05-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

自动化平台开发小结(三)

今天来继续说说自动化开发的一些事情,截止目前,也是按照计划中的开发进度在推进。说几点自己的感受。 元数据的设计 元数据这部分我的设计就是从简,先来一个概要的信息...

3055
来自专栏北京马哥教育

Python Web 框架大乱斗:哪个框架适合你?

今天,有非常多的Python框架,用来帮助你更轻松的创建web应用。这些框架把相应的模块组织起来,使得构建应用的时候可以更快捷,也不用去关注一些细节(例如so...

2986
来自专栏小巫技术博客

App更新策略课程介绍

722
来自专栏程序人生

Docker: 优雅地部署

在我去年的一篇博客自动化的高效团队开发环境提到了用vagrant来统一开发团队的开发环境。用vagrant基本上解决了开发环境异构的问题,但VM(vagrant...

3258
来自专栏杨建荣的学习笔记

运维开发里程碑的小结

说实话,截止目前,五个功能实现了四个,所以算是基本达标了。后续的改进点依旧有很多,突然发现这样的设计和贯穿,有了一种豁然开朗的感觉。只要行得通,改进也有...

1265
来自专栏智能计算时代

云计算架构:Azure]比较流,逻辑应用(Logic App),函数和 WebJobs

所有这些服务都可以解决集成问题并自动化业务流程。 它们都可以定义输入、操作、条件和输出。 可以在日程安排或触发器中运行其中一个。 但是,每种服务都有其独特的优点...

863
来自专栏Golang语言社区

服务器开发语言比较

下比较的基础都是基于一种编程语言+一定的第三方或者自己编写的网络库和底层进行的,Skynet稍微特殊,但总体比较合适放到比较中来 C# 开发效率:Windows...

38813
来自专栏机器学习算法与Python学习

Python中常用的一些架构

在各种语言平台中,python涌现的web框架恐怕是最多的,是一个百花齐放的世界,各种micro-framework、framework不可胜数;猜想原因应该是...

3444
来自专栏Coding01

构建一份有价值的 Awesome Laravel 清单

跟前几年比,现在越来越多的开发者喜欢使用 Laravel,研究 Laravel。但 Laravel 框架的学习曲线比较陡,市面上各种各样 Laravel 学习资...

702
来自专栏小巫技术博客

Android技术归档

1134

扫码关注云+社区