測試人員遇到Android APP崩潰和無響應手足無措?,基於Python的Appium環境搭建合集

這2天,在測APP兼容性時,遇到APP奔潰閃退的情況。將問題反饋給開發后,開發自己調試后,沒有復現。由於又是遠程,base地不在一塊,我總不能把手機寄過去吧,那也太費事了。

所以就想到,提供明確的報錯日誌,讓開發定位問題,豈不是就很方便了,也解決了遠程的問題。

那如何抓取到Crash日誌呢,我又沒開發調試工具,也不可能在短時間內搭建一套開發環境。尋思答案后,最終得到了完美解決,且聽細細道來。

了解Crash

我們先來簡單了解下Crash:Crash,就是崩潰。anr(Application Not Responding — 程序無響應)是Crash的一種。程序正常運行中,可能會出現未捕獲到的異常,這就會造成崩潰。

常見Crash異常

NullPointerException  空指針

ClassCastException  類型轉換異常

IndexOutOfBoundsException  下標越界異常

ActivityNotFoundException Activity  未找到異常

IllegalStateException  非法狀態異常

ArrayIndexOutOfBoundsException  數組越界異常

SecurityException  安全異常

NoSuchMethodException  方法未找到異常

SQLException  操作數據庫異常

抓取奔潰和無響應日誌

對於開發人員來說,抓取日誌是很方便的,但對於測試人員來說,就不是太方便了。大多都是直接dos窗口下執行adb命令來抓取日誌,而每次都敲命令也是很麻煩。

所以通過adb程序與bat命令組合使用來抓取日誌,就要方便很多了,短短几秒鐘,可以輕鬆搞定日誌的抓取,期不期待。

環境準備

安裝JDK和ADB,這個安裝很簡單,可參見以前的博文,基於Python的Appium環境搭建合集。

bat文件製作

環境準備好后,就來寫bat文件了。

捕獲Crash異常的bat文件命令

命令參考如下,製作成logcat.bat文件,logcat.bat文件可以放置任意位置。注意:如果adb沒有配置到環境變量中,則需要將logcat.bat文件放到adb對應文件夾中。

@ECHO OFF
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"

SET timeStamp=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%_%dt:~8,2%-%dt:~10,2%-%dt:~12,2%
SET mutID=_mut

@ECHO ON
adb logcat -v time > .\"%mutID%_%timeStamp%_logcat.log"

pause

上述命令實現原理:該工具的原理是bat文件調用adb工具,將手機運行日誌拉到本地,並將實時日誌也記錄到本地。

當手機需要重現Crash、或者某一段時間內已經發生過Crash,點擊我們製作的bat文件,logcat文件中的命令會將手機的logcat日誌拉下來並實時記錄,直到你關閉cmd窗口。

然後在拉下來的txt中尋找FATAL關鍵字,附近上下文即為Crash日誌。

捕獲ANR異常的bat文件命令

anr:全稱為Application Not Responding,意思為程序無響應。

命令參考如下,製作成anr.bat文件,anr.bat文件可以放置任意位置。注意:如果adb沒有配置到環境變量中,則需要將anr.bat文件放到adb對應文件夾中。

@ECHO OFF
for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
SET timeStamp=%dt:~0,4%-%dt:~4,2%-%dt:~6,2%_%dt:~8,2%-%dt:~10,2%-%dt:~12,2%
SET mutID=_mut
@ECHO ON
adb pull data/anr/traces.txt traces_%timeStamp%.txt

實現原理與捕獲Crash異常是一樣的,只是該命令是針對發生anr的情況。

具體實踐

捕獲Crash異常具體用法:

①將android手機連接電腦,開啟開發者模式並允許usb調試;

②運行logcat.bat文件

③如果手機程序已經發生過crash,10秒后關閉cmd窗口;如果是想重現crash,則在手機端重現后即可關閉cmd窗口;

④在logcat.bat的同級目錄下會生成一份log文件,從文件中搜查FATAL關鍵字,便可找到崩潰代碼。

查看報錯日誌,報錯如下所示:

如上所示截圖,就是測試過程中,發生奔潰的日誌了,將日誌貼在bug里,既方便開發排查問題,又節約協作時間。

使用優點

使用bat文件捕獲日誌,有如下幾個有點:手機無需root;無需開發環境支持;方便保存、查找日誌;操作簡單。

以上就是捕獲報錯日誌的操作步驟了,希望對有需要的博友有所幫助。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

聚甘新

JVM源碼分析之Object.wait/notify(All)完全解讀

概述

本文其實一直都想寫,因為各種原因一直拖着沒寫,直到開公眾號的第一天,有朋友再次問到這個問題,這次讓我靜心下來準備寫下這篇文章,本文有些東西是我自己的理解,比如為什麼JDK一開始要這麼設計,初衷是什麼,沒怎麼去找相關資料,所以只能談談自己的理解,所以大家看到文章之後可以談談自己的看法,對於實現部分我倒覺得說清楚問題不大,code is here,看明白了就知道怎麼回事了。

Object.wait/notify(All)大家都知道主要是協同線程處理的,大家用得也很多,大概邏輯和下面的用法差不多

