# 軟體工程 Week 4
###### tags: `軟體工程`
# 測試
## ACM 調查
* 校園很少介意
## QA & QC
### Good quality product requirement (將軟體視為一項產品)
* Quality control 品質控制
* Quality assurance 品質確保
* Testing 軟體測試(品質確保中的一環)
* 把Bug抓出來的一手段
### 製造業案例
* 希望生產與可販售的數量相符
* Process Improment(工業工程領域):製造流程改,提高良率
* 最好提升品質方式,使用機器
* 但機器有磨損問題
* 生產線:
* 讓每個人做簡單工作,使他們【不易出錯】
* 不需要太過聰明
* 切割小步驟,每個步驟能在最短時間完成
* 使其發現產品問題不困難
### 能如法炮製嗎?
* 並不能
* 軟體發展是設計的工作
### Programmer VS Assembly line worker (生產線作業員)
* Programmer
* requires perfection
### The Big GAP

* Demo-Oriented reasearch
* Don't Touch
* research prototypes
* Major Features are usable (主要功能)
* prove of concpts (概念證明)
* not responsible for bugs (不負責任)
* user friendly not guaranteed (不保證)
* crappy UI (糟糕的UI)
* Product
* all features
* bugs are not allowed
* usable
* user friendly
* the generic data format
* performance is tuned.
* UI is well designed and pleasant
### Other engineer VS software engineer
* Other engineer
* Idea
* Marketing(Requirement) Analysis
* Analysis and Design (分析與設計)
* Manufacturing (QC) (製造)
* Testing (QA)(測試)
* Release product (產品出廠)
* software engineer
* Idea (概念)
* Requirement analysis and specification (100% design) (需求分析與規格)
* Design and analysis (分析與設計)(100% design, QC here?)
* Implementation (程式實做)(95% design?, QC here?)
* Manufacturing (製造)(compilation – no cost manufacturing)
* Testing(測試)
## Tradiction
1. Marketing
2. Develop
3. QAs(Testing)
* QAs 必須與Programmer 站在對立面
* 管帳的不管錢,管錢的不管帳
* 法官判案,承認判案是錯的
## Software Testing V model

* 瀑布模型 開發模式
### Testing
1. 模組設計(小塊) => Unit Test
* Programmer
3. 設計與分析 => Integration Test
* Programmer / QA 負責
4. 規格 => System Testing
* 系統已經完成
5. 需求 => User Acceptance testing (UAT): 驗收測試
6. Regression testing(回歸測試)
7. Alpha testing: 整合測試完成後,程式功能皆已大致完畢且完成測試(程式一Run就當掉都修的差不多嘞)
* Most software function & feature are basiclly completed: 程式碼已經完成
* freezing : 新功能不再添加功能。All function are tested, no function will be added beyond this point
* Serious flaws(high severity) are sloved and addressed(show stopper)
8. Beta Testing
* Sub-serious bug all fixed: 嚴重Bug 皆以解決
* Text plan has been completely excuted: QAs 已經完成 Testing Report
* Bug discovering rate is lower than fixing rate,發現頻率低於修復頻率
## SDLC(Software Development Life Cycle)

