<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          轉(zhuǎn)轉(zhuǎn)App代碼覆蓋率方案

          共 4272字,需瀏覽 9分鐘

           ·

          2020-10-16 21:49

          作者|張志陽(yáng)

          代碼覆蓋率是業(yè)內(nèi)常用的統(tǒng)計(jì)代碼被執(zhí)行程度的手段。覆蓋率數(shù)據(jù)結(jié)果是對(duì)測(cè)試工作的一種保證,可以贏得信任、增加上線信心。今天就讓我們來(lái)聊聊?轉(zhuǎn)轉(zhuǎn)App代碼覆蓋率方案的實(shí)現(xiàn)及應(yīng)用,希望可以給大家?guī)?lái)一些思路和參考。

          目的

          在轉(zhuǎn)轉(zhuǎn)客戶端團(tuán)隊(duì),搭建代碼覆蓋率方案的主要目的:

          • 通過(guò)代碼被執(zhí)行的比例程度,表現(xiàn)測(cè)試工作的覆蓋程度

          • 通過(guò)未覆蓋內(nèi)容的分析&補(bǔ)充測(cè)試,保證測(cè)試覆蓋程度

          • 通過(guò)分析無(wú)法覆蓋的內(nèi)容,判斷代碼設(shè)計(jì)的合理性

          這里需要補(bǔ)充強(qiáng)調(diào)一點(diǎn):覆蓋率只是一種度量測(cè)試完整性的手段, 是一種測(cè)試有效性的度量,代碼覆蓋率100%也并不代表不會(huì)有其他的問(wèn)題。


          方案選擇

          當(dāng)我們想實(shí)現(xiàn)一套專(zhuān)項(xiàng)測(cè)試方案的時(shí)候,首先都會(huì)想到“在業(yè)內(nèi)有沒(méi)有公開(kāi)的、流行的、可用的方案,可供參考或者 直接可以”拿來(lái)主義”。

          首先,我們可以在搜索引擎、論壇上去進(jìn)行搜索 “App代碼覆蓋率”, 結(jié)果發(fā)現(xiàn)每種語(yǔ)言都有自己的覆蓋率數(shù)據(jù)收集方式。

          比如現(xiàn)在服務(wù)端代碼覆蓋率使用的Jacoco,是一套非常成熟的Java 方案。

          python 、C++、OC 也都有自己體系的覆蓋率收集方案,但并沒(méi)有Jacoco 那么方便集成。更沒(méi)有已經(jīng)將多種語(yǔ)言的覆蓋率統(tǒng)計(jì)集成在一起的方案。


          在調(diào)研&對(duì)比幾種方案后,都會(huì)發(fā)現(xiàn)了一些缺點(diǎn)、功能缺失?和不方便使用的地方,所以開(kāi)始考慮,能否從0實(shí)現(xiàn)一套完全適用自己團(tuán)隊(duì)的代碼覆蓋率方案。


          方案構(gòu)思

          在常見(jiàn)的代碼結(jié)構(gòu)中,“行”是代碼工程的最小單元,所以想要實(shí)現(xiàn)代碼覆蓋率方案來(lái)統(tǒng)計(jì)代碼的被覆蓋程度,首先我們應(yīng)該都會(huì)想到,我們需要統(tǒng)計(jì)所有“代碼行”的覆蓋情況,“行”應(yīng)該是最小的統(tǒng)計(jì)單元。


          在大家日常的測(cè)試工作中,應(yīng)該經(jīng)常會(huì)做?埋點(diǎn)測(cè)試,簡(jiǎn)單的說(shuō),就是通過(guò)埋點(diǎn)代碼記錄某個(gè)頁(yè)面入口/操作/事件?的觸發(fā)?或者結(jié)果的返回,當(dāng)頁(yè)面入口/操作/事件?被觸發(fā)后,記錄&上報(bào),埋點(diǎn)系統(tǒng)統(tǒng)計(jì)計(jì)數(shù),進(jìn)行業(yè)務(wù)層次的數(shù)據(jù)分析。


          這和我們當(dāng)前要實(shí)現(xiàn)的代碼覆蓋率方案需求有些類(lèi)似,我們想要在代碼行被執(zhí)行后,進(jìn)行記錄&上報(bào),覆蓋率系統(tǒng)進(jìn)行統(tǒng)計(jì),進(jìn)行代碼層次的數(shù)據(jù)分析,與埋點(diǎn)對(duì)比,代碼覆蓋程度更廣一些,但是實(shí)現(xiàn)的方式是比較類(lèi)似的,就是在需要關(guān)注的 代碼/事件后增加?用于“記錄”的代碼塊,這種添加代碼的方式,就是常說(shuō)的插樁(* 基本的原則:保證被測(cè)程序原有邏輯的完整性),插入的代碼塊一般稱(chēng)之為探針”。

          所以想要實(shí)現(xiàn)一套代碼覆蓋率方案基礎(chǔ)就是:

          1. 在保證被測(cè)App原有代碼邏輯的完整性的前提下,通過(guò)代碼插樁的方式,在每行源代碼后插入“探針”代碼,記錄對(duì)應(yīng)代碼行已被執(zhí)行

          2. 將記錄的代碼覆蓋數(shù)據(jù)上報(bào)給覆蓋率服務(wù)

          3. 覆蓋率服務(wù) 將數(shù)據(jù)進(jìn)行保存 & 合并計(jì)算

          結(jié)合團(tuán)隊(duì)內(nèi)的實(shí)際方案需求,我們需要先實(shí)現(xiàn)以下部分

          1. 實(shí)現(xiàn)Android、iOS工程的代碼插樁

          2. 探針代碼被執(zhí)行時(shí)?記錄對(duì)應(yīng)代碼的執(zhí)行狀態(tài)

            為了統(tǒng)一Android 、iOS?覆蓋率數(shù)據(jù)的計(jì)算及使用方式,需要統(tǒng)一記錄時(shí)使用的數(shù)據(jù)結(jié)構(gòu)

          3. 代碼執(zhí)行狀態(tài)數(shù)據(jù)上報(bào)、接收、存儲(chǔ)

          4. 數(shù)據(jù)合并計(jì)算、存儲(chǔ)


          實(shí)現(xiàn)

          1、插樁:

          (1)需要解決的難點(diǎn)

          • 難點(diǎn)1:?準(zhǔn)確插樁,保證被測(cè)App原有代碼邏輯的完整性

            在日??吹降拇a中我們發(fā)現(xiàn),不同的語(yǔ)言,會(huì)對(duì)代碼格式/語(yǔ)法都有不同的要求/規(guī)范,每個(gè)人在寫(xiě)代碼時(shí)的習(xí)慣也有所不同

            在不對(duì)代碼內(nèi)容進(jìn)行語(yǔ)義分析就進(jìn)行隨意插樁,可能會(huì)導(dǎo)致編譯失敗/ 影響原有代碼邏輯

            語(yǔ)義分析需要對(duì) 代碼格式/語(yǔ)法 有足夠的掌握程度?&?大量的嘗試保證語(yǔ)義分析的足夠全面

          • 難點(diǎn)2:?所有代碼行都進(jìn)行插樁,會(huì)不會(huì)影響客戶端性能

            答案是必然的,當(dāng)前客戶端的代碼量,至少已經(jīng)是百萬(wàn)級(jí)別了

            如果在每行代碼前后插入探針代碼、在App實(shí)際運(yùn)行過(guò)程中、頻繁的IO運(yùn)算工作,App的 穩(wěn)定性、性能都不敢保證

          (2)解題方案

          • 準(zhǔn)確插樁,保證被測(cè)App原有代碼邏輯的完整性

            由客戶端RD同學(xué)負(fù)責(zé)插樁方案的具體實(shí)現(xiàn),即高效又可靠

            Android: 使用?ASM?對(duì)字節(jié)碼進(jìn)行分析?,再進(jìn)行準(zhǔn)確插樁

            iOS: 通過(guò)語(yǔ)義分析,判斷插樁位置,再進(jìn)行準(zhǔn)確插樁

          • 所有代碼行都進(jìn)行插樁,會(huì)不會(huì)影響客戶端性能

            初期方案,我們選擇先對(duì)邏輯分支進(jìn)行插樁,大量減少插樁量

            優(yōu)點(diǎn):控制了插樁數(shù)量,減少了對(duì)工程性能的影響

            弱點(diǎn):只能采集到進(jìn)入分支,不能判斷分支結(jié)束;不能按行統(tǒng)計(jì)計(jì)算, 不能結(jié)合Code Diff 直接判斷?新增/修改代碼的覆蓋情況

          (3)插樁前后代碼對(duì)比

          Android

          iOS

          (4)探針代碼解讀

          標(biāo)記邏輯分支被執(zhí)行(邏輯分支全局編號(hào))

          • 全局編號(hào)從哪來(lái)?

            在遍歷所有類(lèi)文件時(shí),對(duì)識(shí)別出的邏輯分支進(jìn)行編號(hào)

          • ?插入位置怎么獲得

            Android:字節(jié)碼中有行號(hào)的描述,通過(guò)ASM解析可以獲取

            iOS:代碼遍歷,判斷出邏輯分支時(shí),就已經(jīng)知道當(dāng)前行行號(hào)

          (5)插樁流程

          • 獲取方法路徑和方法簽名(用于多個(gè)tag之間邏輯塊執(zhí)行數(shù)據(jù)的比較和合并)

            方法路徑:類(lèi)名+方法名可以確定當(dāng)前工程中一個(gè)唯一的方法:

            com.wuba.zhuanzhuan.activity.AboutZhuanzhuanActivityonCreate(Landroid/os/Bundle;)

            法簽名:對(duì)方法內(nèi)的所有字節(jié)碼做MD5編碼,如果方法邏輯有修改(增減),那么簽名就會(huì)變化

            Tag間對(duì)比:如果相同方法路徑的簽名有變化,則認(rèn)為該方法內(nèi)的所有邏輯分支都需要重新覆蓋測(cè)試

          • 找到邏輯塊

          • 獲取邏輯塊行號(hào)

          • 邏輯塊編號(hào)

          • 將方法路徑、方法簽名、邏輯塊信息存入methodMapping文件

          • 插樁結(jié)束后,將methodMapping文件上傳到服務(wù)器

          2、記錄代碼被執(zhí)行:

          (1)數(shù)據(jù)存儲(chǔ)為了不影響原始代碼的執(zhí)行效率,探針代碼執(zhí)行記錄數(shù)據(jù)的讀寫(xiě)效率必須得到保證,所以我們的選擇是:

          • Android:使用字節(jié)數(shù)組(Bitset) 存儲(chǔ) 探針代碼執(zhí)行記錄數(shù)據(jù)

          • iOS : 在內(nèi)存中申請(qǐng)指定長(zhǎng)度的數(shù)組空間 存儲(chǔ) 探針代碼執(zhí)行記錄

          • 數(shù)組長(zhǎng)度?

            邏輯塊編號(hào)完成后,可以知道邏輯塊總數(shù),一個(gè)字節(jié)可以存儲(chǔ)8個(gè)邏輯塊編號(hào),即可計(jì)算出需要的數(shù)組長(zhǎng)度

          • 大約會(huì)占多少空間?

            EXP: 20W 邏輯塊 = 2W5 (20W / 8) 字節(jié) = 24.4KB (2W5 / 1024)

          (2)探針代碼被執(zhí)行:

          • 探針代碼中,入?yún)⒕褪?邏輯塊 在所有邏輯塊的中編號(hào)

          • 將數(shù)組中編號(hào)對(duì)應(yīng)的位 置為 1 , 代表已覆蓋

          3、數(shù)據(jù)上報(bào)、接收、存儲(chǔ):

          (1)什么時(shí)候上報(bào)數(shù)據(jù)

          如果頻繁上報(bào),可能會(huì)影響App的正常使用,也并沒(méi)有必要。所以考慮在一些 察覺(jué)不到/不太Care的 操作節(jié)點(diǎn)進(jìn)行數(shù)據(jù)上報(bào)。

          • Android:頁(yè)面的創(chuàng)建、不可見(jiàn)、銷(xiāo)毀 時(shí) 上報(bào)

          • iOS:App 啟動(dòng)、退后臺(tái)、喚醒 時(shí)上報(bào)

          (2)上報(bào)哪些內(nèi)容

          • project: 與 代碼覆蓋率服務(wù)約定的唯一 覆蓋率項(xiàng)目名,區(qū)分終端,如zhuanzhuanAndroid / zhuanzhuanIos

          • version: 版本號(hào)

          • uniqueId: methodMapping 文件上傳時(shí)時(shí)間戳,文件的唯一標(biāo)識(shí)

          • record: 數(shù)組數(shù)據(jù)

          (3)數(shù)據(jù)存儲(chǔ)

          服務(wù)端接收數(shù)據(jù)后,根據(jù)project、version、uniqueId,查詢出記錄的 record數(shù)據(jù),與上報(bào)的record 數(shù)據(jù) 做按位或計(jì)算,即 只要有1出現(xiàn),該位即為1,已覆蓋,再將結(jié)果存儲(chǔ)起來(lái)

          所以覆蓋率數(shù)據(jù)都是按 uniqueId 進(jìn)行區(qū)分存儲(chǔ)的,即每個(gè)安裝包的覆蓋率數(shù)據(jù)都單獨(dú)存儲(chǔ)。

          4、數(shù)據(jù)合并計(jì)算:

          (1)兩個(gè)安裝包的覆蓋率數(shù)據(jù)如何合并

          數(shù)據(jù)庫(kù)中存儲(chǔ)的覆蓋率數(shù)據(jù)是每個(gè)安裝包的數(shù)據(jù)以及基礎(chǔ)信息,當(dāng)兩個(gè)安裝包并不是同一個(gè)Tag,有代碼差異的時(shí)候,是不能直接進(jìn)行按位或計(jì)算合并數(shù)據(jù)的。

          這時(shí) methodMapping文件就起到了作用。查找到兩個(gè)安裝包對(duì)應(yīng)的methodMapping文件,對(duì)其中的內(nèi)容進(jìn)行解析,就可以分別獲得兩個(gè)安裝包中的所有類(lèi)名、方法名、方法簽名等信息. 通過(guò)循環(huán)對(duì)比,即可進(jìn)行數(shù)據(jù)合并:

          為了區(qū)分兩個(gè)不同Tag的安裝包,方便后續(xù)描述的理解,這里將Tag創(chuàng)建時(shí)間較早的安裝包稱(chēng)之為Old, 將Tag創(chuàng)建時(shí)間較晚的安裝包稱(chēng)之為New.

          • 遍歷New 的Mapping數(shù)據(jù)

          • 如果Old 的Mapping數(shù)據(jù)中?有相同的方法簽名,則方法內(nèi)部的所有邏輯分支進(jìn)行被執(zhí)行狀態(tài)的合并計(jì)算

          • 如果Old 的Mapping數(shù)據(jù)中沒(méi)有相同的方法簽名,則認(rèn)為該方法為新增/修改過(guò)的方法,被執(zhí)行狀態(tài)以?New?的覆蓋率數(shù)據(jù)為準(zhǔn)

          最終會(huì)得到以New 的代碼為準(zhǔn)的覆蓋率數(shù)據(jù),即相對(duì)較新代碼的整體覆蓋率數(shù)據(jù)

          (2)要合并哪些安裝包

          我們存儲(chǔ)了那么多安裝包的覆蓋率數(shù)據(jù),那么在實(shí)際的客戶端迭代流程中,我們應(yīng)該合并哪些安裝包的數(shù)據(jù),才可以幫助我們進(jìn)行分析,實(shí)現(xiàn)我們的方案目的呢?

          我們對(duì)?單次打包緯度、單Tag緯度、版本緯度、分支緯度?幾種統(tǒng)計(jì)緯度進(jìn)行了利弊分析&對(duì)比,最后我們選擇使用分支緯度進(jìn)行覆蓋率數(shù)據(jù)的匯總統(tǒng)計(jì),即根據(jù)Tag的前后節(jié)點(diǎn)關(guān)系,合并同一分支線上的所有Tag(以前一版本的發(fā)版Tag為起點(diǎn),以當(dāng)前分支線中最新的Tag為終點(diǎn))的所有安裝包的覆蓋率數(shù)據(jù)。

          ?(3)多個(gè)安裝包的數(shù)據(jù)集如何快速合并

          為了保證合并計(jì)算效率,采用多線程來(lái)處理。

          • 以前一版本的發(fā)版Tag為起點(diǎn),以當(dāng)前分支線中最新的Tag為終點(diǎn),根據(jù)記錄的Tag前后節(jié)點(diǎn)關(guān)系,查詢出分支線中的Tag列表,再查詢出對(duì)應(yīng)的所有安裝包覆蓋率數(shù)據(jù)集

          • 多線程分別合并數(shù)據(jù)集


          流程

          1、簡(jiǎn)化流程

          2、打包流程

          3、測(cè)試過(guò)程中上報(bào)流程


          4、自動(dòng)計(jì)算流程

          平臺(tái)功能

          1、查看指定版本、分支的增量代碼覆蓋率數(shù)據(jù)?& 依賴(lài)組件工程的增量代碼覆蓋率數(shù)據(jù)

          2、查看組件工程中詳細(xì)的類(lèi)增量覆蓋率數(shù)據(jù)

          ?3、查看類(lèi)增量代碼中邏輯分支的詳細(xì)覆蓋狀態(tài)?& 實(shí)時(shí)計(jì)算、渲染

          4、選擇Tag區(qū)間,臨時(shí)計(jì)算增量覆蓋率數(shù)據(jù)

          5、選擇同版本兩個(gè)Tag ,對(duì)比計(jì)算增量覆蓋率數(shù)據(jù)


          后續(xù)規(guī)劃

          分支統(tǒng)計(jì)緯度的優(yōu)缺點(diǎn)前面已經(jīng)提到過(guò),接下來(lái)我們會(huì)增加行覆蓋和方法覆蓋統(tǒng)計(jì)緯度,并且會(huì)結(jié)合Git diff,計(jì)算/渲染 Diff 代碼的覆蓋率數(shù)據(jù)。

          現(xiàn)在iOS的插樁方案有些簡(jiǎn)單粗暴,效率也并不高,所以已經(jīng)開(kāi)始著手重構(gòu)。

          我們也計(jì)劃在平臺(tái)上增加更多的人性化的功能,提升覆蓋率數(shù)據(jù)的分析效率、提升整體的使用體驗(yàn)。


          好了,轉(zhuǎn)轉(zhuǎn)App代碼覆蓋率方案?就先給大家介紹的這里,希望能對(duì)大家有所幫助。

          如果喜歡我們分享的內(nèi)容,歡迎點(diǎn)贊、在看、分享~






          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  婷婷亚洲五月色综合 | 国产精品三级在线观看 | 淫色AV网| 亚洲成人免费 | 欧美性受XXX黑人XYX |