覆盖的15中方法

上传人:j****9 文档编号:45690910 上传时间:2018-06-18 格式:DOCX 页数:7 大小:32.46KB
返回 下载 相关 举报
覆盖的15中方法_第1页
第1页 / 共7页
覆盖的15中方法_第2页
第2页 / 共7页
覆盖的15中方法_第3页
第3页 / 共7页
覆盖的15中方法_第4页
第4页 / 共7页
覆盖的15中方法_第5页
第5页 / 共7页
点击查看更多>>
资源描述

《覆盖的15中方法》由会员分享,可在线阅读,更多相关《覆盖的15中方法(7页珍藏版)》请在金锄头文库上搜索。

1、1. 代代码码覆覆盖盖即代码所有路径被经过,这种需要注意的是:不应该覆盖而被覆盖的情况。例如某种特殊异常就是不期望遇到的,但是遇到了,异常处理的代码也覆盖了,这时,我们应该追溯异常产生的根本原因,而不因覆盖了就直接忽略。提示:不仅要关注未覆盖的代码,也要关注覆盖的,特别是偶然覆盖的代码。2. 废废弃的功能弃的功能一些功能点随着产品版本不断更新,可能会被取消,这部分功能可以直接移除,保留只会让代码看起来越冗余。如果某天需要参考或找回删除的那些代码,CVS/SVN 工具就搞定了。提示:不用的功能不需要覆盖,要及时删除,不通过保留或者注释的方式残留在代码中。3. 工具工具类类(助手(助手类类)、常量

2、)、常量类类等的私有构造器等的私有构造器工具类和常量类共有的特征是对外开放的都是静态方法,调用方法的时候,无需创建实例,所以推荐实践是创建一个 private 的构造器方法。这导致类的构造器代码无法覆盖(不考虑反射等方式)。相反,如果某天发现对于这样的类覆盖率为 100%,那检查下是否代码写的不规范: 用默认构造器,然后通过实例来调用静态方法。例 1:工具类public final class StringUtil public static String concatWithSpace(String. strings) return concat(MarkConstants.SPACE, s

3、trings);public static String concatWithSemicolon(String. strings) return concat(MarkConstants.SEMICOLON, strings);private StringUtil() 例 2:常量类public final class MarkConstants /* value*/public static final String SEMICOLON = “;“;private MarkConstants() 提示:工具类(助手类)、常量类等的私有构造器不能被覆盖4. 日志日志级别级别配置配置日志级别不同

