code

2017年11月27日 星期一

Software Testing 5 - Code Review and Defects

Code review

code review / inspection對找出defects很有幫助,不過實務上似乎很少進行。通常能透過code review找到的defects如下:

1. 缺少或是錯誤的comments
2. 重複性的code
3. 過於複雜的設計
4. 無法測試的路徑
5. 錯誤使用技術
6. coding errors (這啥?!)

 細分的話,其實code review還可以分成以下三類:
1. walkthru:
找個senior的幫你看一些部分,稱為peer review。

2. code review:
這是最常進行的,可能牽涉多個reviewers,主要檢查implementation。


3. inspection
這是最正式的code review流程,可以有以下腳色:

Moderator – works with author to schedule inspection, send out materials, runs meeting, follows up with author on follow-ups from inspection (often team lead or project manager)
·         Author – provides moderator with inspection material, explains material as needed, responds to questions, responsible for rework based on inspection comments
·         Reader – walks though the code, saying what it does in English and stops for comments on that piece
·         Reviewer – technical experts for the document being inspected; provides comments and questions

·         Recorder – one of the reviewers who agrees to document issues raised at the meeting; usually compiles a list with categories (defect, suggestion, comment, etc.) and distributes to all after meeting; opens internal defect reports to help track fixes


Defect Management

俗稱bug XD,就是不按照design發生的行為。

defect不一定能找出來,找出來也不一定要或能修改,修改後也不一定正確。
所以必須要有系統性的方法來面對defects,需要一個defect tracking system。

defect 可以有類似以下的tracking status:



Defect Report


defect reports不只是展現QA人員的專業,也是developers的重要資產。
defect report需要包含以下:
1. isolation: 切割出可以復現的操作方法
2. generalization: 即便切割出來,但仍需要考量此defect對整體性的影響
3. severity: bug分級定義,根據發生機率以及衝擊性

綜合以上,一個可能的defect report template長這樣:

Item
Description
Title
A unique, concise and descriptive title for a defect is vital. It will allow the defect to be easily identified and discussed.
Good : “Closed” field in “Account Closure” screen accepts invalid date
Bad : “Closed field busted”
Severity
An assessment of the impact of the defect on the end user
Status
The current status of the defect
Initial configuration
The state of the program before the actions in the “steps to reproduce” is to be followed. All too often this is omitted and the reader must guess or intuit the correct pre-requisites for reproducing the defect.
Software
Configuration
The version and release of software-under-test as well as any relevant
hardware or software platform details (e.g. Win 7 vs Win Vista)
Steps to Reproduce
An ordered series of steps to reproduce the defect
Good :
1. Enter “Account Closure” screen
2. Enter an invalid date such as “54/01/07” in the “Closed” field
3. Click “Okay”
Bad: If you enter an invalid date in the closed field it accepts it!
Expected behavior
What was expected of the software, upon completion of the steps to reproduce.
Good: The functional specification states that the “Closed” field should only
accept valid dates in the format “dd/mm/yy”
Bad: The field should accept proper dates.
Actual behavior
What the software actually does when the steps to reproduce are followed.
Good: Invalid dates (e.g. “54/01/07”) and dates in alternate formats (e.g.
“07/01/54”) are accepted and no error message is generated.
Bad: Instead it accepts any kind of date.
Impact
An assessment of the impact of the defect on the software-under-test. It is
important to include something beyond the simple “severity” to allow readers to understand the context of the defect report.
Good: An invalid date will cause the month-end “Account Closure” report to crash the system and corrupt all affected customer records.
Bad: This is serious dude!
(Proposed solution)
An optional item of information testers can supply is a proposed solution.
Testers often have unique and detailed information of the products they test and suggesting a solution can save designers and developers a lot of time.
Priority
An optional field to allow development managers to assign relative priorities to defects of the same severity
Root Cause
An optional field allowing developers to assign a root cause to the defect such as “inadequate requirements” or “coding error”



Root Cause Analysis