* Release
* Bug discovering rate is lower than fixing rate for 【long period of time】
* The version after fixing bugs has been regressively tested (regression test): 版本修復後,且經過回歸測試
* Quality is formally proved by QA team: QAs正式證明質量
* All documents are ready: 文件皆已經齊全
## Testing tasks to be done
* Write Test plan
* often seen in large software company with formal QA team
* write test cases, prepare test data
* test case management
* file bugs
* Bug 回報系統(文件)
* regression testing
* test automation (with tools): 測試自動化
* QA team 來做
* stress testing/load testing
* security testing
* test as assets.
### How to plan
* (要或不)測什麼
* 測試代價有多高
* 前後順序
### 很重要的一句話
#### No test case No quality
# Test Case
* Test ID
* Revision History
* Summary
* Tested Story
* Creator
* Test Step
* 
## Test ID
* 可包含之元素
* Test Suite name
* Computer or Requirement abbreviation(縮寫)
* ID 值可使用有意義之值
* A: automatically Excuted : 測試自動化
* M: Manually Excuted : 需透過人工
* P: Positive case
* N: Negative case : 故意操作超出範圍之值
* B: Boundary case : 故意測試邊界值,如:<0,會測試0與1
* 0: cast priority
* 1....9
## Bug Report System
* 紀錄Bug
* 確認測試足夠的
* 能夠與未來的人溝通
* 若有人來詢問Bug代表敘述不清楚
* Attach any files
* input file
* output file
* dump
* 也可利用 OBS: 影片錄影
### Severity of Software Defect
* Severity 1(Show Stop): 非常嚴重,一跑就當掉嘞
* Severity 2: 不會當掉,但會無法繼續操作
* Microsoft 1-30
# Devops
## Regression Testing
*  => 
* 敏捷開發 => 回歸測試自動化
## Buttom up But Fow
### AFILE
* 不斷 Release
* 先顯示可以動的部分,不等成品完成
* Quality 要由底部向上完成
### Module Test
* 雖然不是整段程式,屬於片段程式,但還是能夠進行測試
#### Test Bench
* Module under test
* Component under test
* Program under test
* dependecy
* 需要透過其他的人合作的程式組件才能執行
* 需建置一個API Server才能夠處理
* Test Driver
* 
* Test Runner
* Dummy r(): 假的 = fack
* 使用造假輸入,並回傳
* 設定中斷點
* 使用假的 Server
### Testing in isolation

## Parafigm Shift
* 徒然讓Proggramer 加入 Testing文化
* Tools: Coverage
### Google
* 讓Proggramer 工作增加但薪水也增加
* 讓Proggramer 每天習慣與實踐
### Unit Test Benefits
* Unit Test = Black Box + While Box
* 有Source Code
* Unit Test 1 : Unit testing provides documentation (測試及文件)
* basic picture
* carry information
* appropriate
* inappropriate
* Unit Test 2 : Reusable and Reliable (可重用性且可靠性)
* 因為由Buttom up , 因此程式品質本就好
* Unit Test 3 : Unit testing help gauge performance (能幫助測量程式):(你可以在更早的時間進行效能測試)
* Unit Test 4 : Unit testing improves code coverage (改進測試覆蓋率)
## Bottom up Vs Top Down
* Project vs Product
* Short-term fix product vs long-term maintained project?
* 你的老舊系統 (legacy) 要不要回去補單元測試? (其實你想補也大概補不動)
* 一個可能的 good timing – 老系統因為效能,功能改善得重構 -> 圈出一個範圍補單元測試
# Junit
* @Test
* assertEquals(比對值,呼叫函數<被Test>)
* 
* BeforeEach : Test Case Run之前會先呼叫
* 不能添加 Static
* AfterEach: Test Case 每個Run完成以後呼叫
* 不能添加 Static
* AfterAll : Test Case 全部 Run完成以後呼叫
* 一定要添加Static
# Test Oracles
* 能判斷 Program Behavior 是否出錯,針對程式的輸入輸出做一比較
* monkey tests: 隨便亂點按鈕
* Teating automation 測試自動化困難之處
* 無法判別程式的正確與否
* 決定規格與一致性是否不符合
* 規格=> 正確性
*
* 人是最厲害的 Test Oracles
* 聖杯(holy grail)問題
## About
* 驗證是否與程式執行結果一樣
* 視為一個黑箱
* 使用CUT 建立物件
### Unit Test單元測試
* Unit Test = Black Box + White Box
* 有Source Code
* 需要額外增加
* 讀取Internal Value(內部變數)判斷
* Construction injection
* 當你需要使用 fake object
* 像是 test stub, mocks.
* 案例一: Construction injection
#### white box
* 能夠知道source code
* 推倒Test Case
* 能夠知道 Iternal behaviors 的狀況
### 案例一: Construction injection
* 
* 在Test Case呼叫後,
* 可提供給其他函數使用: Object 都會重新被建立,重新New
### 案例二: assertTrue Run For(){}
* 
* 
## True Oracle

* X 你寫的Program: 不確定是否正確
* 應用情境: 舊版改寫須重購、改良
* 不一定存在

## Partial Oracle

* X 你寫的Program: 不確定是否正確
* Detect X 輸出的值是否正確,不正確輸出 Failed
* 並不容易撰寫
* AVL Tree 案例實作
* 應用情境:
* Program Prove
* Precondiction PostCondiction

