題外話
測試入門
很多受過高等教育的大學生經常問要不要去報測試培訓班來入門測試。
答案是否。
高等教育的合格畢業生要具備自學能力,如果你不具備自學能力,要好好地反省一下,爲什麼自己受了高等教育迷戀於各種入門級別的培訓?是沒有毅力還是不知道學習方法?
沒有毅力的話,要自己多看些勵志的書,多想想社會的殘酷,親人的失望等來勉勵自己,畢竟企業多半也不會喜歡懶散的人的。
不知道學習方法的話,可以去知乎上看看,有些地方是回答得挺好的。簡而言之,讀《軟件評測師教程》(國內軟件評測師教材),《Software Testing Foundations 4th》(強烈推薦 國外測試認證ISTQB教材),《谷歌測試之道》是通常比培訓機構更好地入門測試。這些測試入門書籍可以在 qq羣144081101 567351477的共享找到。
我身邊碰到比較有水平的軟件測試,沒有一個是什麼_石、_testing、_林、_鳥、*內等入門測試的。而且這些機構經常打着包就業的名義騙人去培訓,培訓的老師通常口才很好,善於包裝,但是關鍵的一點,這些老師多數自己都不是合格的測試。培訓完之後有些學生重學幾次又無法就業,甚至出現學生和培訓機構對簿公堂的情況(這種情況通常是培訓機構敗訴,如果你身邊有這樣的被騙朋友可以建議他們先交涉不行再找律師保護自己)。
實體培訓業尤其成爲打着就業的幌子進行行騙的重災區,導致現在主流企業一看到有某些機構經歷的簡歷直接連面試機會都沒有了。
當然不是一棍子打死所有的測試培訓,比如斯特沃克的培訓,google的gtac等分享是做得相當不錯,建議自己先對測試有一定的瞭解,瞭解測試培訓授課老師的水平之後再選擇培訓,儘量自學爲主,在身邊找有經驗的實際測試人員稍微帶下。
測試的方向整體是功能測試的工作崗位逐漸減小。facebook就沒有測試人員,google也沒有專職的功能測試,功能測試由開發、產品、用戶等分擔會降低溝通等成本。未來的測試人員更加需要開發技能。
對於太極,推拿之類的,視頻是一個很好的學習方法。但是對於軟件自動化測試,最好的學習方法不是聽課,也不是看視頻,而是在有經驗的專業人士指導下進行項目實戰、發現問題、解決問題。實戰實戰再實戰!
本人曾在公司項目中曾手把手教剛畢業的毫無編程基礎的技校生接口、性能、自動化等測試,結果3個月之後他們都跳槽,薪水從4k漲到10k以上(2015年)。
自動化測試進階
IT主要技術體現爲英文,要想提升到比較高的水平,必須要有流利的英文閱讀能力。
搜索引擎方面要珍惜生命,遠離競價排名,做個有良知不受騙的人,從不用死不悔改的*度開始,優選google,其他的還有 必應 雅虎, 很多QQ羣還有免費fanqiang工具。google的搜索通常能直中目標,stackoverlow的回答通常是首選方案。
選擇有水平的業內人士幫助是掌握linux、python和測試基礎之後一個迅速提升的方法。
自動化測試的層次
從圖看出自動化儘量以單元、接口爲主,如果你有志在自動化測試深入,還在死磕QTP,selenium等的話,建議看下pytest、pexpect、API測試、單元測試等。
腳本
1-1 不要在實際項目中使用錄製和回放
大多數自動化工具(特別是商業工具)具有記錄和播放功能,這個功能的表面簡單,實際是一個衆所周知的陷阱。錄製和回放在廣告視頻和演示文稿中看起來非常棒。但錄製的腳本不使用變量,循環和條件。自動創建的程序和函數的名稱通常不直觀,通常所有操作都錄在一個函數中(可能很大),執行不穩定,維護成本也高。
- 錄製和回放適用點
- 在學習自動化工具
- 不重用的工作
- 很難識別和處理的控件
1-2 不要使用暫停
暫停,比如python中的:
:::python
import time
time.sleep(5)
定義全局變量可以避免大量代碼修改,如下
WAIT_TIME = 5
...
time.sleep(WAIT_TIME)
上述等待不利於快速執行,較快出現的控件同樣需要常見等待。等待對象或對象屬性是更好的選擇,比如selenium中的顯式等待:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
又如selenium中的隱式等待:
from selenium import webdriver
driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")
以WebDriverWait一定的時間間隔檢查對象的存在(例如每秒一次),如果象出現對,則返回true。如果對象在timeout參數指定的時間內沒有出現,則返回false。因此,如果控件一秒鐘內出現,那麼等待時間將會是 1秒。
當然短時間的等待,有時也是必要的,比如降低CPU使用率,短時間等待狀態改變等。
1-3 在循環中超時退出
以常量的形式定義類似超時。例如定義兩種類型的短超時(3秒)和長超時(3分鐘)。
1-4 不要將自動化測試完全等同於開發
然自動化需要編程技巧,但它通常不是完整的開發項目。自動化常由初級程序員開發,因爲工作簡單得多,並一般爲內部需求。在99%的情況下不需要大多數設計模式。在使用數據庫時不會使用事務。測試數據量一般不會很大。
代碼要力求簡單,快速開發。即使使用了行爲驅動開發(BDD:behavior-driven development)或關鍵字驅動的測試(KDT:keyword-driven testing)等方法也要儘量保證代碼簡單。
1-5 不要寫複雜的代碼
在使用條件和條件時,儘量遵循“不超過三個嵌套級別”的規則。
代碼嵌套超過三層非常難以調試。寧肯代碼多重複也不要嵌套超過三層。
1-6 驗證邏輯條件的所有選項
if A and B or C:
# if (A and B) or (C and D)
定要檢查這些代碼的每個條件(在這個例子中的A,B,C)和所有可能的True和False。添加括號能增加可讀性。
1-7 使用編程規範
初學者通常不太關注變量和函數的名稱使用任何規則。儘管如此,幾乎所有的語言都有所謂的編碼標準。比如python的PEP8, google的編程規範。
在大項目中這些標準成爲強制性規則,方便互相理解代碼。
1-8 使用靜態代碼分析器
對於流行的編程語言,有特殊的代碼分析器。例如Python的pylint,JavaScript語言的jslint等。
特別指出對python這樣的動態類型的語言,這個更加重要。
pylint通常有很多誤報,但是mypy的檢查則比較實用。參考:python代碼分析和lint。
1-9 隨機
比如打開菜單有快捷鍵、下拉菜單、圖標等多種方式,儘量寫方法隨機調用各種方式。以求覆蓋各種場景,不過要記得添加日誌以便跟蹤錯誤。
1-10 不要使用座標
非標準控件儘量不要使用座標,可以用圖像識別的方法:
Window.Toolbar.Click(135, 15)
替換爲:
toolbar_click_button_by_image(Window.Toolbar, "Button Caption")
1-11 學習和使用庫
比如:
full_name = '{0}\\{1}'.format(file_path, file_name)
在linux上就比較尷尬,可以替換爲:
full_name = os.path.join(file_path, file_name)
1-12 避免複製和粘貼
複製的代碼維護成本很高,儘量提取爲公共庫。
1-13 異常捕捉到具體的類
異常通常是程序考慮不周到纔會發生:
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except Exception as e:
pass
上述捕捉所有異常並忽略異常的代碼通常只在臨時代碼中使用。通常也要把異常異常信息顯示出來。比如
import sys
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except Exception as e:
print e
for item in sys.exc_info():
print item
又如:
import traceback
import cv2
import numpy as np
def raw2jpg(filename, height=480, width=640):
try:
img = np.fromfile(filename, dtype=np.uint16)
img = img.reshape( (height, width) )
img.astype(np.float)
img = np.sqrt(img)
img = img * (255 / img.max())
#img.astype(np.uint8)
cv2.imwrite(filename+'.jpg', img)
except Exception as info:
print('Error: {}'.format(filename))
print(info)
traceback.print_exc()
return False
return True
更佳的方式是捕捉到具體異常:
try:
x = input('Enter the first number: ')
y = input('Enter the second number: ')
print x/y
except ZeroDivisionError as e1:
print("ZeroDivisionError")
except TypeError as e2:
print("TypeError")
另外一種異常處理方式:
far = 0 if not no_number else far_number/float(no_number)
1-14 代碼與數據分離
對於小數據集可以使用數組或列表。大數據可以使用數據驅動測試(DDT:data-driven testing)。數據源可能爲數據庫,Excel或CSV文件等。
注意點:
-
以讀模式打開數據文件。
-
每列只存儲一種類型的數據。在數據庫的情況下,
-
用完關閉與數據源
-
數據文件中不要用空行
1-15 調試
簡單的可以多使用print或者logging打印一些信息。更高級的內容有
•斷點 •單步執行 •查看本地和全局變量的值 •觀察變量和表達式
1-16 不要爲未來編寫代碼
項目的變化是很頻繁,可以做一些自動化測試的技術預研,但一般不要書寫有些只供未來使用的代碼。
1-17 讓代碼更好
在不影響性能的情況下提高可讀性。
1-18 測試選擇適當的語言
•很重要:語言上手的難易程序和流行度及庫支持。一般而言python因爲其容易上手、是膠水語言(與其他語言調用方便)、語法簡潔、維護成本低、方便調試,是目前自動化測試佔有率最高的首選語言。但是c#在windows平臺、java、c++等也有一定的市場。雖然python的佔有率最高,但是一定要考慮到有些自動化測試開發可能已經有c++,go,java之類的現成的工具。 •儘量不要產生新的編程語言。 •諮詢開發 •可以和開發採用同一種語言,尤其是單元測試,一般爲採用和開發一樣的語言。 • 簡化API測試等其他原因
值得注意的是TCL(Tool Command Language)早起因爲expect的命令自動化擁有一定的名聲,且testcenter、smartbits等儀表一度不支持python等主流語言。但是TCL的語法晦澀,功能弱小,是能不用就不要去用的語言。
參考資料: 編程流行度 tiobe
1-19 使用變量前要初始化
這個在python中可以用mypy檢查。
測試最佳實踐
2-1 不要實現被測應用的功能
因爲:
•計算和邏輯可能很複雜,且開發已經實現了 •計算和邏輯可能會更改 •使用浮點數的精度可能和語言有關。
白盒和灰盒測試中一般是知道輸入和預期結果就好,不要知道具體內部實現得的過程。
例外:大數據、搜索引擎中間算法等不明確預期結果的測試,經常用python快速實現一遍,與開發用c++等語言實現得結果進行比對。
2-2 測試的獨立性
2-3 哪些不應該自動化
主要是基於成本考慮
•難以維護的自動化。 •儘量多做單元測試和接口測試的自動化,少做UI層的自動化 •重複使用次數不多的自動化
有些手工不能做的必要測試,即便自動化的成本很高,也是需要自動化。
2-4 向開發人員尋求幫助
開發在具體的開發方面可以值得學習,但是在自動化測試很方案方面自己定奪比較好。比如結果驗證,開發大多喜歡直接從數據庫中讀數據,但是實際上展示數據庫數據的應用也是可能出問題的。
2-5 雲測試
雲測試
•要測試桌面應用程序,必須打開會話,操作系統是否支持 •硬件相關的測試雲測試支持並不方便。 •移動設備的雲服務通常比較貴 •Web應用程序的自動化比較適合在雲中執行。 •手機兼容性的測試可以考慮雲,功能自動化測試則不用雲比較好。
2-6 充分利用邊界值和等價類
2-7 錯誤與警告
注意區分自動化測試平臺或工具的錯誤和被測應用的bug。
2-8 使用合適的技術
在測試自動化中使用了許多特定的方法:ODT,DDT,KDT,BDD,頁面對象,基於模型的測試等等。比如那麼對KDT一般需要一部分寫測試平臺,一部分寫測試庫,一部分寫測試用例。
2-9 特殊錯誤的驗證
可以書寫一個臨時的測試來處理某些特定的bug。
2-10 在寫真實測試之前做POC
環境
軟件測試自動化中有兩種主要的環境類型。一個創建和調試測試,另一個用於運行測試。
3-1 爲您的需要選擇一套適當的工具
以接口自動化測試爲例,一些團隊,執着的認爲java是最好的語言,要用java去發HTTP請求,更有甚者,用jmeter去做接口自動化測試。不排除個別場景,這可能是合適的方式,但是通常的HTTP接口測試,用requests,代碼行數通常比java少一個數量級,還不用編譯。
python是主流語言中的膠水語言,和其他語言配合都比較完美,通常情況下是自動化測試的首選語言,但是python未必適用所有地方,還需要其他工具和語言進行補充,不過不要太多,學習很多語言也是一件痛苦的事情。
現在還有很多培訓機構在鼓吹UI自動化就是自動化測試的全部,一說自動化就是QTP,一問Selenium,Testcomplete之類的都不知爲何物,更不用說什麼junit,pytest之類的了。
3-2 慎用自動提交bug
配置錯誤,測試代碼錯誤經常導致測試失敗。
測試代碼有時難以描述清楚測試步驟
注意不要提交重複的bug。
在沒有十足的把握的情況下可以用半自動的方式,發送郵件給測試人員,然後又測試人員提交bug。
3-3 不要使用欺騙的結果
避免註釋測試代碼的問題部分或改變預期的結果,以便測試不會出現失敗。
如果實在用禁用,要知道禁用用例的比例,後面定期檢查修改。
3-4 熟練使用工具
比如wingide中Ctrl + \爲註釋代碼的快捷鍵
3-5 使用版本控制系統
避免文件丟失,方便協作,儘快使用hg、git之類的。
3-6 避免自定義表單
本來自動化就是爲了把頁面的東西儘可能走後臺,你爲了取悅領導(附:大陸目前多數測試領導是不太合格的)還是什麼原因,搞成形式主義了。
參數可以用配置文件等方式。
3-7 自動化所有能自動化的東東
比如:測試,代碼,測試環境,虛擬機,SQL查詢,測試數據,報告等等
運行,日誌記錄,驗證
4-1 儘可能經常運行腳本
4-2 測試失敗時重新執行
當出現錯誤時應用程序運行很長一段時間,或特定情況下要儘量定位問題。
一般而言失敗的測試先記錄下來,所有測試執行完之後在重新執行一次。
4-3 豐富的日誌內容
錯誤日誌儘量包含:預期值,實際值,地點和操作。
參數儘量用引號等括起來,以免把包含空格的參數當成多個參數。
4-4 截圖
UI測試必要的時候可以截圖,同時處理好滾動。
4-5 儘量避免比較圖像
審查
審查是保持碼清晰易懂的好方法,要做代碼的互相評審。
5-1 讓非自動化者也可以看懂代碼
def test_login(url, user, password, text):
open_page(url)
login_as(login=user, password=password)
verify_page_opened(text)
5-2 避免不必要的優化
在開始執行任何優化之前如需要慎重考慮。
通常不需要的優化工作看起來像這樣:
1.應用程序啓動3秒鐘,然後進行5秒鐘的測試腳本填充搜索字段,還有5秒鐘搜索過程,之後腳本用1秒鐘讀取找到的數據並進行驗證。 2.測試人員開始優化讀取和驗證 3.測試人員花費一天時間進行優化並達到目標:閱讀和閱讀每次運行時間爲半秒
事實上,測試工程師的代碼生產力已經翻了一番,但是結果是他整體方案取得了約5%的收益。花一天時間是不值得的。一般需要綜合考慮,涉及腳本、被測應用、環境、執行頻率等。
建議你在兩種情況下優化測試:
•如果測試運行時間過長,並且測試的應用程序是在測試執行期間空閒。 •如果您在代碼中看到明顯的問題,請更正其中的問題。
pandas大數據分析性能優化實例-read_csv引擎和分組等,這裏是一個必要的優化實例。
5-3 定期審查別人的代碼
定期審查別人的新代碼。可以結對編程,甚至是同時一個人寫,一個人看。
5-4 參與論壇和討論
如果您是自動化領域的初學者,並且在自動化團隊中工作,那麼會從你的同事那裏學到很多東西。如果你是唯一的自動化工程師在公司或你的部門沒有人能幫助你?
知乎,特別是stackoverflow等社區常常可以找到自己問題滿意的答案。同時試圖幫助別人也可以擴展自己的眼見。
5-5 執行重構
重構是對現有代碼的簡化,功能和應用程序不會改變。儘管測試自動化中的代碼通常很多實際應用更簡單,有時候你仍然需要重構。
•您可能會發現您所支持的代碼太複雜。 •可能有編寫新測試的請求,需要修改代碼 •可能需要重構來改進已編寫的代碼
重構後可以執行所有測試來驗證,也可以在公共庫等地方添加必要的單元測試。
5-6 刪除低收益的測試
•測試執行了多少次; •測試發現了多少實際問題; •測試需要多久進行一次維護。