root cause analysis通常有助於降低未來defect發生的可能性,可能的種類如下:

Classification
Description
Requirements
The defect was caused by an incomplete or ambiguous requirement with the result assumption differing from the intended outcome.
Design Error
The design differs from the stated requirements or is ambiguous or incomplete resulting in assumptions.
Code Error
The code differs from the documented design or requirements or there was a syntactic or structural error introduced during coding.
Test Error
The test as designed was incorrect (deviating from stated requirements or design) or was executed incorrectly or the resultant output was incorrectly interpreted by the tester, resulting in a defect “logged in error”.
Configuration
The defect was caused by incorrectly configured environment or data.
Existing bug
The defect is existing behavior in the current software (this does not determine whether or not it is fixed).



2017年11月25日 星期六

Software Testing 4 - Test case, suite, report

Testing the design

requirement / documentation / spec 其實也可以test,主要針對以下五個方向去檢驗:
1. specific: 越明確越好
2. measurable: 能夠量化
3. testable: 其實就是1. 2. 的結果
4. consistent: 要跟先前的spec一致
5. exclusive: 把"不該做的"也明列出來。


non-functional (non-feature) test cases

非功能性的tests,包括:
1. usability
2. scalability
3. performance
4. security
5. logging
6. reliability
.
.
.
通常是functional test通過之後,才會進行non-functional tests。


Performance testing

舉performance testing來說,一個明顯困難點在於通常不能用production environment來測試,因為會影響營運,所以必須有一個test environment來模擬production environment。

此外performance testing重點在測試系統弱點,這屬於白箱測試,只有系統開發者知道哪些是可能的弱點,不要因為"政治因素"害怕去測試這些點的極限。

此外要有baseline當比較對象,因為有些時候performance improvement沒什麼太大意義,如果baseline profile已經達到,可能不需要投入資源去提升performance。

performance testing包括以下種類:
1. load testing: 測試在不同的load狀態下,系統有什麼behavior
2. stress testing: 找出系統能承受的最大capacity
3. soak(endurance) testing: 主要瞄準長時間狀態下,系統的在某個load的承受能力
4. spike testing: 這是測試突然增加極大load會讓系統產生什麼行為


Test plan的重要性

test是要規劃的! 不是自己隨興加減測試,事實上這是一個挑戰!
先要有個認知是: 100% coverage是不可能的。

事實上要把test plan當成一個project,所以也會有project management中需要考量的三元素: resource / budget / schedule

所以選擇測試標的,也是一個學問,可能的方向:
1. 趕時間做出來的item
2. remote data / api 接介
.
.

test coverage廣度: 盡可能發現系統中潛在bug
test coverage深度: 在某些容易發生bug的系統,大量重複深入測試


Test Suite

就是一堆test cases的集合,歸類成某一類。


Test report

可能包含以下項目:

1. scope: 測試涵蓋了那些範圍,也該列出未涵蓋的範圍
2. 測試通過標準: 那些問題一定要fix,test cases通過率
3. 測試方法
4. 最後結果
5. defects/status: 列出目前測試出來,尚未解決的defects

上面講的有點籠統,主要是還是要看相關人員想要看到資訊才能做後續決策。




2017年11月22日 星期三

ios XCode9 Continuous Integration

名詞解釋

scheme: 就是build script
bot: 執行schemes,也可以排程的process
Integration: 每次bot執行一次稱為一次integration

Continuous Integration Chart


好處
1. 早期整合,早期發現問題
2. 在server build/test,不用浪費開發者時間
3. 可以排程,測試各版本simulators/devices
4. 產生報表


pre-XCode9: 安裝XCode Server

要先安裝macOS server app:


這邊先略過了,畢竟xcode9已經發表了。


post-XCode9

藏在xcode 裡面:

WWDC 2017有影片說明整合進去xcode。

1. automatic code signing
2. 整合進入xcode 9
3. 自動在simulators / devices 上測試


Code Signing

