【DevOps】SVN集成PMD实现代码自动静态检查

在实现SVN集成Checkstyle实现代码自动静态检查之后,除了循序渐进地推动相应规范的落地外,我们当然也不能仅仅将目光局限在偏隅一角。毕竟对于代码静态检查而言,CheckStyle只是其中的辅助工具之一,我们还需要集成更多的检查工具进行交叉校验以加快我们代码规范化的速度,以及进一步提升我们对代码库的信心。

1. 概述

PMD是一款采用BSD协议发布的Java程序代码检查工具。该工具可以做到检查Java代码中是否含有未使用的变量、是否含有空的抓取块、是否含有不必要的对象等。该软件功能强大,扫描效率高,是Java程序员debug的好帮手。

2. 实现

通过阅读相应源码,我们可以发现SVNChecker是提供了相应检查扩展的,因此本次我们依然使用SVNChecker来完成需求。

  1. 下载 pmd-bin-x.xx.x.zip ,解压到相应目录下,建议放到和svnchecker-0.3目录所在的同级目录下。

  2. svnchecker-0.3\checks目录下,拷贝 Checkstyle.py 文件,并将其重命名为 PMD.py

    cp Checkstyle.py PMD.py
    
  3. 修改上一步中生成的PMD.py(为了方便读者,这里将所有的代码(除了顶部版权声明注释)全部贴出来)。

    #coding=utf-8
    #-*- coding: UTF-8 -*- 
    
    from modules import Process
    
    def run(transaction, config):
        # 默认只检查Java文件
        check = config.getArray("PMD.CheckFiles", [".*\.java"])
        # 设置检查白名单, 默认为空
        ignore = config.getArray("PMD.IgnoreFiles", [])
        files = transaction.getFiles(check, ignore)
        # java命令工具所在位置
        java = config.getString("PMD.Java")
        # java classpath路径
        classpath = config.getString("PMD.Classpath")
        # PMD配置规则所在路径
        config = config.getString("PMD.ConfigFile")
    
        # 执行PMD命令的格式
        command = "%s -classpath %s net.sourceforge.pmd.PMD -R %s -dir " % (java, classpath, config)
    	
        files = [transaction.getFile(oneFile[0]) for oneFile in files.iteritems() if oneFile[1] in ["A", "U", "UU"]]
        if len(files) == 0:
            return ("",0)
        try:
            # 这里的截取字符串是比较有争议的位置.
            # 在笔者的测试中, pmd命令执行的时候, 配置参数 -filelist 存在比较多的问题, 因此更推荐使用 -dir 来指定目录来进行检查, 因此我们需要获取到本次提交到SVN库中的所有Java文件路径的共同路径。
            # 关于如何获取本次提交到SVN库的java文件暂存路径, 可以采用如下方式进行调试:
            # import sys
            # sys.stderr.write(files[0])
            # sys.exit(1)
            Process.execute(command + files[0].split("src/main/java")[0])
        except Process.ProcessException, e:
            msg = "Coding pmd errors found:\n\n"
            msg += e.output + "\n"  #
            msg += "See PMD documentation for a detailed description: http://PMD.sourceforge.net/"
            return (msg, 1)
    
        return ("", 0)
    
  4. 修改SVNChecker配置文件svncheckerconfig.ini(依然贴出所有相关的部分,省略无关细节)。

    [Default]
    
    #This property tells Subversionchecker about all checks
    #(UnitTests, AccessRights, XMLValidator etc) it should execute.
    #Separated with comma (",")
    # 增加 ,PMD
    Main.PreCommitChecks=CheckStyle,PMD
    
    # =================================================== PMD (PMD相关配置)
    #Path of java executable to run PMD command
    PMD.Java=java
    
    #Classpath for executing PMD rules
    PMD.Classpath=F:/_svnChecker/pmd-bin-6.20.0/lib/*
    
    #Configuration file for PMD to run its rules.
    PMD.ConfigFile=rulesets/java/quickstart.xml
    
    #In case of failures, where should Subversionchecker redirect the errors
    PMD.FailureHandlers=Console
    
  5. 修改svnchecker-0.3/Main.py文件。

    globalConfig =  os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), configFilename)
    # 第56行, 将globalConfig, localConfig调换位置, 优先读取本地配置  
    config = Config.Config(localConfig, globalConfig)
    config.setHooksLocation(os.path.join(reposPath, "hooks"))
    

3. 效果

以上配置正确生效之后,研发人员在进行代码提交时,应该可以得到如下效果:
【DevOps】SVN集成PMD实现代码自动静态检查_第1张图片

4. 延伸

很多时候,规则的执行必须循序渐进,代码规范也不例外。对于一个公司而言,需要长期维护的既有产品以及不断发展的新产品相当于人的两条腿,缺一不可。为了减少对既有产品项目的大幅修改导致的不稳定性,我们一般会将代码规范拆分为OLD,NEW两个版本。新产品项目使用NEW版本,而既有产品项目则使用OLD进行缓慢迭代。

以上方法经过笔者所在公司的数月试行,发现存在一个非常尴尬的问题:“对于那些存在于NEW版, 而OLD版中没有的规则,我们无法确保既有产品项目的维护人员遵守它们”,对这些规则,如果完全依赖于人工审核,这将耗时耗力,也无法确保没有纰漏。

所以我们需要仿造本文里的方式,建立扩展的CheckStyleForNew.py扩展检查。

  1. svnchecker-0.3\checks目录下,拷贝 Checkstyle.py 文件,并将其重命名为 CheckStyleForNew.py
    def run(transaction, config):
    
        ...
        config = config.getString("CheckstyleForNew.ConfigFile")
    
        ...
    	# 删除 ["A", "U", "UU"] 中的后两个元素, 只留 ["A"] ; 即只针对新增文件进行检测 
        files = [transaction.getFile(oneFile[0]) for oneFile in files.iteritems() if oneFile[1] in ["A"]]
    
    
  2. 修改SVNChecker配置文件svncheckerconfig.ini ,新增以下内容。
    # =================================================== CheckStyle For New
    CheckstyleForNew.ConfigFile=F:/_svnChecker/checkstyle-NEW.xml
    CheckstyleForNew.FailureHandlers=Console
    
    Main.PreCommitChecks=Checkstyle,CheckstyleForNew,PMD
    

5. 关于静态代码分析

静态代码分析是指无需运行被测代码,仅通过分析或检查源程序的语法、结构、过程、接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数不匹配,有歧义的嵌套语句,错误的递归,非法计算,可能出现的空指针引用等等。

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

但是,由于静态代码分析往往要求大量的时间消耗和相关知识的积累,因此对于软件开发团队来说,使用静态代码分析工具自动化执行代码检查和分析,能够极大地提高软件可靠性并节省软件开发和测试成本。

静态代码分析工具的优势:

  1. 帮助程序开发人员自动执行静态代码分析,快速定位代码隐藏错误和缺陷。
  2. 帮助代码设计人员更专注于分析和解决代码设计缺陷。
  3. 显著减少在代码逐行检查上花费的时间,提高软件可靠性并节省软件开发和测试成本。

6. LInks

  1. Office Site - PMD CLI reference
  2. SVN集成Checkstyle实现代码自动静态检查
  3. SVN之常用Hook

你可能感兴趣的:(DevOps,SVN,pre-commit,PMD,代码质量静态检查)