熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

巧用工具 為Java程序生成代碼做覆蓋統計

2013-11-23 18:45:19  來源: Java核心技術 

  曾經為大家相信介紹過款常用Java測試工具代碼覆蓋率工具這項軟件測試過程中使用的一個重要的工具卻從來沒介紹過來為Java?程序生成測試的覆蓋率結果並提供了關於怎樣分析結果以改進測試的信息本文向您展示了怎樣使用IBM一款開發工具(IBM? Rational? Application Developer)中提供的代碼覆蓋工具如何來為Java?程序生成測試的覆蓋率結果

  什麼是Rational Code Coverage特性?

  代碼覆蓋率是軟件測試的一個重要方面對於一個構件的總體系統測試來說可能是一個基本的參數覆蓋工具背後的動機向您(作為開發員或者測試員)提供了關於代碼的一系列觀點這些代碼在一系列的測試之中會得到檢查該信息會非常的有用因為您可以使用它來設計新的測試用例以獲得足夠的覆蓋范圍

  IBM? Rational? Code Coverage特性是一個與IBM? Rational? Application Developer相集成的工具您可以使用它來生成並分析關於Java程序的覆蓋率統計數據工具會為測試下的程序生成聲明覆蓋率統計數據(這就是說執行程序中行的數量與百分比)

  Rational Code Coverage特性現在只能獲得Rational Application Developer 版本及其後續版本本文假設您使用的是Rational Application Developer 版本對代碼覆蓋率而配置IBM? WebSphere?Application Server的部分假設您使用的是版本但是提供的指南的一些調整仍然適用於上述版本

  指南

  為了適當地分析Rational Code Coverage特性中的覆蓋率統計數據理解場景背後所用到的技術是非常重要的

  Eclipse Test與Performance Tools Project(TPTP)中提供的Rational Code Coverage特性所使用的工具引擎Probekit用於控制一個類的比特代碼並引入覆蓋率數據收集引擎的通用訪問提供了關於這個過程的一個高層次的概述

  