app需要簽名認證,辨別是真實發行者,ios在app runtime會檢查此數位簽名,才能才能確保以下三件事情:


製作一個signature需要以下三個文件:


1. certificate:
2. provisioning file:
3. entitlement:

以上的細節可以在2016 WWDC XCode Automatic Code Signing影片中詳細解釋。

簡單來說,Xcode 9最大的改進就是把automatic code signing放入 Xcode Server

也唯有automatic code signing才能讓xcode server去在手機上自動化測試app,因為需要code signing (只要target有設定automatic signing):



這背後依賴另一個command line executable : Xcodebuild,所以第三方CI server(e.g. jenkins) 也可以利用此Xcodebuild command去做automatic code signing。



Setup XCode Server in XCode 9

1. 先到xcode preferences打開xcode server:



把右上角switch打開會自動設定,結果如下:



2.  在accounts pane加入xcode server當成“開發者一員”,因為這樣才會有bot (軟體機器人)讓我們來排成做事:



至於Manual Signing影片中有講到,可以先略過。


Setup a bot

在product menu最後有一個"create bot",點下去之後xcode會自動去看目前project是否是來自某個git repository (猜測應該是去scan專案目錄)以及下載的branch,然後會要求設定登入帳號密碼。

之後會有一連串的設定,都可以先採取預設值就好,反正都可以在更改。
接下來會來到要不要授權此 "server team member"來管理 automatic signing issues:



建立bot之後,似乎會馬上進行一次integration,所謂的integration包含以下步驟:
(a) 從repository下載branch
(b) build app
(c) provisioning / signing
(d) test


Distribution Signing 

開發過程中打包的app 稱為archive,這是需要development signing,流程相對簡單。
如果要發布到app store,需要做distribution signing,把archive再打包成.ipa檔案:



事實上有三種distribution signing,adhoc / enterprise / app store:


XCode server可以distribute signing似乎是個很大個改進?不確定,總之台下有歡呼就是了,之後有需要用到再說吧。



優點

1. 整合性超高
2. 可以parallel test,比較神奇的是,某些simulator連launch都沒有,不知道怎麼測試出來的?



3. automatic signing



2017年11月21日 星期二

iOS test 2 - UI test & XCTest framework

XCode 7的新功能

首先罵一下apple,好少的official tutorial,好爛的documentation!!!
這一點Android好太多!!!!

這在WWDC 2015出現,可以選左邊這個連結觀看影片。

整個UI test架構主要由以下三個classes構成:



XCUIApplication

這是UIApplication的代理人 (proxy),會永遠啟動一個新的process,幫助我們clean app state,XCUIApplication也是所有XCUIElement的最上層,形成一個element hierarchy:




XCUIElement

這是UIApplication中的UI element的代理人。

要找到畫面中的一個XCUIElement,我們需要進行query,其實體化物件為XCUElementQuery。要做任何event synthesis (例如tapping) 或是access property的動作一定要是unique element,否則XCTest不知道要找哪一個才是正確的,所以就會被判定成failure!


XCUIElementQuery

有一個安全測試XCUIElement是否存在的屬性: exists。
使用exists屬性,即便UI element已經不存在,或是非唯一,都不會使得test case被判定成failure。

每個query都會回傳一個set,可能有零到多個elements,可以用subscript operator (e.g. [ ] )來取得:




Relationship Query

1. Descendents (所有在某個ui element下面的ui element):



2. Children (direct descendents):



3. Containment:
這是當一堆無法unique分出來的elements,例如uitableview cell,但是他們subviews會有獨特的元素,就可以query他們的containment relationship,來代表此cell的獨特性。


Filter a query

filter一個傳回來的query:
1. UI type


或者是方便的api:




2. ids: accessibility id / label / title

3. predicates

4. relationship




Query evaluation

算是lazy evaluation,只有當以下情況才會被evaluated:


Event Synthesis

這個就是模擬使用者能做的互動,所有程式通道都是跟真實互動時的通道一樣。