4、,覆盖率高低也不同。在产品部署中,很少将日志的级别设成 debug,因为日志占用磁盘空间会增长很快。只在做一些问题跟踪、调试时才会调高日志级别。所以环境使用不同的日志级别,也会导致一些日志代码没有覆盖。如以下示例程序,不打开 debug 级别无法覆盖部分代码:public static String formatPath(String path) ValidationUtil.checkString(path);String returnPath = path.trim();if (!returnPath.startsWith(SPLIT)returnPath = SPLIT + return

5、Path;if (returnPath.endsWith(SPLIT)returnPath = returnPath.substring(0, returnPath.length() - 1);if (LOGGER.isDebugEnabled()LOGGER.debug(String.format(“utilconvert %s to %s“, path, returnPath);return returnPath; 那么这部分代码需要覆盖嘛?需要。 假设代码误写成:LOGGER.debug(String.format(“utilconvert % to %s“, path, returnP

6、ath);某天日志级别设为 debug,就会发现报错。类似的还有日志中经常输出某个对象信息,但是该对象可能是null,从而抛出空指针异常。提示:日志也是代码的一部分,需要通过调整日志级别来覆盖。5. JVM 等参数等参数程序的配置参数会直接影响代码路径覆盖,不仅包括业务上的一些配置,也包括依赖平台的参数,例如 JVM参数除了会影响性能,也会影响代码的覆盖情况,例如断言相关参数:-ea:.|: 和-da:.|: 分别是启用和关闭用户断言(-esa/-eda,针对系统断言),在 JAVA 中断言是默认关闭的,所以涉及断言的代码默认无法覆盖。提示:一些代码路径能否覆盖与 JVM 等参数有关,需要通过

7、调整参数来覆盖6. main()方法方法一些程序员喜欢临时写一个 main()方法方便于测试,完成测试后寻思以后还能方便测试就留了下来。导致产品代码中的这些代码无法被覆盖。在产品代码中,应该删除这些,部署的毕竟是产品代码,不是测试代码。提示:main()方不需要被覆盖,产品代码不保留测试代码7. 编码习惯编码习惯写法写法在编码过程中,常常有一些习惯写法,最常见的比如:(1) 覆盖 toString()方法; (2) 以意义配对形式写一些方法:比如数据连接中 Connect()搭配 DisConnect(), 枚举中常用的 toString()搭配 fromString(),这些惯用的写法告诉读

8、者一些涵义,但是不见得所有的方法都必须被调用,例如在产品应用中,我们可能启动起一个周期性的 job,但是本身尚未添加“取消“功能(或本来就不需要停止)。自然也就无法调用: 但是它应该不应该存在?笔者认为作为完整的功能应该存在。 类似的还有异常定义的时候,会定义很多重载的方法,虽然不见得每个都调用,但是不定某天就会被调用。提示:编码习惯写法造成的未覆盖代码需要被覆盖,是代码的一部分。8. 项项目的使用方式目的使用方式下面两种使用方式会造成代码不能全部被覆盖:1.客户端 Jar 方式:部分代码作为客户端 Jar 包形式提供给他人使用;2.分布式系统交互:分布式系统之间存在交互时,例如从系统 1 复

9、制文件到系统 2,如果始终按照从 1 到 2 的顺序,又仅仅统计系统 1 的代码覆盖肯定不能覆盖全部。 需要覆盖的代码虽出于一处,但是使用方式不同也会导致在不合并覆盖数据情况下代码未覆盖。提示:项目使用方式造成的代码覆盖统计数据分散需要通过合并数据来覆盖。9. 常用最佳常用最佳实实践践一些很难覆盖的最佳实践:例如对于一些资源(IO,lock)的释放,可能直接 trycatch 然后记录异常,这些异常一般很难发生。public static void close(InputStream inputStream)try inputStream.close(); catch (Exception e

10、) LOGGER.warn(“fail to close inputstream“);提示:常用最佳实践可以不覆盖。10. 被拒被拒绝绝的的馈赠馈赠在接口/抽象类定义的时候,有时候定义的一些方法子类并没有都实现,即常说的被拒绝的馈赠(Refused Bequest),这种问题如果是为了短期扩展需求多加了一些方法也可接受,否则还是需要重新继承体系设计。提示:子类未使用“馈赠”,无需覆盖,需重新审视继承体系结构。11. 代代码码覆盖工具未做合并覆盖工具未做合并做代码覆盖时,往往工具本身不支持“合并”的功能,这导致以下问题存在:时间上:1.例如对于拥有 cache 的系统: 系统经过一段时间运行后,

11、重新测试得到的代码覆盖往往不包括 cache miss 的情况。2.手工测试问题:每次统计都需要重新完成全部手工测试,否则将丢失数据。空间上:1.负载均衡:现在大多系统应用都采用负载均衡技术,如果测试时间不够长且只统计一台系统的代码覆盖情况,往往不全面。提示:代码覆盖本身要支持“合并”功能,对多个系统、不同时间的数据进行合并,才能覆盖的完整全面。12. 系系统逻辑统逻辑重复重复这里可分为两种情况:1.组件之间重复:上层系统可能会对数据合法性做检验,但是下层系统出于系统的独立性目标,也可能对数据做二次校验,但是作为一个完整系统进行 end-to-end 测试时,就无法覆盖二次校验的代码;针对这种

12、情况,需要拆开成独立组件进行测试。2.组件内部重复:同一组件内多层重复逻辑确实可以纠正代码,例如在对于某个数据做多次同一类型校验,这种问题常出现于多人协同编码又缺乏沟通的情况中。提示:逻辑重复导致的部分未覆盖要分辨是组件之间还是组件内部冗余,组件之间则需要覆盖,组件内部则要修改代码。13.代代码码写法写法有时候某些代码的写法,也会导致无法覆盖,例如对于代码调用顺序:多个类调用读取配置文件,而稍晚些调用的再次判断配置文件是否初始化,自然为已初始化。再如对于单例,某些代码写成这样:private static SingleInstance INSTANCE = new SingleInstance

13、();public static SingleInstance getInstance() if (INSTANCE = null) INSTANCE = new SingleInstance(); return INSTANCE; 提示:代码写法造成的未覆盖,需要审查下是代码问题。14. 隐隐式的分支式的分支当代码中含有隐式的分支时,往往很难 100%覆盖,例如上文提到的断言 assert,貌似只有一句,但是即使启用断言仍然无法 100%覆盖,例如下例还是显示黄色:分支未覆盖。public class AssertCodeCoverage public void verify(Boolean

14、 b) assert b;究其原因,查看编译后的 class 可知,存在第三条指令:判断是否启用断言。在实际应用中,要么启用要么关闭,所以不可能覆盖所有分支。只能说启用断言,或许能提高指令覆盖率,下图为启用及关闭断言的覆盖率对比:public void verify(java.lang.Boolean b);0 getstatic com.test.coverage.AssertCodeCoverage.$assertionsDisabled : boolean 163 ifne 216 aload_1 b7 invokevirtual java.lang.Boolean.booleanVal

15、ue() : boolean 2810 ifne 2113 new java.lang.AssertionError 3316 dup17 invokespecial java.lang.AssertionError() 3520 athrow21 return0x9a ifne当栈顶 int 型数值不等于 0 时跳转。因此,从这个角度来说,想覆盖断言,不仅要关闭断言完成测试用例,还要在开启断言情况下完成测试。提示:隐式的分支(黄色)需要分析未覆盖分支。15. 不在覆盖范不在覆盖范围围内内下面两种类型的代码不在代码覆盖统计范围内:1.Java 接口,接口里面都是抽象方法的结合,不含有任何代码细

16、节;2.不含有可执行 java 字节码的方法:抽象方法和本地 native 方法。abstract class AbstractService abstract String getString(); /不做统计String getName() return getString().trim(); public class BaseService extends AbstractService OverrideString getString() return “zookeeper“; 提示:不在统计范围内的直接忽视。小小结结: :通过对上面 15 种典型情况的概括,相信大家对代码覆盖的常见情景已有大概印像,在实际分析中,可以按照以下规则进行:1.内容:包-类-方法-代码;2.优先级: 核心业务类-普通业务类-工具助手类-常量类;

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号