2017年7月6日

測試的方向選擇

又默默地過了一年.... 

做了一陣子 test infrastructure development 回來重做測試規劃, 可以說也有些體會, 或者說發現一些之前覺得理所當然的東西現在要重新整理一下思考邏輯.

假設有一項測試工作交代下來, 要做之後半年到一年間的規劃, 我們應該做些什麼呢? 

時間跟資源(包括人力以及開發的時間)是做規劃的重要依據, 但還是有些事情在這之前需要先釐清.

好比說產品的方向, 當然可以是產品經理跟使用者體驗設計師的工作, 但是沒有這個方向在做風險評估上會有問題, 即是在問題嚴重程度上會有歧見.

在縮短上線時間為第一目標的前提之下, 我們其實要從一些營運上的角度來思考.

  • 什麼功能是要99.99%可用的? 
  • 什麼功能中斷服務一陣子使用者是可以接受的? 
  • 如果這個功能無法使用了, 我們可以做些什麼? 較低品質但可以維持功能使用? 提示使用者重啟服務? 自動回復並屆時通知? 
  • 即使上線了, 是不是也有方法定期監測功能是否穩定? 
  • 上線後發現問題, 該怎麼解決? 能直接觸發回溯至前一個穩定版本? 
  • 離線或不支援類似功能的話應該怎麼辦? 
這些看起來不是測試的問題, 然而掌握到話無疑可以在測項的建立與取捨上有更好的發揮. 

在有開發資源的狀況下, 我們還可以從測試設施的角度多思考一點.

  • 現有自動化的設施是否完備? 
  • 自動化工具是否有改善空間, 以減少工程師花在上面的時間? (一個例子是, 如何讓自動測試可以在合理的時間內跑完, 像是30分鐘?) 
  • 測試方法上是否 現有的驗證方法是否可靠? 
  • 有沒有更有效的方法驗證並減少錯誤? 
在軟體的方向越來越多元的現在, 軟體品質漸漸從這種多元中抽出模式, 如何快速地理解產品及服務的內容與本質, 兼顧上線後的規劃, 做測試架構才能由針對產品本身走向更普遍可用的服務.

2016年3月28日

買了 google domain

幫家裡的網站續約網址之後感覺也可以幫自己買一個, 沒想到過程比想像的還麻煩....
主要是 google domain 有使用其他 google 的服務, 像是 google wallet, 而沒有使用過 Android 的原因使我對他們非常陌生....

目前 dns 還沒有正確的導到這個網誌, 等到我發現他成功運作以後再來回這篇吧...orz

2015年1月14日

python decorator 也可以吃參數

看了草稿累積的狀況感覺... 來寫一點簡單的筆記好了。

最近碰了一點 python 的 decorator,透過 wrapper 的方式幫你處理一些 function 重複的部分,相對簡明而好懂。
但如果我需要多種 decorator 但只有些微的不同呢?
可能會考慮直接寫多個來實現, dec1, dec2, ... 然後再用 function 的方式去包裝,考慮了 http://stackoverflow.com/questions/10176226/how-to-pass-extra-arguments-to-python-decorator 裡面說的,也可以透過傳一個參數的方式去實現。

python 並非原生支援這種語法,所以寫起來有點難讀,不過使用的時候會比較簡潔。

另外一個在寫 decorator 遇到的事, 就是要注意進入 function wrapper 的時候,原來要傳入的 arguments 並不存在 wrapper 的 scope 。所以只能多包東西進去,不能調整傳進來的東西。

2013年3月29日

軟體測試這回事

做了幾年的軟體測試, 覺得這行飯其實還滿微妙的.

