[雪峰磁針石部落格]軟體自動化測試初學者忠告

書籍尋找發表於2018-08-15

題外話

測試入門

很多受過高等教育的大學生經常問要不要去報測試培訓班來入門測試。

答案是否。

高等教育的合格畢業生要具備自學能力,如果你不具備自學能力,要好好地反省一下,為什麼自己受了高等教育迷戀於各種入門級別的培訓?是沒有毅力還是不知道學習方法?

沒有毅力的話,要自己多看些勵志的書,多想想社會的殘酷,親人的失望等來勉勵自己,畢竟企業多半也不會喜歡懶散的人的。

不知道學習方法的話,可以去知乎上看看,有些地方是回答得挺好的。簡而言之,讀《軟體評測師教程》(國內軟體評測師教材),《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和測試基礎之後一個迅速提升的方法。

  • 技術支援qq群: 144081101(後期會錄製視訊存在該群群檔案) 591302926 567351477 釘釘免費群:21745728

自動化測試的層次

testing_automation_tips1.png

從圖看出自動化儘量以單元、介面為主,如果你有志在自動化測試深入,還在死磕QTP,selenium等的話,建議看下pytest、pexpect、API測試、單元測試等。

指令碼

1-1 不要在實際專案中使用錄製和回放

大多數自動化工具(特別是商業工具)具有記錄和播放功能,這個功能的表面簡單,實際是一個眾所周知的陷阱。錄製和回放在廣告視訊和簡報中看起來非常棒。但錄製的指令碼不使用變數,迴圈和條件。自動建立的程式和函式的名稱通常不直觀,通常所有操作都錄在一個函式中(可能很大),執行不穩定,維護成本也高。

  • 錄製和回放適用點
    • 在學習自動化工具
    • 不重用的工作
    • 很難識別和處理的控制元件

1-2 不要使用暫停

暫停,比如python中的:

#!python

import time

time.sleep(5)

定義全域性變數可以避免大量程式碼修改,如下

#!python

WAIT_TIME = 5
...
time.sleep(WAIT_TIME)

上述等待不利於快速執行,較快出現的控制元件同樣需要常見等待。等待物件或物件屬性是更好的選擇,比如selenium中的顯式等待:

#!python

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中的隱式等待:

#!python

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 驗證邏輯條件的所有選項

#!python

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 不要使用座標

非標準控制元件儘量不要使用座標,可以用影像識別的方法:

#!python

Window.Toolbar.Click(135, 15)

替換為:

#!python

toolbar_click_button_by_image(Window.Toolbar, "Button Caption")

1-11 學習和使用庫

比如:

#!python

full_name = `{0}\{1}`.format(file_path, file_name)

在linux上就比較尷尬,可以替換為:

#!python

full_name = os.path.join(file_path, file_name)

附: python自動化測試開發庫

1-12 避免複製和貼上

複製的程式碼維護成本很高,儘量提取為公共庫。

公共測試庫示例

1-13 異常捕捉到具體的類

異常通常是程式考慮不周到才會發生:

#!python

try:
    x = input(`Enter the first number: `)
    y = input(`Enter the second number: `)
    print x/y
except Exception as e:
    pass
    

上述捕捉所有異常並忽略異常的程式碼通常只在臨時程式碼中使用。通常也要把異常異常資訊顯示出來。比如

#!python

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
    

又如:

#!python

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 
    

更佳的方式是捕捉到具體異常:

#!python

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")

另外一種異常處理方式:

#!python

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 讓非自動化者也可以看懂程式碼

#!python

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 刪除低收益的測試

•測試執行了多少次;
•測試發現了多少實際問題;
•測試需要多久進行一次維護。

參考資料


相關文章