看到上面代碼,你會有什麼疑惑嗎?至少我會有幾個問題會問自己: * 為什麼進入wait和notify的時候要加synchronized鎖 * 既然加了synchronized鎖,那當某個線程調用了wait的時候明明還在synchronized塊里,其他線程怎麼進入到鎖里去執行notify的 * 為什麼wait方法可能會拋出InterruptedException異常 * 如果有多個線程都進入wait狀態,那某個線程調用notify喚醒線程時是否按照順序喚起那些wait線程 * wait的線程是在某個線程執行完notify之後立馬就被喚起嗎 * notifyAll又是怎麼實現全喚起的 * wait的線程是否會影響load

如果上面這些問題也都是你想了解的,那這篇文章或許能給你一個答案。

為何要加synchronized鎖

從實現上來說,這個鎖至關重要,正因為這把鎖,才能讓整個wait/notify玩轉起來,當然我覺得其實通過其他的方式也可以實現類似的機制,不過hotspot至少是完全依賴這把鎖來實現wait/notify的。

如果要我們來實現這種機制我們會怎麼去做,我們知道wait/notify是為了線程間協作而設計的,當我們執行wait的時候讓線程掛起,當執行notify的時候喚醒其中一個掛起的線程,那需要有個地方來保存對象和線程之間的映射關係(可以想象一個map,key是對象,value是一個線程列表),當調用這個對象的wait方法時,將當前線程放到這個線程列表裡,當調用這個對象的notify方法時從這個線程列表裡取出一個來讓其繼續執行,這樣看來是可行的,也比較簡單,那現在的問題這種映射關係放到哪裡。而synchronized正好也是為線程間協作而設計的,上面碰到的問題它也要解決,或許正因為這樣wait和notify的實現就直接依賴synchronzied(monitorenter/monitorexit是jvm規範里要求要去實現的)來實現了,這隻是我的理解,可能初衷不是這個原因,這其實也是這篇文章遲遲未寫的一個原因吧,因為我無法取證自己的理解是對的,歡迎各位在這塊談談自己的見解。

wait方法執行后未退出同步塊,其他線程如何進入同步塊

這個問題其實要回答很簡單,因為在wait處理過程中會臨時釋放同步鎖,不過需要注意的是當某個線程調用notify喚起了這個線程的時候,在wait方法退出之前會重新獲取這把鎖,只有獲取了這把鎖才會繼續執行,想象一下,我們知道wait的方法是被monitorenter和monitorexit包圍起來,當我們在執行wait方法過程中如果釋放了鎖,出來的時候又不拿鎖,那在執行到monitorexit指令的時候會發生什麼?當然這可以做兼容,不過這實現起來還是很奇怪的。

為什麼wait方法可能拋出InterruptedException異常

這個異常大家應該都知道,當我們調用了某個線程的interrupt方法時,對應的線程會拋出這個異常,wait方法也不希望破壞這種規則,因此就算當前線程因為wait一直在阻塞,當某個線程希望它起來繼續執行的時候,它還是得從阻塞態恢復過來,因此wait方法被喚醒起來的時候會去檢測這個狀態,當有線程interrupt了它的時候,它就會拋出這個異常從阻塞狀態恢復過來。

這裡有兩點要注意: * 如果被interrupt的線程只是創建了,並沒有start,那等他start之後進入wait態之後也是不能會恢復的 * 如果被interrupt的線程已經start了,在進入wait之前,如果有線程調用了其interrupt方法,那這個wait等於什麼都沒做,會直接跳出來,不會阻塞

被notify(All)的線程有規律嗎

這裏要分情況: * 如果是通過notify來喚起的線程,那先進入wait的線程會先被喚起來 * 如果是通過nootifyAll喚起的線程,默認情況是最後進入的會先被喚起來,即LIFO的策略

notify執行之後立馬喚醒線程嗎

其實這個大家可以驗證一下,在notify之後寫一些邏輯,看這些邏輯是在其他線程被喚起之前還是之後執行,這個是個細節問題,可能大家並沒有關注到這個,其實hotspot里真正的實現是退出同步塊的時候才會去真正喚醒對應的線程,不過這個也是個默認策略,也可以改的,在notify之後立馬喚醒相關線程。

notifyAll是怎麼實現全喚起的

或許大家立馬想到這個簡單,一個for循環就搞定了,不過在jvm里沒實現這麼簡單,而是藉助了monitorexit,上面我提到了當某個線程從wait狀態恢復出來的時候,要先獲取鎖,然後再退出同步塊,所以notifyAll的實現是調用notify的線程在退出其同步塊的時候喚醒起最後一個進入wait狀態的線程,然後這個線程退出同步塊的時候繼續喚醒其倒數第二個進入wait狀態的線程,依次類推,同樣這這是一個策略的問題,jvm里提供了挨個直接喚醒線程的參數,不過都很罕見就不提了。

wait的線程是否會影響load

這個或許是大家比較關心的話題,因為關乎系統性能問題,wait/nofity是通過jvm里的park/unpark機制來實現的,在linux下這種機制又是通過pthread_cond_wait/pthread_cond_signal來玩的,因此當線程進入到wait狀態的時候其實是會放棄cpu的,也就是說這類線程是不會佔用cpu資源。

 

一起來學習吧:

PerfMa KO 系列課之 JVM 參數【Memory篇】

Hotspot GC研發工程師也許漏掉了一塊邏輯

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

FB行銷專家,教你從零開始的技巧

聚甘新