第七章程序員
1. 健壯性和正確性編程
(1)健壯性:處理各種狀況的能力數組
(2)正確性:正確實現規格說明的能力數據結構
(3)測量:平均故障間隔時間(MTBF)、殘餘缺陷率(軟件發佈後留下的bug)框架
2. Throwable:有兩個子類,即error和exception函數
(1)error:程序沒法處理的錯誤,一般是JVM的問題,不須要catch工具
·處理策略:預先阻止、錯誤中恢復、優雅地退出學習
·處理方式測試
- 返回中立值優化
- 替換下一個有效數據
- 返回與前一次相同的答案
- 代替最接近的法律價值
- 將警告消息記錄到文件
- 返回錯誤代碼:設置狀態值 -> 返回狀態值 -> 利用異常機制
- 調用一個錯誤處理例程/對象
- 顯示錯誤信息
- 在本地處理錯誤
- 關掉程序
(2)exception:程序自身能夠處理,代碼能夠經過異常機制將錯誤或異常事件傳遞給調用它的代碼,Java沒法以正常方式完成其任務時容許每種方法都有一個替代退出路徑
3. Runtime 異常、其餘異常
(1)Runtime異常:程序員本身的錯誤,如空指針、數組越界、類型轉換等
(2)其餘異常:一般爲IOE異常,即找不到文件路徑等
4. Checked 異常、Unchecked 異常
(1)Checked 異常:每一個調用者都應知道並處理的錯誤
·處理機制
- 拋出:聲明是throws,拋出時throw
- 捕獲(try/catch):try出現異常,忽略後面代碼直接進入catch;無異常不進入catch;若catch中沒有匹配的異常處理,程序退出;若子類重寫了父類方法,父類方法沒有拋出異常,子類應本身處理所有異常而再也不傳播;子類從父類繼承的方法不能增長或更改異常
- 處理:不能代替簡單的測試,儘可能苛刻、不過度細化、將正常處理與異常處理分開、利用好層次結構、早拋出晚捕獲、避免沒必要要的檢查
- 清理現場、釋放資源(finally):finally中語句不論有無異常都執行
(2)Unchecked 異常:JVM拋出,如空指針、數組越界、數據格式、不合法的參數、不合法的狀態、找不到類等
5. 自定義異常類:繼承自Exception,在構造函數中可經過super(key)修改默認值
6. 斷言
(1)做用:容許程序在運行時檢查本身,測試有關程序邏輯的假設,如前置條件、後置條件、不變量等,可將黑盒測試轉換爲白盒測試
(2)應用場合
·輸入/輸出參數落在預期範圍內
·程序運行/結束時文件流的打開和關閉
·程序開始(結束)時文件處於開始(結束)
·文件流以只讀、只寫或讀寫方式打開
·輸入變量的值不被方法改變
·判斷指針不是空值
·判斷數據結構是不是指定長度
·判斷真值表是否初始化
·當一個方法開始執行時(或完成時)容器是空的(或滿的)
·高度優化的複雜方法的結果與較慢但清晰編寫的例程的結果相匹配
(3)注意
·編譯時加入-ea選項運行斷言,-da關閉斷言
·條件語句或開關沒有涵蓋全部可能的狀況,最好使用斷言來阻止非法事件
·能夠在預計正常狀況下程序不會到達的地方放置斷言:assert false
·在開發和調試階段設置斷言,在軟件發佈時禁止斷言
·斷言有代價,需慎用,通常用於驗證正確性,處理毫不應該發生的狀況
·不能做爲公共方法的檢查,也不能有邊界效應
7. 調試(Debugging)
(1)進攻式編程:在開發階段讓異常顯現出來,而在產品運行時讓其自我恢復
·產品版與開發版:開發版只要開發順利能夠放肆一些,產品版必須剋制
·作好計劃,避免調試代碼和程序代碼糾纏不清
·使用存根例程
·開發中但願錯誤儘量明顯,發佈後但願錯誤儘量不明顯
·肯定程序的哪些部分可以承受未檢測出錯誤而形成的後果,哪些不能,若是後果微不足道,可經過make或版本控制刪除檢測代碼(不是物理刪除)
·若是您的程序包含檢測潛在致命錯誤的調試代碼,可將代碼保留在其中,以使程序穩妥地崩潰
·考慮在產品代碼中留下調試代碼,但改變他們的行爲,以便適合生產版本
(2)Bug的狀態
·被發現提出(New)-> 被審覈批准(Open)-> 被分配給開發者(Assign)-> 被解決/修正/測試(Resolved/Fixed/Test)-> 從新測試(Retest)-> 經過測試(Verified)-> 修復後仍存在問題(Reopen)-> 成功修復(close)
·若bug優先級低,推遲到下一個版本,有時可能須要無限推遲
·若是開發人員認爲系統的特定行爲(測試人員報告爲錯誤的行爲)必須相同,而且錯誤無效,那麼該錯誤將被拒絕並標記爲「等待拒絕」
·若是bug沒法經過QA的報告中給出的步驟重現,則開發人員能夠將該錯誤標記爲「CNR」, QA須要採起措施來檢查是否重現了bug,而且能夠向開發人員分配詳細的重現步驟
(3)基本過程:重現問題 -> 找到緣由(95%) -> 進行修正 -> 反思
(4)方法
·重現問題
- 找到一個產生失敗的小的可重複測試用例(保持復現bug的前提降低低輸入規模)
- 消除因版本、環境、配置等不一樣引發的差別(經過構建軟件實現),肯定bug出現的環境(經過程序模擬硬件平臺的細節,實現不一樣的操做系統環境)
- 利用逆向設計推斷致使錯誤的輸入
- 若沒法重現,則沒法觀察以證實分析和修補的正確性
·診斷錯誤(插樁、分治、VCS、尋找特例、學習他人)
- 從假設開始,構造實驗,證實它是對的或者錯的
- 從不符合理論的觀察結果開始,修正理論
- 查看致使錯誤的測試輸入,以及錯誤的結果,失敗的斷言以及由此致使的堆棧跟蹤
- 提出一個與全部數據一致的假設,說明錯誤發生的位置或錯誤發生的位置,設計實驗測試假設
- 收集實驗數據,減小錯誤可能出現的範圍,作出新的假設
- 設計不一樣的實驗:檢查內部狀態、修改運行方式、改變自己邏輯
- 每次只作一個修改、作好記錄、不忽略細節、運行不一樣的測試用例、設置斷點、用可實現相同功能而且被證明無問題的組件替代當前組件
·修復bug
- 確保從乾淨的源代碼樹開始
- 運行現有的測試,並證實它們經過
- 添加一個或多個新測試,或修復現有測試,以演示錯誤
- 修復錯誤、發現可改進之處
- 證實你的修復工做正常且沒有引入迴歸(之前經過的測試如今失敗)
- 若是引入迴歸,經過回顧之前的版原本找出確切的變化
(4)調試工具
·語法和邏輯檢查
·源代碼比較器
·內存堆轉儲
·打印調試/記錄
·堆棧跟蹤
·編譯器警告消息
·調試器
·執行分析器
·測試框架
8. 黑盒測試用例的設計
(1)黑盒測試:在沒有任何內部實現知識的狀況下檢查功能,而無需查看源代碼
(2)測試用例:圍繞規範和要求構建,通常來自軟件的外部描述,包括規範,要求和設計參數,主要是功能性的
(3)等價類劃分:將程序的輸入域劃分爲可導出測試用例的數據類
·若一組對象自反、對稱、傳遞,則爲等價類
·可產生類似結果的輸入集合中的一個可代替整個集合
·同理,對輸出也能夠劃分等價類
·兩個極端:每一個分區只有一個測試用例,覆蓋全部分區
(4)邊界值分析:錯誤一般隱藏在邊界中,如一位偏移、邊界值需單獨處理等
9. 以註釋的形式撰寫測試策略
(1)在測試類的頂端寫策略
(2)在每一個測試方法前說明測試用例是如何選擇的
10. JUnit 測試用例寫法
(1)@Before:每一個測試方法前執行一次
(2)@After:每一個測試方法後執行一次
(3)@Test:代表測試方法,內含Assert語句
·@Test(expected=*.class):對錯誤的測試,expected的屬性值是一個異常
·@Test(timeout=xxx):測試方法在制定的時間以內沒有運行完則失敗
(4)@ignore:忽略測試方法
11. 測試覆蓋度
(1)一般沒法徹底覆蓋,所以只需儘可能提升
(2)代碼覆蓋率高的程序在測試期間執行了更多的源代碼,與低代碼覆蓋率的程序相比,包含未檢測到的軟件錯誤的可能性較低
(3)基本覆蓋標準:函數、語句、決策或分支、條件或謂詞、路徑
(4)覆蓋強度:路徑 > 分支 > 語句