有些人叫測試工程師, 或者 QA (Quality Assurance 品管?) QC (Quality Control), SQA, Tester, blabla.... 這個 domain 對台灣人比較陌生, 最酷的是你在學校很難學到.
一般測試可能會遭遇到以下工作:

  • Manual Test, 使用開發完的產品. 包括照表操課的 (有準備 test plan), 或者隨便亂試的. 這類的工作價值有一部分是使用產品本身就是模擬使用者 (客戶) 去操作產品, 相對於其他測試會更能貼近用戶會遇到的問題. 由於正職的測試人員對產品會有一定的熟悉 (也應該熟悉啦), 這件事會讓測試用戶體驗上有負面的影響, 所以也常有公司單獨作這一塊的測試, 有點像是市場調查.
  • Test Planning (Design?) , 泛指 test case creation, test plan creation, ... 跟產品相關的. 這邊的工作常與上面的工作重疊.  也有些公司把這邊的工作特化出來. 或者產品根本就是有白紙黑字的規格, 這邊的工作負荷相對少. 軟體測試因為產品改變的速度極快 (一天變好幾版也有可能), 規格改變導致測試項目與預期結果也急遽改變, 擔任這個角色的工作內容比較吃重.
  • Test Reporting, 根據測試結果產生測試報告. 這邊提到的測試報告是一個彙整, 根據所有測試報告產生列表或者圖像的結果, 以提供決策人員客觀的品質評估. 有些公司是 Developer 作這件事; 也有些地方是 Lead, Manager 在做的.
  • Test Automation, 測試自動化. 有鑑於人作的永遠不會比程式快, 很多公司在考慮流程優化的時候會想到這件事. 如果讓我來說, 最好的自動測試也許就是作一個產品專門使用你的產品, 但實務上相當不切實際.  試著考慮一個產品, 可能的架構是, 他使用了許多 Library, 如下圖的 OS/Driver/Platform 這塊. 程式本身提供了一些 Interface 來完成流程, 或者與使用者互動.  然後跟使用者互動時的圖形界面. 理論上 presentation 這一層之所以要切開就是為了讓 UI 可以頻繁的更動. 以寫一份自動測試的成本/ 效益而言, 過多對於呈現面的自動化無疑自討苦吃. 市面上有許多產品試著解決這樣的問題, 像是 selenium. 相較之下, 在 API 層作自動化, 可以保證作低限度的正確性. 而相較之下不易改變的 API 行為, 也會保證測試本身有較高的性價比. 
  • Write Test Tool, 輔助測試用工具. 這跟測試自動化有相關但我把他切成兩個部份, 因為目標不完全一致. 通常是幫助測試者完成冗長而不易完成的準備工作, 或者是使用一般狀況下無法碰觸到的情境 (高記憶體用量等等). 有些公司會有專屬的人作這些開發, 包括測試自動化; 但如果 QA 能負擔這些工作, 便能減少許多溝通造成的成本.
  • Test Process, 測試流程規劃, 一般來說是 Manager 以上的角色在做的工作, 如果你作的夠久也可能碰的到. 內容像是, 定義開發流程之中的測試工作.


測試所帶來的價值
  • 提供使用者經驗
  • 風險管理
  • 幫助釐清問題
前面兩個項目前面提過了, 我想談一下幫助釐清問題這件事. 作為一個測試人員, 除了發現問題以外, 很多的時間會花在重現問題, 而這是釐清問題的一個重要關鍵. 測試工程師不能只是對問題束手無策. 常用的作法是在 test case 中列舉, 經由交叉比對縮小問題點. 發現 root cause 這個工作如果在測試這邊就有足夠的資訊, 當問題交到開發工程師手上便會減少處理時花費的時間.
自動化在這個地方就扮演一個極其重要的角色.  如果 test case 設計時考慮到平行處理與容易程式化, 便能大幅縮短執行一個完整測試所需時間. 而兩個完整測試的間隔時間若縮短, 就可以縮小回歸 (regression) 問題所需翻查的 code/commit 數. 當發現問題與研究 root cause 的時間縮短, 可以想見的是品質將隨之提昇, 並且需要的開發時間也縮短了, 兩全其美?

測試是很重要的工作, 最重要的是不要把他作小了.

2012年11月14日

用 Mockito 的 injectMocks

官方網站上面沒找到, google 一下看到這篇 http://gladkowski.blogspot.tw/2011/06/mocking-objects-and-injecting.html

常常會遇到待測目標是用 @Resource, 或者其他方法拿到的, 測試的時候一般會想要排除這些依賴項目而嘗試寫假物件來提供更一致的行為; 這邊是要提用 Mockito 時候應該怎麼做.

首先必須 import 以下項目:


import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.runners.MockitoJUnitRunner;
import org.junit.runner.RunWith;




在你的test class 宣告前面放上

@RunWith(MockitoJUnitRunner.class)


假設欲測的 class 叫做 target, 需要 inject 的 resource 叫做 dependent; 那麼在 class 的 scope, 可以宣告


@Mock
private Dependent dependent;
@InjectMocks
Target target = new Target();


之後你就可以跟原本一樣使用 dependent 來達成測試的需求了, 例如


when(dependent.func(anyString()).thenReturn("Hello");
        assertEquals("Hello", target.getStringFromDependentFunc());