---
# System prepended metadata

title: 軟體工程 Week 4
tags: [軟體工程]

---

# 軟體工程 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
![](https://i.imgur.com/M3sbvO0.png)
* 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
![](https://i.imgur.com/mrM7XxK.png)
* 瀑布模型 開發模式
### 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)
![](https://i.imgur.com/LjNO8lF.png)
* 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 
* ![](https://i.imgur.com/A3O8VeC.png)

## 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: 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
* ![](https://i.imgur.com/R4PeWei.png) => ![](https://i.imgur.com/N9RqFY1.png)
* 敏捷開發 => 回歸測試自動化 

## 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
    * ![](https://i.imgur.com/x45lksp.png)

    * Test Runner
    * Dummy r(): 假的 = fack
        * 使用造假輸入，並回傳
        * 設定中斷點
        * 使用假的 Server

### Testing in isolation
![](https://i.imgur.com/gT1WWAg.png)

## 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>)
    * ![](https://i.imgur.com/W7NSCNE.png)
* 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
* ![](https://i.imgur.com/kRxZevz.png)
    * 在Test Case呼叫後，
        * 可提供給其他函數使用: Object 都會重新被建立，重新New
 
### 案例二: assertTrue Run For(){}
* ![](https://i.imgur.com/NGEtZPs.png)
* ![](https://i.imgur.com/Krf3dcY.png)

## True Oracle
![](https://i.imgur.com/Fr0ojtF.png)
* X 你寫的Program: 不確定是否正確
* 應用情境: 舊版改寫須重購、改良
* 不一定存在
![](https://i.imgur.com/VZ7qh0F.png)

## Partial Oracle
![](https://i.imgur.com/rFtE9iI.png)
* X 你寫的Program: 不確定是否正確
* Detect X 輸出的值是否正確，不正確輸出 Failed
* 並不容易撰寫
    * AVL Tree 案例實作
* 應用情境: 
* Program Prove
    * Precondiction PostCondiction
![](https://i.imgur.com/5Icubrw.png)





## Test-Oriented oracle(xUnit test)
## ParameterizedTest vs Partial Test Oracles
哪裡不一樣??

# 要寫多少測試才夠
* Code Coverage
* Paryition Test
* Boundery Test
* Negative Test

## Code Coverage
![](https://i.imgur.co:m/f7od7i9.png)
* Statement coverage: 每條路都走過
    * ![](https://i.imgur.com/uXGf0pE.png)
    * You only need 3 test cases to have each statement at least executed once.
* Testing 的最低測試標準
    
## Branch coverage: 分支測試
![](https://i.imgur.com/KB9PFmB.png)
* there are 3 branches, so at most 2 * 2 * 2 branching 
    * ![](https://i.imgur.com/bcHaA9L.png)

## Path Coverage: 窮舉測試
![](https://i.imgur.com/yOnmbEa.png)

* ![](https://i.imgur.com/XBHOoOg.png)
* 最困難達成，理論上達不到
* exhaustive testing
* ![](https://i.imgur.com/vB0r6eP.png)
    * Omega（大寫Ω，小寫ω): infinite 無窮

## Summary 總結
![](https://i.imgur.com/DTF9STi.png)
* 左座標: 現實中是否能夠達成
* intractable: 棘手的；太困難的
* feasible: 可行的 
* 金管會 要求到 Branch
    * 基本上不可能達到
* 根據時間與資源決定測試的位置

## Partition Test
* 人類最古老的測試理論
    * ![](https://i.imgur.com/ViwHjyo.png)
    * Input 以及對應的 Domain
    * 只需要挑橢圓形區域中的一個就可以嘞
* Equivalence partitioning(partition testing)
* White box 白箱測試
* 案例一: Bobble sort
    * 測試案例
    * ![](https://i.imgur.com/SFrBhyu.png)

## Boundery Test: 測試邊緣人，不只是邊界
* 通常 Boundery Test + Partial Test
* boundery values 被暴露出來
* ![](https://i.imgur.com/n2g5ymX.png)
    * X=Y
    * X=0，整數最大值、最小值
    * Y=0
* ![](https://i.imgur.com/TmlSHqh.png)
    * ![](https://i.imgur.com/SXLt6yT.png)
* ![](https://i.imgur.com/j1ZzXAd.png)
    * ![](https://i.imgur.com/TG768yB.png)
    * 999999..., 根據規格書
    * 字串超出範圍
## Negative Tests :(給不合法，超出範圍的參數值，看看你的程式碼會不會掛掉)
* 測試字串超出長度
* 字串不符合規定的跳脫字元
* 有非Ascii亂碼

# Unit test in Isolation
![](https://i.imgur.com/NhvuNYU.png)
* Other Class 讀取檔案
* 不會包那麼大包的原因
    * 因為會讓測試成本、代價過高
        * 如改寫資料庫
    *  因此使用假的Dummy Object來做取代
    ![](https://i.imgur.com/eXv56xh.png)

## Mocks and Other Test Double
![](https://i.imgur.com/ylLDS5L.png)
* Dummy Object
    * New 一個 Dummy 物件，只為了能夠讓Player建立出來
* Fack Object
    * 已經有Interface，需要去繼承
        * 建立一個新的Class
* Test Stub
    * Constructor injection
        * 讀檔案，會直接讀取，但測試實不希望干擾到系統
        * 建立Constructor injection: ![](https://i.imgur.com/GGzyADT.png)
            * 將ＣＵＴ的Ｃode做更動，放入假資料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
![](https://i.imgur.com/4TMF58e.png)
![](https://i.imgur.com/lzb0zGM.png)
* 無法隨心所欲單元測試
## Aproach 2 : Dependency Injection : 修改建構值
* constrictor Injection (建構值隔離)
    * 只需要動態轉換物件即可
    * Constroctor 只需要專注初始化記憶體與變數即可
### 物件導向的原則: LoD(Law of Demeter)
* 是否有複雜化的行為
* 給店員25元，是直接給錢包，還是拿25就好D
* 建構值:  ![](https://i.imgur.com/8uwD2LZ.png)
    * engine = factory.... => 不應該出現在這裡，汽車何必知道工廠的資訊
        * 應該在外面New 再丟進來
* 太多的物件繼承 : ![](https://i.imgur.com/n8UtxlU.png)
    * 有太多的問號，不知道該測哪一個
    * 物件繼承被濫用
        * ![](https://i.imgur.com/G3yEvHh.png)
            * 正確 : ![](https://i.imgur.com/j22719o.png)

            * If you dont't take advatage of polumorphism : 如果沒有要用多形，請把繼承拿掉
        * B繼承A，B is A
        * 把不對的繼承換成Composition
        * (絕對不要!!)不要用繼承來Reuse你的Code
        * Testability
            * Seams (介面)
### Exaple 3
![](https://i.imgur.com/iaqn2Cr.png)
* 該測試為甚麼難寫
    * 牽涉兩個物件
        * Customer
        * Money( wallet )
        * 歸咎於你的Poor物件導向
            * ![](https://i.imgur.com/dZM5yxJ.png)
        * 修正後的結果: ![](https://i.imgur.com/tZTBInz.png)
            * 將原本在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
* 相關方法: ![](https://i.imgur.com/Bivfe5R.png)
* 程式碼案例:![](https://i.imgur.com/B65JecL.png)..... ![](https://i.imgur.com/7nKBcci.png)..... ![](https://i.imgur.com/KlDZYMm.png)
    * tuormock => TeachStub取代: ![](https://i.imgur.com/9wL1TCW.png)

* 語法: ![](https://i.imgur.com/cC70fEp.png) 
    * 介面宣告:  ![](https://i.imgur.com/kxuKbIY.png)
    * tutormock.checkin(): 確認是否有值
    * When(...).thenRewturn(...): 負責造假
    * V.S.: ![](https://i.imgur.com/Vski0Ek.png)
        * 都被取代掉了
* 語法2(callBack): ![](https://i.imgur.com/IPifg5B.png)

### Another External Dependecy: Mock
![](https://i.imgur.com/MrliHFp.png)
* 測試的麻煩事情
    * TCP 測試
        * 需要再準備一個TCP Server
        * 無準備，會卡住 Block
        * ![](https://i.imgur.com/SttI0q4.png)
        * 


#### 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 裡面
    * ![](https://i.imgur.com/8aUfv7M.png)
    * assert(,XXX())

* Interaction-Based
    * Mock 通常模擬 內部物件接收 SUT 送出的Information
    * Mock 會記錄CUT與自己的所有內部互動
    * Tesr Oracle 所要的 asser 的正確型，會在Mock 收的訊息
    * ![](https://i.imgur.com/zntAGkY.png)
    * 比較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 ![](https://i.imgur.com/DXnAk1b.png)
        * ![](https://i.imgur.com/wkBxEEG.png)
##### Exception Handling
![](https://i.imgur.com/tfC2Wi5.png)
![](https://i.imgur.com/2jPuNSb.png)

# test-isolation
![](https://i.imgur.com/O0RB2of.png)
![](https://i.imgur.com/NYj2EwE.png)
![](https://i.imgur.com/jcvQQPY.png)
* DummyObject
    * ![](https://i.imgur.com/If0TOnz.png)
* 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)
![](https://i.imgur.com/tQkoxpB.png)

一般的原則是你在 test code 裡面是不會去 try catch 的。其原因如上

#### Case2: SC IS DESIGNED NOT to catch，pass the exception upward

![](https://i.imgur.com/hC4H7M9.png)

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