## Test-Oriented oracle(xUnit test)
## ParameterizedTest vs Partial Test Oracles
哪裡不一樣??
# 要寫多少測試才夠
* Code Coverage
* Paryition Test
* Boundery Test
* Negative Test
## Code Coverage

* Statement coverage: 每條路都走過
* 
* You only need 3 test cases to have each statement at least executed once.
* Testing 的最低測試標準
## Branch coverage: 分支測試

* there are 3 branches, so at most 2 * 2 * 2 branching
* 
## Path Coverage: 窮舉測試

* 
* 最困難達成,理論上達不到
* exhaustive testing
* 
* Omega(大寫Ω,小寫ω): infinite 無窮
## Summary 總結

* 左座標: 現實中是否能夠達成
* intractable: 棘手的;太困難的
* feasible: 可行的
* 金管會 要求到 Branch
* 基本上不可能達到
* 根據時間與資源決定測試的位置
## Partition Test
* 人類最古老的測試理論
* 
* Input 以及對應的 Domain
* 只需要挑橢圓形區域中的一個就可以嘞
* Equivalence partitioning(partition testing)
* White box 白箱測試
* 案例一: Bobble sort
* 測試案例
* 
## Boundery Test: 測試邊緣人,不只是邊界
* 通常 Boundery Test + Partial Test
* boundery values 被暴露出來
* 
* X=Y
* X=0,整數最大值、最小值
* Y=0
* 
* 
* 
* 
* 999999..., 根據規格書
* 字串超出範圍
## Negative Tests :(給不合法,超出範圍的參數值,看看你的程式碼會不會掛掉)
* 測試字串超出長度
* 字串不符合規定的跳脫字元
* 有非Ascii亂碼
# Unit test in Isolation

* Other Class 讀取檔案
* 不會包那麼大包的原因
* 因為會讓測試成本、代價過高
* 如改寫資料庫
* 因此使用假的Dummy Object來做取代

## Mocks and Other Test Double

* Dummy Object
* New 一個 Dummy 物件,只為了能夠讓Player建立出來
* Fack Object
* 已經有Interface,需要去繼承
* 建立一個新的Class
* Test Stub
* Constructor injection
* 讀檔案,會直接讀取,但測試實不希望干擾到系統
* 建立Constructor injection: 
* 將CUT的Code做更動,放入假資料mgr
Fack Object VS Test Stub??
# External Dependency: Test Stub
## External Dependenncy in a CUT
* 一個物件與你的系統必須有互動
* 對他沒有控制力
* 初始代價過高
* 牽涉到不可分離性: 會做實體的操作
* 對資料庫修改
## A Stub
* 可控制的取代依存之物件,創建一個假的模擬你需要的物件
* A stub can never fail the Test
* Intercept 攔截
* Unit Test單元測試的基本
### Aproach 1 : Fakes via Duplication: 類似Copy


* 無法隨心所欲單元測試
## Aproach 2 : Dependency Injection : 修改建構值
* constrictor Injection (建構值隔離)
* 只需要動態轉換物件即可
* Constroctor 只需要專注初始化記憶體與變數即可
### 物件導向的原則: LoD(Law of Demeter)
* 是否有複雜化的行為
* 給店員25元,是直接給錢包,還是拿25就好D
* 建構值: 
* engine = factory.... => 不應該出現在這裡,汽車何必知道工廠的資訊
* 應該在外面New 再丟進來
* 太多的物件繼承 : 
* 有太多的問號,不知道該測哪一個
* 物件繼承被濫用
* 
* 正確 : 
* If you dont't take advatage of polumorphism : 如果沒有要用多形,請把繼承拿掉
* B繼承A,B is A
* 把不對的繼承換成Composition
* (絕對不要!!)不要用繼承來Reuse你的Code
* Testability
* Seams (介面)
### Exaple 3