Non-accessible UI Elements

如果發現某些element看得到,但是無法在test case access的話,可能有以下原因:


2017年11月18日 星期六

Software Testing 3 - UAT (User Acceptance Testing) and Usability Testing

Human Testing

UAT就是提出requirement的user去驗證(validation)我們寫的程式是否符合他們requirement。
UAT test plan在design phase就會底定,UAT會在開發完成後進行。
UAT不只是以requirement為基礎來validate,也應該要以user scenario來驗證。

UAT的主要挑戰

如果定義UAT在開發完成後才進行,所以要改變需求或是feature是很困難的,通常是不允許的。

敏捷開發建議客戶參與開發流程的意味,事實上這是比較好的方式,漸進式mini UAT變成正式開發流程之一,要求UAT測試者簽署測試通過文件(formal acceptance),確保嚴重的design defects不會在開發結束才發現。


各種Acceptance Testing

不是只有UAT,還有:

1. Factory Acceptance Testing: 經銷商在供貨前測試
2. Site Acceptance Testing:在客戶端安裝後測試,主要是整合性
3. Operation/Production acceptance testing: 主要測試功能性
4. Compliance/Regulation acceptance testing:法規測試

Usability Testing

這是關於好用與否,主要領域是HCI / UX,在此掠過。


Alpha/Beta Testing

alpha主要是內部測試,beta是外部測試。
alpha階段應該就要找出工程上的major defects,讓beta階段著重在使用者回饋修改,因為beta階段可以算是模擬營運階段。


Software Testing 2 - Autotest and Statement Coverage

節省成本

長期來說,理想上寫一次test case卻能無限多次測試,這是非常節省時間與成本,又增進software robustness的方法。

多人共同開發的必須流程

特別是在agile methods的規範中,一天可能會release several times,每次integration回去main branch一定要經過大量的測試,此時需要auto test cases。


製作Auto test cases的代價

unit test很簡單,也很快速可以寫完,在開發過程就可以順便做完。
function test (integration test)則要花更多時間,因為他是要測試模組間的互動,以及一些code path,所以有時候其實手動測試會比寫一個function test快,視情況而定。

事實上 testing program 也是code,理論上所有開發流程都也該應用在test cases上,包括test the test cases!
不過這樣有點弔詭,理論上寫得夠清楚的話,test cases不需要再被test,要不然不就沒完沒了。

test cases也要被放入一個testing repository,就跟一般的code一樣需要版本管理與維護,這些都是成本!

如果test cases需要時常更改變動,那可能這個project不適合auto test,因為維護成本會大於效益。


Automate 什麼標的?

1. 有testing framework support的語言或是開發環境
2. 很穩定不常變動的requirement / spec
3. 重複性高的測試,regression bugs
4. 人類能力無法勝任的test
5. 多組input data / cross platform tests
6. concurrency
7. 花大量時間者 (可以auto test就跑回家睡覺)


JUnit

JUnit可以寫unit test也可以寫function test,語言當然就是Java,所以叫JUnit。

JUnit提供一些predicates,回傳某些條件的true or false,unit test最好只要測試一個predicate,這樣才能說是"unit test",否則如果使用了兩個以上的predicates,由於第一個predicate failed的話, JUnit就會停止測試這個test,那會讓測試者誤以為整體program的test failure很少的錯覺,因為同一個unit test中的其他的predicates都沒被測試到。


Code Statement Coverage

下圖的default constructor需要兩個test cases,分別測試constructor中的兩個instance variable值是否正確:


注意每個test case應該都只能測試一個值!
為什麼我們要測試這個相當簡單的assignment statement? 因為這是spec,如果未來有人改變了constructor中的assignment,就是違反了spec,則我們的test cases就能抓到!

test cases如下:




以下的second constructor需要四個test cases,分別是執行line32, 36, 39, 40,if statement不需要測試,因為那無法驗證什麼東西:


相對應的test cases如下:





通常我們不需要測試getters,因為他的執行是trivial顯而易見的:


以下這個method事實上只需要一個test case就可以測試所有statements line 59,62,63,65:


因為全部都是連動的。

test case如下:




Branch coverage

branch coverage重點在要執行過所有conditional statement的true / false test,在上面提到的constructor中:


這邊需要4個test cases來測試兩個if,else statement則是跟隨著第一個if被測試了。
如果同時做statement coverage的話(已經測試所有if 為true,以及else為true,共3個branch被covered),我們這邊只需要再做一個test case 來測試第二個if 是false的狀態即可。

同樣的,對以下的method來說,如果已經做了statement coverage,則branch coverage只要再加上一個while condition evaluates to false的condition即可:





Path Coverage

path就是測試所有method最後return的路徑,例如上述的constructor:


有三個paths: 兩個throw statement,以及都沒有throw exception,最後隱性的從Line41 return的path。



Data Coverage

這邊稍微紀錄一下data coverage,主要就是測試spec中的臨界值,光是statement coverage是無法測試到所有的臨界值或是極大小或是特殊值。

2017年11月17日 星期五

Agile Software Development 9 - Agile Methods 評比

Ugly (太過極端或是因咽忘食)

1. 不做早期requirement analysis與架構設計: 先期的analysis是必要的,不要太過火就好。
2. user stories不能取代requirement spec
3. test也不能當作requirement spec: 因為test cases不夠全面,是點狀
4. 忽略或是否認系統components之間的dependency: 幾乎是不可能independent
5. Scrum Master應該要寫code
6. TDD 代替analysis - 太極端
7. manager腳色被替代 - self organizing team是個理想,完全取消manager是個幻想
8. 不考慮未來extendibility/reusability - 太短視近利


Hype (不重要的主張)

1. pair programming - 之前說過了
2. 開放辦公空間
3. self-organizing team - 理想
4. 可持續性步調 - 我認為這是重要主張,只是時常現實面達不到
5. MVP - 這也是要看客戶需求而定
6. planning poker - ?
7. cross functional team - team內還是有專家的
8. embedded customers - 通常這類人員代表性不足,也很難在開發過程中產生作用


Good (agile methods中值得採用的方法)

1. acceptance of change - 闡明"改變"是軟體開發的本質之一,接受這個本質,甚至可以變成競爭力
2.  iterative development - 應該是"short"iteration才是重點
3. code是重點 -沒錯,不要一直"討論討論討論"
4. tests是重點 - 這真的是重點!!!!!!!!!!!!!!!!!!!!!!
5. 常態性regression tests
6. velocity - 給progress一個衡量指標
7. no branch - 這邊我不確定原因為何,看來作者同意multiple branches是個危險的設定,需要找更多相關資訊。
8. product burndown chart - velocity的視覺化,這讓所有參與者知道目標快達成(落後)了沒?
9. daily meeting - 有心理學上的意義


Brilliant (軟體工程中的高明見解)

1. short iterations - 哈,看來我看法跟他一樣
2. closed-window rule - 在iteration中不能改任何requirement / spec
3. refactoring - 不斷精進
4. 所有的functionality都該有associated test - 達到quality software的基本要求
5. 伴隨第一點就是以及no branch就是Continuous Integration


Quality is Key

and is King


2017年11月16日 星期四

Agile Software Development 8 - Artifacts

Artifacts (用來support agile practices的工具)

很怪的名字。


User Story

可以使用小卡片(story cards),用來表示最不可分割的requirement。



Task card: story card的companion task。

Use case

可以說是複查精確版的user story,用來描述如何透過系統中或外的各種互動來達成某個task / business goal,是UML diagram的一種類型:



Product backlog (Scrum)

包含以下功能:



Task board

這是product backlog的具體化:


所以trello介面基本上就是一個task board

Velocity (Scrum)

這是scrum嘗試要描述project progress的指標,可以用各種想要的指標,具體化的artifacts是burndown chart:


Bullpen (XP)

大開放空間,方便溝通,資訊流通。


2017年11月15日 星期三

iOS test 1 - XCTest 概論

XCTest

XCTest是Xcode內建的Testing framework,有提供UITest / Unit Test,UI Test只能使用在ios 9以上的simulator/devices。

Unit test

最好用來測試MVC這三個components,或是你寫一個library也適合用unit test。

UI test

XCTest提供了recording功能,可以記錄測試者的動作來形成test cases。這聽起來是相當好的功能(不過試過了才知道好不好)。


Test Classes

test classes算是用來設定測試大分類,所有的test classes都是XCTestCase的subclasses。

一個xcode default產出的test class長這樣:
#import 

@interface MyMOMOTests : XCTestCase

@end

@implementation MyMOMOTests

- (void)setUp {
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testExample {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
}

- (void)testPerformanceExample {
    // This is an example of a performance test case.
    [self measureBlock:^{
        // Put the code you want to measure the time of here.
    }];
}

@end

其中setup() 和 tearDown()相當於 willTest() 和 didTest(),用ios viewcontroller的術語來說。

Serial Test Execution Flow

Test class中的每一個 test method測試時都會重新initialize 這個test class instance,所以setup() 和 tearDown() 都會重新跑一次。跑完所有的 setup -> method -> teardown triplets之後,這個Test class就算測試完畢,接著再跑下一個test class。

所以test flow是serial的

所以setup / tearDown 可以當作shared init/deinit function,對所有的methods來說。


寫測試methods

test class中的test method的function prototype是 不回傳值,也不接受參數的function,例如:


Async Operation Tests

前面說過test execution flow是serial的,所以遇到async operation test的話,XCTest framework會等待此async operation returns或是timeout,這邊要用到的是XCTestExpectation class

例如以下的code中,最後的waitForExpectationsWithTimeout 會被block住,直到前一行openWithCompletionHandler async operation結束。



這適合用來測試某個網頁或是API是否respond了


Performance Tests

這個會把你丟入的block (closure)跑十次,取mean 和 standard deviation,然後跟某個baseline profile 比較。

例如以下測試加法10次 (但是每次有個loop跑10000次加法):



所謂的baseline是記錄在device configuration,因為每個device的能力都不一樣。


XCTest Assertions

assertion的形式大概長這樣:




Code Coverage

XCode內建code coverage功能,應該是statement code coverage,不過一launch就會發現有些file已經有一點code coverage,即便沒寫任何的test cases,為何?因為宣告static variables等於在run test的時候一定會執行到,所以就會被記錄在有被cover到。


XCode會紀錄在test過程中被呼叫到的statement次數:



Test Automation

XCode有自己的CI server,之後用到再來筆記筆記


User Interface Testing

這是模擬user怎麼使用你的app 的過程,這是一個blackbox test。

UI Test依賴兩個framework:
1. XCTest
2. Accessibility

因為這是最近才加入的功能,所以需要較新的軟體環境:


主要用到以下三個XCTest中的classes:


UITest最好是用recording的方式(最下面toolbar的紅色錄影按鈕),這樣不用自己寫code之外,也可以知道怎麼使用UITest相關的classes:



當然UI Test也是可以做performance test。

不過這邊有個XCode 9 default打開的Main thread checker,會讓test crash,因為test是跑在non-main thread上,所以有用到UIKit的code都會被此checker擋住,丟出exception,這邊有詳細解釋所以在不改動code的前提下,可以先disable Main Thread Checker,這應該只影響到Test Scheme



疑難雜症1: 關於unicode

在UI Test recording的時候,會發生中文側錄的問題 (”UITest incompatible universal character"),只要手動把抓到的unicode @"\U..."改成@"\u..\u..." 即可,我不求甚解囉,不想管原因是啥,請看這篇blog解釋

其實如果沒有多國語言的問題的話(單一語言),直接在test case裡面寫中文就好。