neo4j browser执行脚本后不提示用时_还不懂什么是分层自动化测试的,有赞的实践经历告诉你...
#? 背景
先理一下自動化測試的概念,從廣義上來說,一切通過工具(程序)的方式來代替或者輔助手工測試的行為都可以成為自動化。從狹義上來說,通過編寫腳本的方式,模擬手工測試的過程,從而替代人工對系統的功能進行驗證。
有贊是一家互聯網行業的創業公司,測試起步較晚,發布非常頻繁,就算每次只回歸核心功能,對人數極少的幾個測試人員來說工作量巨大,且基本是重復勞動,極其枯燥,持續時間長了也容易出錯。
所以初期我們測試自動化切入的思路非常簡單:從實際用戶的角度出發,模擬真實的操作,替代現有的手工測試用例的執行。這樣一來,每次重復的工作就可以用自動化來替代,測試人員只需要關注每次發布的增量需求即可。
隨著腳本數量的增加,這種自動化覆蓋的方式的弊端也逐漸暴露:
執行效率低下
構建成功率低(誤報率高)。
受前端樣式變更影響大
外部依賴較多,不是所有用例都能自動化
覆蓋能力有限
雖然我們在測試框架和工具層面通過結合 selenium-grid 實現了腳本并發執行和失敗用例重試機制以提高執行效率和降低誤報率,但是這種方式只能緩解問題,并不能從根本解決覆蓋不全的問題。
正好趕上公司的 SOA 服務化進程,測試這邊也開始配合的做自動化方面的轉變,從原來的黑盒系統級自動化測試向分層自動化測試轉變。
# 分層自動化測試
在談分層測試之前,先回顧幾個概念:
單元測試:對軟件中的最小可測試單元進行檢查和驗證。
具體的說就是開發者編寫的一小段代碼,用于檢驗被測代碼的一個很小的、很明確的功能是否正確。通常而言,一個單元測試是用于判斷某個特定條件(或者場景)下某個特定函數的行為。
集成測試:集成測試是在單元測試的基礎上,測試在將所有的軟件單元按照概要設計規格說明的要求組裝成模塊、子系統或系統的過程中各部分工作是否達到或實現相應技術指標及要求的活動。
也就是說,在集成測試之前,單元測試應該已經完成。這一點很重要,因為如果不經過單元測試,那么集成測試的效果將會受到很大影響,并且會大幅增加軟件單元代碼糾錯的代價。
系統測試:將需測試的軟件,作為整個基于計算機系統的一個元素,與計算機硬件、外設、某些支持軟件、數據和人員等其他系統元素及環境結合在一起測試。
系統測試的目的在于通過與系統的需求定義作比較,發現軟件與系統定義不符合或與之矛盾的地方。
接下來我們談談有贊是如何隨著系統拆分 SOA 服務化推進分層自動化測試的。在經典的測試金字塔中:
其中 Unit 代表單元測試,Service 代表服務集成測試,UI 代表頁面級的系統測試。分層的自動化測試倡導產品的不同層次都需要自動化測試,這個金字塔也正表示不同層次需要投入的精力和工作量。
下面逐層介紹有贊的分層自動化實踐。
1、Unit-單元測試
在系統拆分之前,有贊只有一個龐大的巨無霸系統,單元測試極度缺失。在系統逐漸SOA服務化的過程中,我們逐漸提出了對單元測試覆蓋率的要求。
我們的單元測試會分別做DAO層和服務層的測試。DAO層的單元測試主要保障SQL腳本的正確性,在做服務層的單元測試時就可以以DAO層是正確的前提進行用例編寫了。
為了做細粒度的測試,需要解決單元測試的外部依賴。系統和模塊之間的依賴可以通過Mock框架(Mockito/EasyMock)解耦,同時可以結合h2database解決對數據庫的依賴,使得測試用例盡可能做到可以隨時隨地運行。
這一層發現并解決問題付出的成本相對來說最低,自動化用例的維護成本也不高,總的來說自動化測試的投入產出比最高。
單元測試的責任主體一般來說是開發人員,寫單元測試也是開發人員對自己的代碼進行檢查的一個過程。
2、Service-服務集成測試
我們在服務層的測試首要考慮的是各系統(子系統)的集成測試。因為在經過單元測試這一層的保障之后,在服務層我們更關注的是某個系統的輸入輸出功能是否正確,以及若干個系統間的交互是否和業務場景的要求一致。
先來看看我們系統拆分之后的SOA系統應用架構圖:
展現層:老的 Iron 應用,代碼為 php。拆分之后 Iron 只剩下和前端交互的展現層邏輯,以及調用核心業務的 API層。
核心業務:Iron 系統拆分出來的核心業務。
這一層的被測對象是抽離了展現層的代碼(前端以及部分后端展現層邏輯)。
鑒于有贊的測試起步較晚(應該很多創業公司都有類似情況),測試資源緊缺,代碼覆蓋率低得可憐。所以我們的初期自動化用例覆蓋策略是這樣的:
從老的 Iron 應用的 API 接口作為業務場景覆蓋的切入點
優先覆蓋核心業務的場景
配合系統拆分,優先覆蓋拆分出去的系統
已拆分出去的系統,做好系統服務層的測試覆蓋(全面覆蓋該服務的接口)
測試依賴的數據準備優先選擇調用系統接口的方式(為了增加業務覆蓋面)
測試方式逐漸從黑盒向灰盒/白盒轉變
這樣做的好處是,可以快速增加業務場景的覆蓋面,同時事先準備好的 API 接口用例,可以作為系統拆分后的冒煙測試用例,起到核心老功能的回歸作用(只是做系統拆分,業務邏輯以及對展現層暴露的接口行為不變)。
畢竟在自動化測試的過程中,最怕的就是變化,會帶來更多的腳本維護工作,而以這種方式覆蓋的用例,目前來看維護成本很低。
再介紹一下這一層的初期我們用例的基本形態:
專注于業務場景,和 UI 腳本一致,只是腳本從操作頁面變成了調用接口。相對于 UI 自動化,服務層的接口測試更加穩定,測試用例也更容易維護。服務層接口測試可以更關注與系統整體的邏輯(業務)驗證,而 UI 自動化則會轉變為頁面展示邏輯及界面前端與服務的集成驗證(這個在 UI 層會介紹)。
暫時不做系統間的 Mock。更多的考慮系統之間的耦合和依賴。
搭建 MockServer 解決系統的外部依賴,主要是類似于支付等第三方系統(關于我們的 MockServer 會有專門的文章介紹)。
結合我們的交易系統舉個例子:比如交易系統會依賴于商品和營銷活動,那我們的下單場景的用例會依次調用商品和營銷這幾個系統的 API 構造數據作為用例的前置條件,然后按照下單的業務場景調用交易系統的下單接口,校驗返回值以及寫入 DB 的數據,最后做好數據清理的工作。
我們在這一層的測試框架選擇是基于公司通用的服務框架(Nova)基礎之上搭建的,架構圖如下:
BIT :服務接口集成測試(Business Interface&Integration Test)
SUT:被測系統(System Under Test)
Validator:各個業務的數據庫結果驗證封裝
Mock:用例前置條件依賴的數據Mock服務
HttpClient:根據IRON系統的接口封裝了返回通用的RPCResult對象
Util:常用工具類封裝
Biz:在此封裝了所有被測系統對外暴露的接口,供測試用例直接調用
TestCase:我們服務接口測試又分為SDV(System design Verify-系統設計驗證)和SIT(System Integration Test-系統集成測試)。按照上面提到的用例覆蓋策略,我們是在系統拆分之前,先根據該系統的業務場景和REST接口補充核心的接口集成測試用例,后續可以作為系統拆分之后的冒煙用例。在系統拆分之后,詳細補充該系統的測試用例,粒度更細。
Facade:結合了Nova框架,對外發布各個業務的數據構造的REST接口,同時可以作為測試數據構造系統,輔助測試人員的手工測試。
這一層的測試覆蓋主要是由測試人員進行,是測試人員大展身手的地方。
我們不需要非常詳細的了解代碼的實現,但是我們的用例里充分體現了我們對系統的結構,模塊之間關系等的充分的理解。
后續我們對于 Service 層自動化測試的推進策略是:
逐漸豐富 SDV 層的測試用例,并且在一定程度上進行用例依賴的系統的解耦,比如數據構造從調用接口向直接往數據庫寫入數據轉變。
逐漸細化拆分業務場景,做好用例的解耦。
優先做場景覆蓋,之后再考慮代碼覆蓋。
3、UI-展現測試
先提一個問題,既然在文章開篇提到了 UI 自動化測試有這么多弊端,這么勞民傷財,那么是否還有必要進行 UI 層的自動化呢?
答案是肯定的,因為 UI 層是產品最終呈現給用戶的東西。所以在做好上面兩層的測試覆蓋之后,測試人員可以投入更多的精力到 UI 層的測試上。正是因為測試人員會在 UI 層投入較大精力,還是有必要通過自動化來幫助解放部分重復勞動力。
根據我們的 UI 層自動化實踐,提一下 UI 層自動化覆蓋的原則:
能在底層做自動化覆蓋,就盡量不在 UI 層做自動化覆蓋
只做最核心的功能的自動化覆蓋,腳本可維護性盡可能提高
提高 UI 腳本可維護性的方法是遵循 Page Object 設計模式。
Page Object
Page Object 模式是為了避免在測試代碼中直接操作 HTML 元素,對 Web 頁面的抽象。好處有:
減少測試代碼的冗余
提高測試代碼的可讀性和穩定性
提高測試代碼的可維護性
一個簡單的例子
以有贊首頁的登錄操作為例(Ruby):
class LoginPage include HeaderNav def login(account, password) text_account.wait_until_present.set(account) text_password.set(password) button_login.wait_until_present.click return MainPage.new(@browser) end private def text_account @browser.text_field(:name => 'account') end def text_password @browser.text_field(:name => 'password') end def button_login @browser.button(:class => 'login-btn') endend123456789101112131415161718192021public 方法對外暴露頁面的服務,對于登錄頁面來說就是登錄行為
頁面的 UI 細節設為 private 方法對外隱藏
跳轉到新的頁面后在此方法中 return 之后的頁面的對象,比如登錄之后跳轉到首頁(MainPage)。甚至同一頁面也可以返回 self 做鏈式操作。
各個頁面的公共部分,如頁面頂部導航,可以封裝成 Module 供各個頁面對象直接 include
下面我們來看看測試用例:
class TestLogin < Test::Unit::TestCase def testLogin @browser = Browser.new @browser.goto 'youzan.com' main_page = @browser.login_page.login('xx', '123') #斷言 endend12345678這樣最終的測試腳本呈現的就是單純的頁面操作邏輯,更貼近文本測試用例。
下面來看一下我們的測試框架:
Base:這一層和大多數 UI 測試框架大同小異,使用的是 selenium 和 watir,用例管理方面并沒有使用 Ruby 領域炙手可熱的 BDD 框架 cucumber,而是最基本的單元測試框架 MiniTest。同時還引入了 ruby 的多線程包,配合 UI 腳本的并發執行。
Actir:我們自己封裝的測試框架。
Initializer:自動按照約定的工程結構加載所有的 ruby 文件,并根據 Page 的類名和反射自動生成了所有頁面類的對象實例。
UA:封裝好測試需要的瀏覽器U ser-Agent。
Executor:用例執行器?;?ruby 的多線程包以及 selenium-grid,實現了所有用例的調度及分布式執行,可以一定程度上大大提升 UI 腳本的執行效率。執行器還包括了失敗用例重試機制。
Util:工具類,包括了配置文件讀寫、數據驅動等。
Report:根據 UI 測試腳本執行的最終結果(失敗重試的用例以最終的結果為準)自動生成 HTML 格式的測試報告。
Cli:根據 Actir 框架的上述功能,封裝出的命令行工具,方便持續集成。
Project
Pages:基于 PageObject 模式包裝出的頁面的對象
Components:各個頁面的公用的部分或者插件,如圖片上傳、地址選擇等。包裝成 Module 供各個頁面對象需要時直接include。
Item:根據系統業務抽象出的對象,如訂單、優惠券、商品等
User:根據系統業務抽象出的角色及其Action,如買家的購買行為、買家的退款、發貨等。
隨著服務層自動化覆蓋率越來越高,UI層的自動化覆蓋會逐漸轉變為頁面展示邏輯及界面前端與服務的展現層交互的集成驗證。我們后續對于UI層自動化的演進規劃是這樣的:
依賴環境的 Mock,解除UI腳本的外部依賴
完善的數據準備,可以通過后端服務接口的 mock 使 UI 自動化更關注頁面業務邏輯的自動校驗。
頁面截圖比對校驗 UI 樣式。
UI 層的自動化測試也是由測試人員負責,在覆蓋了核心業務核心場景之后,不應該在這層的自動化覆蓋上投入太多的精力和資源。
就算我們在一定程度上提高了腳本的可維護性,可是畢竟自動化測試最怕的就是變化,而UI界面是變化頻率最高的一層,所以還是得投入一定的精力維護,不是么?
# 持續集成
有了上述各層的自動化測試腳本,下面我們需要建立起持續集成體系。持續集成的目的:
流程自動化,提高工作效率
最大化自動化測試腳本的價值
我們的持續集成是基于 Jenkins 搭建的,主要的動作如下:
代碼提交自動執行單元測試
單元測試通過后自動部署整體的環境
自動執行集成自動化測試(Service/UI)
自動生成構建的詳細測試報告,同時自動通知相關人員
持續集成所需的支撐有:
測試環境自動部署腳本
代碼覆蓋率自動收集
Java 應用:基于 JaCoCo+Jenkins 插件的方式
php 應用:通過 Xdebug+phpunit 的方式
測試報告相關插件及腳本
代碼靜態檢查等
對于持續集成我們后續的演進規劃是朝著持續交付和持續部署的方向努力,在持續集成的基礎之上,自動將代碼部署到測試環境上方便測試人員進行手工測試。
# 總結
本文主要從整體上介紹了在有贊 SOA 化的進程中,測試推行的分層自動化實踐,以及后續的發展方向,同時簡單介紹了相關的測試框架結構。下面再從整體回顧一下我們的分層自動化的要點:
單元測試:
優先級最高
粒度最細、覆蓋面最全
開發實施
服務測試
對測試來說優先級最高
從業務場景的角度切入
系統外部接口100%覆蓋
關注系統間的依賴和調用
測試實施
頁面測試
優先級相對最低
只保證核心功能的自動化覆蓋,只關注UI層的問題
通過數據mock的方式減少對后臺數據的依賴。
測試實施
至于各層投入的具體比重,還是需要根據項目的需求來實際規劃。在《Google 測試之道》一書,對于 Google 產品,70%的投入為單元測試,20%為集成、接口測試,10% 為UI層的自動化測試。
最后再提一些觀點吧:
越底層的自動化,收益越高
質量不是測試人員一個人的事情
自動化測試的目的不是為了減少手工測試,而是為了測試人員做更多更有意義的手工測試(end)
?往期推薦?
?
- 轉給你的老板,如何給程序員更少的薪水?
- 20年3月數據庫排行榜
- v2ex:飛機上用的是什么操作系統?
點擊
總結
以上是生活随笔為你收集整理的neo4j browser执行脚本后不提示用时_还不懂什么是分层自动化测试的,有赞的实践经历告诉你...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言scanf函数隐藏的缓冲区,零基础
- 下一篇: wps中图片怎么居中_wps图片怎么添加