Rational Code Coverage執行環境的概述

  基本快與可執行的單元

  Probekit是一種在Eclipse平台上的框架並可以操作所謂可執行單元的比特代碼可執行單元的定義與基本塊的傳統定義有輕微的不同但是當您在分析結果時您就需要去關注這點差異了

  根據定義一個所謂的基本塊就是一系列的指南這些指南不能再進行分支或者分散這裡的關鍵思想在於當第一個指南運行的時候該塊中隨後所有指南都一定會得到執行而且不會得到中斷接下來的是一個基本塊它可以認為是一個單個組或者一系列的指南通常來說基本塊的結尾是branchcallthrow或者return聲明

  一個可執行的單元由每一個基本快開始而與每行源代碼相對應的指南與前面版本中的指南有所不同可執行的單元與基本塊的不同點在於決定一個可執行單元末尾的因素例如pide指南並沒有認為是一個可執行單元的結尾盡管有例外情況的存在

  Probekit是Rational Code Coverage特性所使用的以將通用代碼引入到每一個可執行的單元之中結果來說您可以定制Rational Code Coverage特性以向組成性(換句話說就是塊覆蓋率)可執行單元層次報告統計數據為了知道這些工具是怎樣更改類了您可以參考接下來的代碼清單與代碼清單代碼清單提供了未處理類的分解輸出(從javap工具來)同時代碼清單為處理過的類提供了分解輸出注意代碼清單中italics的行就是作為處理步驟一部分導入的代碼部分

  清單未處理的類文件

  Compiled from Partjava

  public class comibmstoreappmodelsPart extends javalangObject{

  public comibmstoreappmodelsPart(int);

    Code:

     :   aload_

     :   invokespecial   #; //Method java/lang/Object<init>:()V

     :   iload_

     :   bipush 

     :   if_icmple      

     :  aload_

     :  iload_

     :  invokespecial   #; //Method setDiscountedPrice:(I)V

     :  goto   

     :  aload_

     :  iload_

     :  putfield        #; //Field price:I

     :  return

  

     public int getPrice();

    Code:

     :   aload_

     :   getfield        #; //Field price:I

     :   ireturn

  

  }

  清單每一個可執行單元處理的類文件

  Compiled from Partjava

  public class comibmstoreappmodelsPart extends javalangObject{

  public comibmstoreappmodelsPart(int);

   Code:

    : ldc #; //String com/ibm/storeapp/models/Part : iconst_ : iconst_ :

      invokestatic #; //Method llc_probe$Probe__executableUnit:(Ljava/lang/String;II)V

   :   aload_

   :   invokespecial   #; //Method java/lang/Object<init>:()V

   : ldc #; //String com/ibm/storeapp/models/Part : iconst_ : iconst_ :

      invokestatic #; //Method llc_probe$Probe__executableUnit:(Ljava/lang/String;II)V

   :  iload_

   :  bipush 

   :  if_icmple      

   : ldc #; //String com/ibm/storeapp/models/Part : iconst_ : iconst_ :

      invokestatic #; //Method llc_probe$Probe__executableUnit:(Ljava/lang/String;II)V

   :  aload_

   :  iload_

   :  invokespecial   #; //Method setDiscountedPrice:(I)V

   : ldc #; //String com/ibm/storeapp/models/Part : iconst_ : iconst_ :

      invokestatic #; //Method llc_probe$Probe__executableUnit:(Ljava/lang/String;II)V

   :  goto   

   : ldc #; //String com/ibm/storeapp/models/Part : iconst_ : iconst_ :

      invokestatic #; //Method llc_probe$Probe__executableUnit:(Ljava/lang/String;II)V

   :  aload_

   :  iload_

   :  putfield        #; //Field price:I

   : ldc #; //String com/ibm/storeapp/models/Part : iconst_ : iconst_ :

      invokestatic #; //Method llc_probe$Probe__executableUnit:(Ljava/lang/String;II)V

   :  return

  

   public int getPrice();

   Code:

   : ldc #; //String com/ibm/storeapp/models/Part : iconst_ : iconst_ :

      invokestatic #; //Method llc_probe$Probe__executableUnit:(Ljava/lang/String;II)V

   :   aload_

   :   getfield        #; //Field price:I

   :  ireturn

  static {}; Code: : ldc #; //String com/ibm/storeapp/models/Part : ldc #;

      //String Partjava : ldc #; //String <init>(I)V+setDiscountedPrice(I)V

      +getPrice()I : ldc #; //String #+ : invokestatic #;

      //Method llc_probe$Probe__staticInitializer:

      (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V : return

  

  }

  在Rational Application Developer中生成覆蓋率統計數據

  Rational Code Coverage特性的一個主要的優勢在於您可以通過切換到項目Properties的Code Coverage窗格來將其在Rational Application Developer中的Java項目上激活如圖所示

  
項目Properties中的代碼覆蓋窗格

  選擇圖中的Enable code coverage復選框以激活項目的代碼覆蓋率並評價覆蓋下項目的類您還可以使用該窗格來定制可接受的覆蓋率層次接下來描述了組合的支持層次

  ◆類型覆蓋率一個類中覆蓋的類型百分比

  ◆方法覆蓋率一個類中覆蓋的方法百分比

  ◆行覆蓋率類文件中覆蓋的行百分比

  ◆塊覆蓋率一個類文件中覆蓋的塊的百分比注意一個塊會參考一個可執行的單元(如以前描述的那樣)

  您還可以指定通用的篩選規則而且它們可以用於控制在項目中評價哪些內容默認條件下項目中的所有類都會得到評價但是您可以創建通用的篩選規則來排除目標包或者指定類型如果您需要限制結果的話

  Package Explorer

  在您激活一個項目中的代碼覆蓋率以後覆蓋率統計數據就會在下一次程序啟動的時候生成注意不是所有類型啟動配置都會自動生成統計數據顯示了Rational Application Developer內支持的啟動類型

  表支持的啟動配置

   啟動類型 Java Applet OSGi框架 JUnit JUnit插件測試 Java程序 Eclipse程序 標准Widget Toolkit (SWT)程序

  該程序是一個不同交通工具(汽車貨車摩托車等等)的簡單再現中是一個概括了該程序結構的UML圖

  
范例程序的UML圖

  在項目中有兩種定義好的JUnit測試TestCarjava與TestCarImprovedjava正如其名字所暗含的一樣這些測試的目標是Carjava類而在Rational Application Developer的Java視角中您可以右擊TestCarjava並選擇Run As > JUnit test來啟動TestCarjava測試JUnit測試的結果會正常顯示在JUnit視圖中覆蓋率數據的結果會集成到Rational Application Developer UI中而且您可以切換回Package Explorer來分析它們顯示了TestCarjava測試的一個范例結果

  圖Package Explorer中顯示的TestCarjava的覆蓋率數據

  默認條件下UI只與行覆蓋率信息一起注釋但是您可以在工作台偏好中更改它們並且可以選擇為包類型以及塊而包含覆蓋率每一個Java項目的百分比是最後一次執行代碼覆蓋率的中斷您可以在Package Explorer中深入研究各種Java工件(例如類型與方法)以得到較低組合層次上的覆蓋率統計數據

  結果得到的結果的顏色情況取決於成功率默認條件下紅色意味著沒有達到可接受的覆蓋率層次而綠色則意味著得到了適當的覆蓋率范圍一般來說測試的目的在於達到類可接受覆蓋率層次的結果

  基於如圖所示的結果第一個測試是不充分的Car類(以及抽象父類AbstractFourWheelVehicle和Vehicle)並不能達到適當的覆蓋率層次幸運的是您有第二次嘗試的機會TestCarImprovedjava您可以再一次將測試作為一次正常的JUnit執行而結果將會在Package Explorer中進行自動更新(圖

  
Package Explorer中顯示的TestCarImprovedjava的代碼覆蓋率數據

  Java編輯器

  行覆蓋率結果也是顯示的並在Java編輯器中有所標記而您可以使用它來得到一個更加明確的指示也就是每一類中涉及到了哪一行在生成覆蓋率數據之後您就可以使用Java編輯器來在項目中打開任意的類了編輯器中左邊的標尺欄顯示了關於覆蓋率的信息顯示了Vehiclejava的結果

  
Java編輯器中顯示的覆蓋率結果

  顏色編輯與在Package Explorer中所顯示的是一樣的也就是默認條件下綠色的行是覆蓋的而紅色的則不是覆蓋的在Java編輯器中查看結果有一個微弱的優勢那就是它還指示了部分覆蓋的行當在源代碼中有不止一個的可執行單元時就會產生部分覆蓋的行但是它們中只有一個可以被執行例如查看圖中setTargetSpeed(int speed)方法中第一行的代碼第一個可執行的單元是if聲明而第二個可執行的單元則是return聲明默認條件下一個部分的行會被標上黃色

  生成報告

  您可以將代碼覆蓋率結果數據匯編到報告之中並在Rational Application Developer中查看它們或者將它們保存到文件系統中以便未來的分析您可以生成兩種不同類型的報告Workbench報告(基於Eclipse)與HTML報告為了生成一份報告您可以選擇Run>Code Coverage>Generate Report顯示了報告生成對話框

  
報告生成對話框

  您可以在Rational Application Developer中使用對話框中的Quick View選項來創建並查看一個報告或者使用Save Report選項將其保存到文件系統中去

  工作台報告

  工作台報告(也叫做基於Eclipse的報告)為項目提供了所有覆蓋率統計數據的穩固視圖並包含了執行時項目中所有類的覆蓋率數據顯示了一個基於Eclipse流傳的報告

  
一個基於Eclipse報告的覆蓋率結果

  工作台報告與Rational Application Developer相集成具有額外的優勢因為您可以使用它們作為一個快速的工具以提供了關於部分代碼的視角這些代碼需要改進的測試覆蓋率數據如圖所示工作台報告中的統計數據包含了所有層次組成的覆蓋率信息從一個包到一種方法右擊任意的Java工件會顯示出一個帶有兩種操作的彈出菜單在Package Explorer中顯示與在Java編輯器中將其打開對於識別和研究帶有低覆蓋率的代碼區域來說它們是非常有用的工具因為通過將它們在適當的浏覽器或者編輯器中打開從而強調了代碼的選擇區域

  HTML報告

  HTML報告顯示了基於Eclipse報告所提供的相同類型的信息但是呈現的格式卻是HTML的這些報告能夠發揮一定程度的作用因為它們為在獨立於Rational Application Developer之外去分析覆蓋率數據提供了一種有效的方法您可以與團隊的其他成員一起分享或者將其發布到一個網站上以方便查看

  在工作台的外部生成統計數據

  Rational Code Coverage工具的一個主要特性是其在Rational Application Developer外部生成統計數據的能力它提供了額外的靈活性並使得您可以定制環境以利用系統中的Rational Code Coverage特性例如一個自然的合並過程就是創建一個構建環境並使用JUnit測試來生成統計數據

  通過執行以下的三個步驟評價執行以及生成報告您可以將Rational Code Coverage特性集成到您的環境之中

  第評價

  您可以使用兩種不同的方法來評價您的程序第一個就是使用<RAD_HOME>/plugins/comibmrationalllcengine_<date>/scripts目錄中提供的instrumentbat/sh腳本本文並沒有關注這個腳本但是您可以參考Rational Application Developer文獻以得到更多的信息如果需要的話第二個方法是使用Rational Code Coverage特性提供的評價Ant任務代碼清單顯示了評價任務配置的范例用法以得到本文中的范例程序

  清單本文范例程序的評價Ant任務的范例用法

  <target name=instrument>

    <taskdef name=instrument

      classname=comibmrationalllcengineinstrumentationanttaskInstrumentationTask

      classpath={path to comibmrationalllcengine plugin}/>

    <instrument saveBackups=true

      baseLineFile=projectbaseline

      buildPath=VehicleProject

      outputDir=VehicleProjectInstr/>

  </target>

  對預期參數的快速預覽已經列在後續的表

  表指南任務的輸入參數

  參數描述

  buildPath對文件系統上項目的路徑

  outputDir(可選的)評價項目的輸出目錄如果沒有指定buildPath中的類將會進行評價

  baseLineFile(可選的)基線項目索引文件的輸出位置查看接下來的段落以得到關於該文件更多的信息

  saveBackups(可選的)如果在評價之前先備份原始的類文件那麼您可以設置為true

  評價的兩種方法都會輸出一個基線文件所謂的基線文件是一個特定於Rational Code Coverage特性的概念基線文件包含了項目中所有類的一個索引並維護了關於每一個類的額外元數據該文件在報告階段(接下來的第步)使用以決定程序中的哪一個類不被覆蓋該步是需要的因為Rational Code Coverage數據收集引擎只是在Java? Virtual Machine(JVM)載入類時才會標記一個類所以沒有執行的類的列表在沒有元數據存在的條件下就不能進行決定了如果基線文件沒有在報告時出現那麼沒有載入的類將不會出現在報告中

  第執行

  為了執行評價好的類您必須在啟動時對Java環境做適當的配置執行過程中所需的兩個特定的參數解釋如下

  ◆Dcoverageoutfile=<absolute path to output file>該JUM論斷指定的文件就是覆蓋率統計數據的輸出位置

  ◆向classpath添加<Rational Application Developer HOME>/plugins/comibmrationalllcengine_<date>/RLCjar因為代碼已經進行了評價並得到了Rational Code Coverage數據搜索引擎的回饋RLCjar文件需要在運行時位於classpath處

  JUnit Ant任務提供了這些參數代碼清單提供了范例用法

  清單怎樣指定Ant啟動中Rational Code Coverage特性論斷的范例

  <target name=run>

   <junit showoutput=true fork=yes>

    <jvmarg value=Dcoverageoutfile={absolute path to the output file}/>

    <classpath>

     <pathelement location={absolute path to the

      <Rational Application Developer HOME>/plugins/comibmrationalllcengine_<date>

          /RLCjar file}/>

     <pathelement location={path to the project classes}/>

     <pathelement path={absolute path to the junitjar} />

    </classpath>

    <test name=comibmvehiclestestsTestCar outfile=TestCar />

   </junit>

  </target>

  第生成報告

  您可以使用Rational Code Coverage特性所提供的另外一項Ant任務來生成報告該項任務使用BIRT 項目所提供的報告功能並因此需要您去下載BIRT V Reporting Engine獨立版該操作可以通過訪問選擇V版本並下載Report Engine版本來完成注意該Ant任務只能產生HTML報告

  清單提供了報告Ant任務的范例用法注意作為輸入它需要在第步中所生成的覆蓋率數據以及在第步中(可選)所生成的基線文件

  清單本文中范例程序報告生成Ant任務的范例

  <target name=generatereport>

   <path id=libpath>

    <pathelement location={absolute path to the

      <Rational Application Developer HOME>/plugins/

          common_<date>jar plugin}/>

    <pathelement location={absolute path to the

      <Rational Application Developer HOME>/plugins/

          comibmrationalllcreport_<date> plugin}/>

    <pathelement location={absolute path to the

      <Rational Application Developer HOME>/plugins/

          orgmon_<date>jar plugin}/>

    <fileset dir={absolute path to the BIRT ReportEngine directory}\lib includes=*jar/>

   </path>

  

   <taskdef name=codecoveragereport

     classname=comibmrationalllcreportbirtadaptersantReportGenerationTask

     classpat/>

  

   <codecoveragereport

     outputDir={absolute path to the report output directory}

     coverageDataFile={absolute path to the coveragedata file generated in step }

     baseLineFiles={absolute path to the baseline file generated in step }/>

  </target>

  在圖中顯示有一個范例HTML報告使用Ant任務生成HTML報告會提供一種方法用戶可以通過這種方法來查看獨立於Rational Application Developer之外Ant環境中生成的統計數據

  
HTML報告中的覆蓋率結果

  Ant環境提供了范例腳本以及構建文件該環境可以用於指導執行並生成關於范例程序的報告如果您對測試該環境感興趣那麼您可以參考一下Standalonezip文件中的README文件

  在WebSphere Application Server上生成統計數據

  使用WebSphere Application Server來生成代碼覆蓋率統計數據在這裡是支持的但是不幸的是這個版本中並不支持來自Rational Application Developer內部的自動化配置但是版本中提供的Rational Code Coverage特性足夠靈活以集成到服務器環境中去包括WebSphere Application Server為了對代碼覆蓋率而配置您的WebSphere Application Server您需要按照以下步驟進行操作

  啟動服務器

  登錄到Administrative Console

  在左邊的窗格中展開Servers

  展開Server Types

  點擊WebSphere程序服務器

  選擇適當的程序服務器

  展開右部窗格選項區域內Server Infrastructure部分中Java and Process Management項

  點擊Process definition

  點擊Additional Properties部分中的Java Virtual Machine

  在 Boot Classpath部分中添加RLCjar文件如上面介紹的那樣jar文件位於Rational Code Coverage數據收集引擎中並位於<Rational Application Developer HOME>/plugins/comibmrationalllcengine_<date>/RLCjar

  在Generic JVM arguments中添加Dcoverageoutfile={output file} JVM論斷如上面所述的那樣該論斷指定了應該將輸出的統計數據保存在什麼地方

  保存服務器配置並重啟服務器

  圖顯示了在作出以上所做的變更之後Administrative Console的屏幕截圖注意在每一個服務器實例的後面必須有一個指南這些服務器實例會執行一個代碼覆蓋率程序

  
WebSphere Application Server對Rational Code Coverage特性的配置

  在服務器對代碼覆蓋率進行配置之後您就可以手動對服務器進行代碼覆蓋率的配置了(從Administration Console上進行)或者使用Rational Application Developer中的集成支持功能注意覆蓋率的結果不會自動導入到Rational Application Developer中以進行分析這樣您需要執行接下來的步驟來將統計數據導回到工作區中

  在Rational Application Developer中的Java視角中右擊Package Explorer並選擇Import

  展開Code Coverage

  選擇Code Coverage Data File並點擊Next

  選擇Data is located on the file system選項並點擊Next

  在Coverage Data file區域中選擇服務器所提供的文件系統上的覆蓋率數據

  在Into folder區域中選擇工作區中的一個目錄以保存導入的文件

  在Associate with Project區域中選擇適當的項目您應該將統計數據與工作區中的項目聯系起來工作區中包含的源代碼用於在服務器上生成統計數據

  點擊Finish

  當覆蓋率數據文件位於工作區中時您可以在UI中顯示統計數據並生成報告您可以右擊覆蓋率文件並選擇Code Coverage > Show code coverage indicators或者Generate Report來完成該操作該功能可以使您更加受益因為它提供了對分析Rational Application Developer中結果所用所有工具的訪問途徑

  Paul Klicnik 是位於安大略省馬克姆的 IBM 多倫多實驗室的一名軟件開發人員他自從 年以來從事代碼覆蓋工作 年從事性能和測試工具領域的工作Paul 從事過多個 IBM 核心產品的工作包括 IBM Rational Performance Tester 和 IBM Rational Application Developer還有 Eclipse 測試和性能工具項目(TPTP)項目


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25668.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.