* 該測試為甚麼難寫
* 牽涉兩個物件
* Customer
* Money( wallet )
* 歸咎於你的Poor物件導向
* 
* 修正後的結果: 
* 將原本在purhase 呼叫 錢包 的動作,更改成只Input錢錢
* 相較上述,明顯少了兩個物件的宣告
* 原本應該專注於 Good,卻有多放入Money與Customer,以至於無法 test isolation
* 若兩個物件是正確的倒還好
* 最壞情況,會導致無法準確精準測試Good
## Approach 3: Testing with Mocking Framework
* legency 老舊系統是否能夠Testing??
* 想補也很難補救
* 可能需要重構
* 透過圈出小範圍
### Proble, with Stub
* 必須重新撰寫或新增另一個
* 測試不一樣的測試資料
* 動態測試資料
* 當測試Stub 會隨著修改或新增
* Stub 會隨著不一樣的條件回傳不同值
* 當 Interface 更新 也需要一起更新
*
#### Fragility of test case: 脆弱
* 開發時的變動,也讓你經常更動一大堆單元測試,表示程式或單元測試有一些脆弱與易碎性
* 開發階段常更動
* Class
* methods
* methods signature
* interface
* 必須探討開發流程是否有問題
* 物件導向
* 系統設計
* 隕石開發法
* 上帝
* 老闆
* 客戶端
### Mocking framework
* JUnit
* Mockito
* JMockit
* EasyMock
#### Mocking to replace
* 相關方法: 
* 程式碼案例:..... ..... 
* tuormock => TeachStub取代: 
* 語法: 
* 介面宣告: 
* tutormock.checkin(): 確認是否有值
* When(...).thenRewturn(...): 負責造假
* V.S.: 
* 都被取代掉了
* 語法2(callBack): 
### Another External Dependecy: Mock

* 測試的麻煩事情
* TCP 測試
* 需要再準備一個TCP Server
* 無準備,會卡住 Block
* 
*
#### State-Based vs Interaction testing (behavior testing)
* 如何知道灑水裝置定時灌溉
* state-based: 在乎結果,有許多狀況未被測試到,較為不精準(shit屎)
* 跑12小時
* 跑完後
* 檢查花草
* 檢測土壤濕度
* 是否枯萎
* 目前大部分的測試
* Interaction Testing: 在乎過程 (behavior object)
* 頭尾安裝: 流量偵測器
* Mock: 0記錄所有呼叫行為
#### TestStub vs Mock
* State-base Testing
* A stub can never fail the test
* Stub 通常模擬 內部物件之正確行為
* TestOracle 所要 assert 的正確性在 CUT的行為,不會再Stub 裡面
* 
* assert(,XXX())
* Interaction-Based
* Mock 通常模擬 內部物件接收 SUT 送出的Information
* Mock 會記錄CUT與自己的所有內部互動
* Tesr Oracle 所要的 asser 的正確型,會在Mock 收的訊息
* 
* 比較Care
* 呼叫什麼
* 每一次的參數
* API 倍呼叫的頻率
* 常見行為
* Real external objects (dependency) 在呼叫之後沒有回傳值,或是任何可以讓你驗證external objects 狀態(state)的方法
* 硬碟讀寫
* 資料庫讀寫
* 網路讀寫 (這是最常見的例子)
* 檔案讀寫
* Real external object 會實質更改資料
* Real external object 有 nondeterministic (不確定性)行為
* Real external object 很難觸發
* Real external object 很慢
* Real external object 是 user interface
* Real external object 使用 call back
* Real external object 的行為不容易觸發
* verify().XXX(): 根據流程驗證,是否是相同 Func 
* 
##### Exception Handling


# test-isolation



* DummyObject
* 
* Fack Objet
* a Test Stub acts as a control point to inject indirect inputs into the SUT the Fake Object does not. It merely provides a way for the interactions to occur in a self-consistent manner
## Exceptions from teststub
### 真實的 external dependency – Teacher 會丟 exception 嗎?
* SC SHOULD catch 並且處理掉
* SC IS DESIGNED NOT to catch,pass the exception upward
*
* 如果會,那 tutormock 也應該模擬丟出 exception
* 一般而言 test stub never fail the test,而且模擬所有正確的行為
* 產生了一個不存在學生的名字
* 呼叫 Teacher 的時候,傳的參數都沒有問題,但是真實 Teacher 因為學校的資料庫系統有問題
#### Case 1 :StudentCollection (SC) SHOULD catch (by design)

一般的原則是你在 test code 裡面是不會去 try catch 的。其原因如上
#### Case2: SC IS DESIGNED NOT to catch,pass the exception upward

test cases ALWAYS fail,你的 DEVOP pipeline 永遠都不會過 !