Google軟體測試介紹2章軟體測試開發工程師
我於2001年以工程總監的身份加入Google。當時,Google大概有200名開發人員,但只有區區3位測試人員!那個時候,開發人員已經開始做自己程式碼的測試了,但由於測試驅動開發的模式才剛剛開始,而且像JUnit這樣的測試框架也沒有大規模使用。當時的測試主要是在做一些隨機測試(ad-hoc testing),其好壞取決於編寫程式碼的開發者的責任心。但即使那樣也是可以接受的,因為,當時正處在創業階段,必須快速前進並勇於冒險,否則就無法和那個時代已經非常強大的對手競爭。
然而,當Google逐漸成長變大,Google的一些產品對於終端使用者和客戶來說開始變得至關重要(例如,競價廣告產品,我曾經負責的產品,很快變成許多網站的主要收入來源),我們清晰地認識到必須加大對測試的關注和投入。但只有3個測試工程師,別無選擇,只能讓開發來做更多的測試。與其他的幾個Googler(譯註:Google員工,本書中一般指Google工程師)一起,我們介紹、培訓、推行單元測試,我們鼓勵開發人員把測試作為優先順序較高的事去做,並建議使用一些工具,如JUnit,把測試做成自動化的。但是進展緩慢.
開發人員發現,為了測試充分,他們不得不針對每一行功能程式碼,寫兩到三行的單元測試程式碼,而且這些測試程式碼和功能程式碼一樣都需要維護,且有著相同的出錯概率。而且大家也意識到,僅做單元測試是不夠的,仍然需要整合測試、系統測試、使用者介面等方面的測試。當真正開始要去做測試的時候,會發現測試工作量變得非常大(且需要很多知識的學習),並要求在很短的時間內完成測試,要以"迅雷不及掩耳"之勢完成。
我們為什麼要在很短的時間內迅速地完成測試呢? 我一直這麼認為,對於一個壞點子或考慮欠周的產品,即便再多的測試,也無法把它變成一個成功的產品。但如果測試方法不當,卻會扼殺一個本來有機會成功的產品或公司,至少會拖慢這個產品的速度,讓競爭對手有機可乘。
- Patrick Copeland 谷歌測試和部署技術的架構師
我在Google的旅程始於2005年3月。Alberto在前面的序中也介紹了一些當時Google的狀況:雖然公司規模還比較小,但已開始感受到成長帶來的煩惱。當時適逢快速的技術變革之際,Web世界正在迎接動態內容的到來,而云計算也正在逐漸成為一種新的選擇,取代當時還佔統治地位的客戶機-伺服器架構
我加入Google的時候,工程團隊還不足1000人。測試團隊大概有50名全職人員和一些臨時工,具體數量我一直沒搞清楚。測試團隊當時的稱謂是"測試服務",工作重點在UI的驗證上,隨時響應不同專案的測試需求。可以想象,這並不是Google最閃耀的團隊。
但這在當時已經足夠了。Google當時的主要業務是搜尋和廣告,規模要比今天小得多,一次徹底的探索式測試足以發現絕大多數的質量問題。然而,世界在變,Web點選量開始史無前例地爆發性增長,文件化的Web正在讓位於應用化的Web。你可以感覺到勢不可擋的成長和變化,在這種情況下,規模化和快速進入市場的能力變得至關重要和生死攸關。
在Google內部,規模和問題的複雜性給測試服務團隊帶來了巨大的壓力。在之前小型的、類同的專案裡的一些可行做法,現在卻讓優秀的測試人員感到筋疲力盡,疲於奔命在多個急需救火的專案之間。更加火上澆油的是,Google在專案快速釋出方面的堅持。是時候採取措施了,我面臨兩個選擇,要麼沿用這種勞動密集型的流程增加更多的人手,要麼改變整個遊戲規則。為了適應業界和Google發生的鉅變,測試服務團隊需要根本性的變革。
我也很想說自己是藉助於豐富的經驗構思出了完美的測試組織模型,但實事求是地講,我從過去的經歷中,學到的只不過是一些過時的做法。我所工作或領導過的每個測試組織都有這樣或那樣的問題。有問題是常態,程式碼質量很糟糕,測試用例很差勁,團隊也問題多多。我完全清楚那種被技術質量債壓得喘不過氣來的感受,在那種狀態下,一切創新性的想法都會被遏制,以免不小心破壞了脆弱的產品。如果說我在以往的經歷中有所收穫的話,那就是經歷了各種錯誤的測試實踐。
那個時候,以我對Google的瞭解,有一件事情是確定無疑的,那就是Google對於電腦科學和程式設計能力非常重視。從根本上說,如果測試人員想加入這個俱樂部,就必須具備良好的電腦科學基礎和程式設計能力。
變革Google測試的首要問題是重新定位身為測試人員的意義所在。我過去經常在頭腦中想象理想團隊的模型,想象這樣的團隊是如何肩負起質量重任的,每次我都會得到相同的結論:一個團隊能編寫出高質量軟體的唯一途徑是全體成員共同對質量負責,包括產品經理、開發人員、測試人員等所有人。我認為,達到此目標的最好方式是使測試人員有能力將測試變成程式碼庫的一個實際功能,而測試功能的地位應該與真實客戶看到的任何其他功能同等重要。我所需要的能夠實現測試功能的技能,也正是開發人員需要具備的技能。
招聘具備開發能力的測試人員很難,找到懂測試的開發人員就更難,但是維持現狀更要命,我只能往前走。我希望測試人員能為他們的產品做更多的事情,同時,我希望演變測試工作的性質和從屬,要求開發團隊更大地投入。這種組織結構在當時的業界尚未實現,但我堅信它非常適合Google,我相信在這家公司,時機到了。
不幸的是,這種如此深刻、根本性的變革在公司裡極度缺乏認同,極少有人能分享我的激情。當我開始推銷這種關於軟體測試角色的地位平等而作用不同的願景時,我發現竟然難以找到一個人一起共享午餐!開發工程師們好像被他們將要在測試上發揮更大的作用這個想法嚇著了,他們指出"這是測試人員的職責"。而測試人員也不買賬,因為很多人已經習慣了當前的角色,維持現狀的慣性導致任何變革都變得非常困難。
我毫不鬆懈地繼續努力著,主要是出於對Google的研發過程深陷技術和質量債的困境的恐懼,一旦如此,長達5年的開發週期又會成為現實,而我本來已經很高興地把它們留在客戶機-伺服器的世界裡了。Google是一家由天才組成的公司,以創新為靈魂,這種企業文化與冗長的開發週期是不相容的。這是一場值得打的戰鬥,我說服自己,一旦這些天才理解了這種旨在打造一個生產線式的、可重複的"技術工廠"的開發和測試實踐 ,他們就會改變看法。他們就會理解我們不再是一個初創公司,快速成長的使用者群、不斷累積的bug和糟糕結構的程式碼形成的技術債將會導致開發過程的崩潰。
我逐個接觸各產品團隊,尋找優秀的案例,試圖為我的立論找到比較容易的切入點。在開發人員面前,我描繪了一個持續構建、快速部署的藍圖,一個行動敏捷、省下更多時間用於創新的開發過程;在測試人員面前,我激發他們對於成為同等技能、同等貢獻和同等薪酬的完全的工程合作伙伴的渴望。
開發人員的態度是,如果我們招聘到有能力做功能開發的人,那麼,我們應當讓他們做功能開發。其中一些人對我的想法非常反感,甚至發信給我的主管,非常直率地建議如何來處理我的瘋狂之舉,這些信塞滿了我的主管的郵箱。幸運的是,我的主管並沒有採納那些建議。
令我吃驚的是,測試人員的反應竟然與開發人員類似。他們沉湎於老的做事方式,抱怨自己在開發面前的地位,但又不想去改變。
我的主管對這些抱怨只有一句話:"這裡是Google,如果你有想法,儘管去做就是。"
於是我開始付諸行動。我召集了一批志同道合的骨幹分子,組成了一個面試團隊,開始招聘。事情進行得比較艱難,我們尋找的人要兼具開發人員的技能和測試人員的思維,他們必須會程式設計,能實現工具、平臺和測試自動化。我們必須對招聘和麵試的標準與流程做出一些調整,並向已經習慣了既有模式的招聘委員會做出合理解釋。
最初的幾個季度進行得異常艱難。好的候選人經常在面試過程中失利,也許是因為他們沒能很快地解決一些奇怪的程式設計問題,或是在某些人認為很重要的方面表現得不夠好(然而這些方面其實與測試技能毫不相干)。我預料到了招聘過程的困難,每週都要抽出大量時間寫辯詞。這些辯詞最終會到達Google聯合創始人Larry Page手裡(他一直是招聘的最終批准者)。他批准了足夠多的候選人,我的團隊開始穩步增長。直到現在,我猜每次Larry聽到我的名字時想到的一定是:"招聘測試的!"
當然,到這個時候,我已經做了大量的宣傳和鼓動工作,來說服大家這是唯一的選擇。整個公司都在看著我們,一旦失敗,後果將是災難性的。對於一個混合了很多不斷變化的外包人員和臨時人員的小測試團隊而言,期望顯得如此之高。然而,即使是在我們艱難的招聘進行中同時減少了臨時人員的數量時,我已經注意到了變化在發生。測試資源越稀缺,給開發人員留下的測試工作就越多。很多團隊都勇敢地接受了挑戰。我感覺,如果技術保持不變的話,這個時候的狀態已經在接近我們的目標了。
然而,技術不是靜止不動的,開發和測試實踐處於飛速的變化之中。靜態Web應用的時代已經成為過去,瀏覽器還在努力追趕之中,圍繞瀏覽器的自動化技術比已經遲緩的瀏覽器還要落後一年。開發人員正面臨著巨大的技術變革,在這個時候,把測試交給開發人員,這看上去是徒勞的。我們甚至還不太會手工測試這些應用,更不用提自動化測試了。
開發團隊身上的壓力也同樣巨大。當時Google 開始收購擁有富含動態Web應用的公司。YouTube、Google Docs等後繼產品的融入,延展了我們內部的基礎設施。開發團隊在編寫功能程式碼的過程中,要面臨很多問題,與我們測試人員在測試過程中要面臨的問題一樣,令人生畏!測試人員面對的測試問題無法孤立地解決。把測試和開發割裂開來,看成兩個單獨的環節,甚至是兩類截然不同的問題,這種做法是錯誤的,沿著這條路走下去意味著什麼問題也解決不了。解決測試團隊的問題,只是我們前進路上的其中一步而已。
進展在繼續。僱傭優秀的人是一件很有意思的事情,他們會推動進展的發生!到了2007年,測試團隊有了更好的定位。我們能夠很好地處理髮布週期的最後環節。開發團隊已經視我們為順利上線的可靠合作伙伴。不過我們仍然是在釋出過程的後期才介入的支援團隊,侷限於傳統QA模型。儘管有了優秀的執行能力,我們還沒達到我設想的目標。我解決了招聘方面的問題,測試也向著正確的方向發展,但是我們還是在整個流程中介入太晚。
我們在一個被稱作"測試認證"(本書後面的章節會詳細介紹)的事情上取得了不少進展。我們向開發團隊提供諮詢,幫助他們改善程式碼質量並儘早進行單元測試。我們開發工具並指導團隊進行持續整合,使產品一直保持可測試的狀態。我們進行了無數的改進和調整,從而消除了之前的很多質疑,本書詳細介紹了其中的很多方法。但是,在那個時候,還是感覺缺乏整體感,開發依舊是開發,測試依舊是測試。雖然很多文化變革的因素已經存在,但是,我們還需要一個催化劑把它們聚合成一體。
自從根據我的想法開始招聘擔當測試角色的開發人員以來,測試組織在不斷壯大。基於對這個團隊的思考,我意識到測試僅僅是我們所負責的工作的一部分。我們的工具團隊開發了從原始碼庫到編譯框架,再到缺陷資料庫的各種工具。我們是測試工程師、釋出工程師、工具開發工程師和諮詢師。觸動我的是,我們所做的非測試的工作對生產力的提升產生了巨大的影響力。我們的名稱是測試服務,但是我們的職責已經遠大於此。
因此,我決定正式把團隊名稱改為工程生產力(Engineering Productivity)團隊。伴隨著稱謂的改變,隨之而來的是文化的革新。人們開始更多地談論生產力而不是測試和質量。生產力是我們的工作,測試和質量是開發過程裡每個人都要承擔的工作。這意味著開發人員負責測試,開發人員負責質量。生產力團隊負責幫助開發團隊搞定這兩項任務。
開始的時候,這個觀點還只是一種夢想和志向,我們提出的"給Google加速"的口號聽起來也很空洞,但是,隨著時間的推移和我們的努力,我們實現了這些諾言。我們的工具讓開發的動作更快,我們幫助開發人員掃清了一個又一個障礙,消除了一個又一個瓶頸。我們的工具還使開發人員能夠編寫測試用例,並在每次構建時看到這些測試的結果反饋。測試用例不再只是隔離地執行在某些測試人員的機器上。測試結果會在儀表盤上顯示,並把成功的版本積累下來,作為應用釋出健康性的公開資料。我們並不是僅僅要求開發人員對測試和質量負責,我們還提供幫助讓他們可以輕鬆地達到這些要求。生產力和測試的區別最終變成了現實--Google的創新能夠更為順暢,技術債也不會累積了。
最終結果如何呢?我可不願這麼早就交了底,因為這本書就是要詳細講述這個問題的。作者們花費了巨大精力,根據自身和其他Googler的經歷,把我們的祕訣濃縮成了一套核心實踐。但其實,我們的成功有很多方面,從將構建次數以數量級式地降低,到"跑完即忘"式的測試自動化,再到開源一些非常新穎的測試工具。在我寫這篇序的時候,生產力團隊已經擁有1200名工程師,這個數量比我在2005年加入Google時整個工程部門的工程師的數量還要多。生產力品牌的影響力已經相當大,我們加速Google的使命已經作為工程文化的一部分,被廣泛接受。從我困惑、迷茫地坐在TGIF會議上的第一天到現在,這個團隊已經走過了漫長的征途。這期間唯一沒變的是我那頂三色螺旋槳帽,我把它放在我的桌上,作為我們一路走來的見證。
Patrick Copeland是Google工程生產力部門的高階總監,處於Google整個測試鏈的最頂端。公司裡所有的測試人員都最終彙報給Patrick(而他恰好跨級彙報給Larry Page,Google的聯合創始人和CEO)。Patrick加入Google之前是微軟的測試總監,並在那裡工作了近10年。他經常公開演講,在Google內部被公認為Google軟體快速開發、測試和部署技術的架構師。
Google軟體測試介紹
- 質量不等於測試
有時,測試和開發互相交織在一起,達到了無法區分彼此的程度,而在另外一些時候,測試和開發又是完全分離的,甚至開發人員都不知道測試在做些什麼
質量不等於測試。當你把開發過程和測試放到一起,就像在攪拌機裡混合攪拌那樣,直到不能區分彼此的時候,你就得到了質量。
- 角色
軟體開發工程師(譯註:software engineer,後文簡稱SWE)是一個傳統上的開發角色,他們的工作是實現終端使用者使用的功能程式碼。他們建立設計文件、選擇最優的資料結構和整體架構,並且花費大量時間在程式碼實現與程式碼審查上。SWE需要編寫與測試程式碼,包括測試驅動的設計、單元測試、參與構建各種規模的測試等,這些測試會在本章的後面做詳細解釋。SWE會對他們編寫、修復以及修改的程式碼承擔質量責任。如果一個開發者不得不修改一個函式,或者這次修改導致已有測試用例執行失敗,或者需要增加一個新的測試用例,他就必須去實現這個測試用例的程式碼。開發工程師幾乎將所有的時間都花費在了程式碼編寫上。
軟體測試開發工程師(譯註:software engineer in test,後文簡稱SET)也是一個開發角色,只是工作重心在可測試性和通用測試基礎框架上。他們參與設計評審,非常近距離地觀察程式碼質量與風險。為了增加可測試性,他們甚至會對程式碼進行重構,並編寫單元測試框架和自動化測試框架。SET是SWE在程式碼庫上的合作伙伴,相比較SWE是在增加功能性程式碼或是提高效能的程式碼,SET更加關注於質量提升和測試覆蓋率的增加。SET同樣會花費近百分之百的時間在編寫程式碼上,他們這樣做的目的是為質量服務,而SWE則更關注在客戶使用功能開發的實現上。
測試工程師(譯註:test engineer,後文簡稱TE)是一個和SET關係密切的角色,有自己不同的關注點--把使用者放在第一位來思考,代表使用者的利益。一些Google的TE會花費大量時間在模擬使用者的使用場景和自動化指令碼或程式碼上。同時,他們會把開發工程師和SET編寫的測試分門別類地組織起來,分析、解釋、測試執行結果,驅動測試執行,特別是在專案的最後階段,推進產品釋出。TE是真正的產品專家、質量顧問和風險分析師。某些TE需要編寫大量的程式碼,而另外一些TE則只用編寫少量的程式碼。
- 組織結構
測試是獨立存在的部門,是與專注領域部門平行的部門(橫跨各個產品專注領域),我們稱之為工程生產力團隊。測試人員基本上以租借的方式進入到產品團隊,去做提高質量相關的事情,尋找一些測試不足的地方,或者公開一些不可接受的缺陷率資料。由於測試人員並不是直接向產品團隊進行彙報,因此我們並不是簡單地被告之某個專案急需釋出就可以通過測試。我們有自己選擇決定的優先順序,在可靠性、安全性等問題上都不會妥協,除非碰到更重要的事情。如果開發團隊想要我們在測試上放他們一馬,他們必須事先和我們協商,但一般情況下都會被拒絕。
注意工程生產力團隊會根據不同產品團隊的優先順序、複雜度和其他產品的實際比較後,再來分配測試人員。顯然,有時候我們可能搞錯,實際上也確實出過錯,但總體上來說,這樣會保持實際的需求與不明確的需求之間的某種平衡。
這種測試人員在不同專案之間的借調模式,可以讓SET和TE時刻保持新鮮感並且總是很忙碌,另外還能保證一個好的測試想法可以快速在公司內部蔓延。一個在Geo產品上運用很好的測試技術或工具,很有可能在Chrome產品中也得到使用。推廣測試技術方面創新的最佳方式,莫過於把這個創新的發明者直接借調過來。
在擁有如此少量測試人員的情況下,Google還可以取得不錯的成果,核心原因在於Google從來不會在一次釋出的產品中包含大量功能。
- 版本管理
金絲雀版本、開發版本、測試版本、beta或釋出版本、
- 測試型別
小型測試 一般來說(但也並非所有)都是自動化實現的,用於驗證一個單獨函式或獨立功能模組的程式碼是否按照預期工作,著重於典型功能性問題、資料損壞、錯誤條件和大小差一錯誤等方面的驗證。小型測試的執行時間一般比較短,通常是在幾秒或更短的時間內就可以執行完畢。通常,小型測試是由SWE來實現,也會有少量的SET參與,TE幾乎不參與小型測試。小型測試一般需要使用mock和fake(譯註:mock fake環境是實際依賴系統的替代者,會提供相應的功能,但這些系統可能不存在,或者缺陷太多不可靠,或者是一些很難模擬的錯誤條件)才能執行。TE幾乎不編寫小型測試程式碼,但會參與執行這些測試,來診斷一些特定錯誤。小型測試主要嘗試解決的問題是"這些程式碼是否按照預期的方式執行"。
中型測試 通常也都是自動化實現的。該測試一般會涉及兩個或兩個以上,甚至更多模組之間的互動。測試重點在於驗證這些"功能近鄰區"之間的互動,以及彼此呼叫時的功能是否正確(我們稱功能互動區域為"功能近鄰區")。在產品早期開發過程中,在獨立模組功能被開發完畢之後,SET會驅動這些測試的實現及執行,SWE會深度參與,一起編碼、除錯和維護這些測試。如果一箇中型測試執行失敗,SWE會自覺地去檢視分析原因。在開發過程的後期,TE會通過手動的方式(如果比較難去實現自動化或實現的代價較大時),或者自動化地執行這些用例。中型測試嘗試去解決的問題是,一系列臨近的模組互相互動的時候,是否如我們預期的那樣工作。
大型測試 涵蓋三個或以上(通常更多)的功能模組,使用真實使用者使用場景和實際使用者資料,一般可能需要消耗數個小時或更長的時間才能執行完成。大型測試關注的是所有模組的整合,但更傾向於結果驅動,驗證軟體是否滿足終端使用者的需求。所有的三種工程師角色都會參與到大型測試之中,或是通過自動化測試,或是探索式測試。大型測試嘗試去解決的問題是,這個產品操作執行方式是否和使用者的期望相同,併產生預期的結果。這種端到端的使用場景以及在整體產品或服務之上的操作行為,即是大型測試關注的重點。
關於自動化測試和手動測試的比例,對於所有的三種類型測試,當然更傾向於前者。如果能夠自動化,並不需要人腦的智睿與直覺來判斷,那就應該以自動化的方式實現。但在一些情況下需要人類智慧的判斷,如使用者介面是否漂亮、保留的資料是否包含隱私等方面,這些還是需要手動測試來完成。
軟體測試開發工程師
對於功能程式碼而言,思維模式是建立,重點在考慮使用者、使用場景和資料流程上;而對於測試程式碼來說,主要思路是去破壞,怎樣寫測試程式碼用以擾亂分離使用者及其資料。由於我們假設的前提是在一個童話般的理想開發過程裡,所以我們或許可以分別僱傭不同的開發工程師:一個寫功能程式碼,而另一個思考如何破壞這些功能(譯註:兩種開發工程師,分別是功能開發人員和測試開發人員)。
功能開發人員在編寫功能程式碼的時候,測試開發人員編寫測試程式碼,但我們還需要第三種角色,一個關心真正使用者的角色。顯然在我們理想化的烏托邦測試世界裡,這個工作應該由第三種工程師來完成,既不是功能開發人員,也不是測試開發人員。我們把這個新角色稱為使用者開發人員(譯註:user developer)。他們需要解決的主要問題是面向使用者的任務,包括用例(use case)、使用者故事、使用者場景、探索式測試等。使用者開發人員關心這些功能模組如何整合在一起成為一個完整的整體,他們主要考慮系統級別的問題,通常情況下都會從使用者角度出發,驗證獨立模組整合在一起之後是否對終端使用者產生價值。
SET的工作
- 開發和測試流程
工程師團隊的交付物就是即將釋出的程式碼。程式碼的組織形式、開發過程、維護是日常工作重點。
公開的程式碼庫、和諧的工程工具、公司範圍內的資源共享,成就了豐富的Google內部共享程式碼庫與公共服務。這些共享的程式碼執行依賴於Google的基礎設施產品,它們在加速專案完成與減少專案失敗上發揮了很大作用。
工程師們對這些共享的基礎程式碼做了特殊處理,形成了一套不成文但卻非常重要的實踐規則,工程師在維護修改這些程式碼的時候都要遵守這些規則。
* 所有的工程師必須複用已經存在的公共庫,除非在專案特定需求方面有很好的理由。 * 對於公共的共享程式碼,首先要考慮的是能否可以容易地被找到,並具有良好的可讀性。程式碼必須儲存在程式碼庫的共享區域,以便查詢。由於共享程式碼會被不同的工程師使用,這些程式碼應該容易理解。所有的程式碼都要考慮到未來會被其他人閱讀或修改。 * 公共程式碼必須儘可能地被複用且相對獨立。如果一個工程師提供的服務被許多團隊使用,這將為他帶來很高的信譽。與功能的複雜性或設計的巧妙性相比,可複用性帶來的價值更大。 * 所有依賴必須明確指出,不可被忽視。如果一個專案依賴一些公用共享程式碼,在專案工程師不知情的前提下,這些共享程式碼是不允許被修改的。 * 如果一個工程師對共享程式碼庫在某些地方有更好的解決方案,他需要去重構已有的程式碼,並協助依賴在這個公用程式碼庫之上的應用專案遷移到新的程式碼庫上。這種樂善好施的社群工作是值得鼓勵的(譯註:這是Google經常提及的“同僚獎金(peer bonus)”。任何工程師如果受到其他工程師正面的影響,就可以送出“同僚獎金”作為感謝。除此之外,經理還有權使用其他獎勵手段。這樣做的目的就是讓這種正向團隊合作形成一種良性迴圈,並持續下去。當然,另外還有同事之間私下裡的感謝)。 * Google非常重視程式碼稽核,特別是公共通用模組的程式碼必須經過稽核。開發人員必須通過相關語言的可讀性稽核。在開發人員擁有按照程式碼風格編寫出乾淨程式碼的記錄之後,委員會會授予這名開發人員一個“良好可讀性”的證書。Google的四大主要開發語言:C++、Java、Python和JavaScript都有可讀性方面的程式碼風格指南。 * 在共享程式碼庫裡的程式碼,對測試有更高的要求(在後面部分會做討論)。
最小化對平臺的依賴。所有工程師都有一臺桌面工作機器,且作業系統都儘可能地與Google生產環境的作業系統保持一致。為了減少對平臺的依賴,Google對Linux發行版本的管理也十分謹慎,這樣開發人員在自己工作機器上測試的結果,與生產系統裡的測試結果會保持一致。從桌面到資料中心,CPU和OS的變化儘可能小(注:唯一不在Google通用測試平臺裡的本地測試實驗室,是Android和Chrome OS。這些類目不同的硬體必須在手邊進行測試)如果一個bug在測試機器上出現,那麼在開發機器上和生產環境的機器上也都應該能夠復現。
所有對平臺有依賴的程式碼,都會強制要求使用公共的底層庫。維護Linux發行版本的團隊同時也在維護這個底層平臺相關的公共庫。還有一點,對於Google使用的每個程式語言,都要求使用統一的編譯器,這個編譯器被很好地維護著,針對不同的Linux發行版本都會有持續的測試。這樣做本身其實並沒有什麼神奇之處,但限制執行環境可以節省大量下游的測試工作,也可以避免許多與環境相關且難以除錯的問題,能把開發人員的重心轉移到新功能開發上。保持簡單,也就相對會安全。
Google在平臺方面有特定的目標,就是保持簡單且統一。開發工作機和生產環境的機器都保持統一的Linux發行版本;一套集中控制的通用核心庫;一套統一的通用程式碼、構建和測試基礎設施;每個核心語言只有一個編譯器;與語言無關的通用打包規範;文化上對這些共享資源的維護表示尊重且有激勵。
使用統一的執行平臺和相同的程式碼庫,持續不斷地在構建系統中打包(譯註:打包是一個過程,包括將原始碼編譯成二進位制檔案,然後再把二進位制檔案統一封裝在一個linux rpm包裡面),這可以簡化共享程式碼的維護工作。構建系統要求使用統一的打包規範,這個打包規範與專案特定的程式語言無關,與團隊是否使用C++、Python或Java也都無關。大家使用同樣的“構建檔案”來打包生成二進位制檔案。
一個版本在構建的時候需要指定構建目標,這個構建目標(可以是公共庫、二進位制檔案或測試套件)由許多原始檔編譯連結產生。下面是整體流程。
* (1)針對某個服務,在一個或多個原始碼檔案中編寫一類或一系列功能函式,並保證所有程式碼可以編譯通過。 * (2)把這個新服務的構建目標設定為公共庫。 * (3)通過呼叫這個庫的方式編寫一套單元測試用例,把外部重要依賴通過mock模擬實現。對於需要關注的程式碼路徑,使用最常見的輸入引數來驗證。 * (4)為單元測試建立一個測試構建目標。 * (5)構建並執行測試目標,做適當的修改調整,直到所有的測試都執行成功。 * (6)按要求執行靜態程式碼分析工具,確保遵守統一的程式碼風格,且通過一系列常見問題的靜態掃描檢測。 * (7)提交程式碼申請程式碼稽核(後面對程式碼稽核會做更多詳細說明),根據反饋再做適當的修改,然後執行所有的單元測試並保證順利通過。
產出將是兩個配套的構建目標:庫構建目標和測試構建目標。庫構建目標是需要新發布的公共庫、測試構建目標用以驗證新發布的公共庫是否滿足需求。注意:在Google許多開發人員使用“測試驅動開發”的模式,這意味著步驟(3)會在步驟(1)和步驟(2)之前進行。
對於規模更大的服務,通過連結編譯持續新增的程式碼,構建目標也會逐漸變大,直到整個服務全部構建完成。在這個時候,會產生二進位制構建目標,其由包含主入口main函式檔案和服務庫連結在一起構成。現在,你完成了一個Google產品,它由三部分組成:一個經過良好測試的獨立庫、一個在可讀性與可複用性方面都不錯的公共服務庫(這個服務庫中還包含另外一套支援庫,可以用來建立其他的服務)、一套覆蓋所有重要構建目標的單元測試套件。
一個典型的Google產品由許多服務組成,所有產品團隊都希望一個SWE負責對應一個服務。這意味著每個服務都可以並行地構建、打包和測試,一旦所有的服務都完成了,他們會在一個最終的構建目標裡一起整合。為了保證單獨的服務可以並行地開發,服務之間的介面需要在專案的早期就確定下來。這樣,開發者會依賴在協商好的介面上,而不是依賴在需要開發的特定庫上。為了不耽擱服務級別之間的早期測試,這些介面一般都不會真正實現,而只是做一個虛假的實現。
SET會參與到許多測試目標的構建之中,並指出哪些地方需要小型測試。在多個構建目標整合在一起,形成規模更大應用程式的構建目標時,SET需要加速他們的工作,開始做一些更大規模的整合測試。在一個單獨的庫構建目標中,需要執行幾乎所有的小型測試(由SWE編寫,所有支援這個專案的SET都會給予幫助)。當構建目標日益增大時,SET也會參與到中大型測試的編寫之中去。
- SET是什麼?
SET是開發,主要做可測試性方面的工作。
SET首先是工程師角色,他使得測試存活於先前討論的所有Google開發過程之中。SET(software engineer in test)是軟體測試開發工程師。最重要的一點,SET是軟體工程師,正如我們招聘宣傳海報和內部晉升體系中所說的那樣,是一個100%的編碼角色。這種測試方式的有趣之處在於它使測試人員能儘早介入到開發流程中去,但不是通過“質量模型”和“測試計劃”的方式,而是通過參與設計和程式碼開發的方式。這會使得功能的開發工程師和測試的開發工程師處於相同的地位,SET積極參與各種測試,使測試富有效率,包括手動測試和探索式測試,而這些測試後期會由其他工程師負責。
- SET的介入時機
在專案早期,Google一般不會讓測試介入進來。實際上,即使SET在早期參與進來,也不是從事測試工作,而是去做開發。絕非有意忽視測試,當然也不是說早期產品的質量就不重要。這是受Google非正式創新驅動產品的流程所約束。Google很少在專案建立初期就投入一大幫人來做計劃(包括質量與測試計劃),然後再讓一大群開發參與進來。Google專案的誕生從來沒有如此正式過。
- 團隊結構
Google產品團隊最初是由一個技術負責人(tech lead)和一個或更多的專案發起人組成。在Google,技術負責人這個非正式的崗位一般由工程師擔任,負責設定技術方向、開展合作、充當與其他團隊溝通的專案介面人。他知道關於專案的任何問題,或者能夠指出誰知道這些問題的細節。技術負責人通常是一名SWE,或者由一名具備SWE能力的工程師來擔任。
- 設計文件
所有Google專案都有設計文件。這是一個動態的文件,隨著專案的演化也在不斷地保持更新。最早期的專案設計文件,主要包括專案的目標、背景、團隊成員、系統設計。在初期階段,團隊成員一起協同完成設計文件的不同部分。對於一些規模足夠大的專案來說,需要針對主要子系統也建立相應的設計文件,並在專案設計文件中增加子系統設計文件的連結。在初期版本完成後,裡面會囊括所有將來需要完成的工作清單,這也可以作為專案前進的路標。從這一點上講,設計文件必須要經過相關技術負責人的稽核。在專案設計文件得到足夠的評審與反饋之後,初期版本的設計文件就接近尾聲了,接下來專案就正式進入實施階段。
作為SET,比較幸運的是在初期階段就加入了專案,會有一些重要且有影響力的工作急需完成。如果能夠合理地謀劃策略,我們在加速專案進度的同時,也可以做到簡化專案相關人員的工作。實際上,作為工程師,SET在團隊中有一個巨大的優勢,就是擁有產品方面最廣闊的視野。一個好的SET會把非常專業的廣闊視野轉化成影響力,在開發人員所編寫的程式碼上產生深遠的影響力。通常來說,程式碼複用和模組互動方面的設計會由SET來做,而不是SWE。後面會著重介紹SET在專案的初期階段是如何發揮作用的。
SET需要熟悉瞭解所負責的系統設計(閱讀所有的設計文件是一個途徑),SET和SWE都期望如此。
SET早期提出的建議會反饋在文件和程式碼裡,這樣也增加了SET的整體影響力。
作為第一個審閱所有設計文件的人(也因此瞭解所有迭代過程),SET對專案的整體瞭解程度超過了技術負責人。
對於SET來說,這也是一個非常好的機會,可以在專案初期就與相應開發工程師一起建立良好的工作關係。
審閱設計文件的時候應該有一定的目的性,而不是像讀報紙那樣隨便看兩眼就算了。優秀的SET在審閱過程中始終保持強烈的目的性。下面是一些我們推薦的一些要點。
#!python 完整性:找出文件中殘缺不全或一些需要特殊背景知識的地方。通常情況下團隊裡沒人會了解這些知識,特別是對新人而言。鼓勵文件作者在這方面新增更多細節,或增加一些外部文件連結,用以補充這部分背景知識。 正確性:看一下是否有語法、拼寫、標點符號等方面的錯誤,這一般是馬虎大意造成的,並不意味著他們以後編寫的程式碼也是這樣。但也不能為這種錯誤而破壞規矩。 一致性:確保配圖和文字描述一致。確保文件中沒有出現與其他文件中截然相反的觀點和主張。 設計:文件中的一些設計要經過深思熟慮。考慮到可用的資源,目標是否可以順利達成?要使用何種基礎的技術框架(讀一讀框架文件並瞭解他們的不足)?期望的設計在框架方面使用方法上是否正確?設計是否太過複雜?有可能簡化嗎?還是太簡單了?這個設計還需要增加什麼內容? 介面與協議:文件中是否對所使用的協議有清晰的定義?是否完整地描述了產品對外的介面與協議?這些介面協議的實現是否與他們期望的那樣一致?對於其他的Google產品是否滿足統一的標準?是否鼓勵開發人員自定義Protocol buffer資料格式(後面會討論Protocol buffer)? 測試:系統或文件中描述的整套系統的可測試性怎樣?是否需要新增測試鉤子(譯註:testing hook,這裡指為了測試而增加一些介面,用以顯示系統內部狀態資訊)?如果需要,確保他們也被新增到文件之中。系統的設計是否考慮到易測試性,而為之也做了一些調整?是否可以使用已有的測試框架?預估一下在測試方面我們都需要做哪些工作,並把這部分內容也增加到設計文件中去。
google的程式碼評審工具ofollow,noindex">https://github.com/rietveld-codereview/rietveld
- 介面協議
Google protocol buffer語言(注:Google protocol buffers 是開源的,參見http://code.google.com/apis/protocolbuffers )
為了能夠儘早可以執行整合測試,針對依賴服務,SET提供了mock與fake。
- 自動化計劃
我們首先把容易出錯的介面做隔離,並針對它們建立mock和fake(在之前的章節中做過介紹),這樣我們可以控制這些介面之間的互動,確保良好的測試覆蓋率。
接下來構建一個輕量級的自動化框架,控制mock系統的建立和執行。這樣的話,寫程式碼的SWE可以使用這些mock介面來做一個私有構建。在他們把修改的程式碼提交到程式碼伺服器之前執行相應的自動化測試,可以確保只有經過良好測試的程式碼才能被提交到程式碼庫中。這是自動化測試擅長的地方,保證生態系統遠離糟糕程式碼,並確保程式碼庫永遠處於一個時刻乾淨的狀態。
SET除了在這個計劃中涵蓋自動化(mock、fake和框架)之外,還要包括如何公開產品質量方面的資訊給所有關心的人。在Google,SET使用報表和儀表盤(譯註:dashboard)來展示收集到的測試結果以及測試進度。通過將整個過程簡化和資訊公開透明化,獲取高質量程式碼的概率會大大增加。
- 可測試性
為了使SET也成為原始碼的擁有者之一,Google把程式碼審查作為開發流程的中心。相比較編寫程式碼而言,程式碼審查更值得炫耀。
在CL提交審查之前,會經過一系列的自動化檢查。這種自動化靜態檢查所使用的規則包含一些簡單的確認,例如是否遵循Google的程式碼風格指南、提交CL相關的測試用例是否執行通過(原則上所有的測試必須全部通過)等。CL裡面一般總是包含針對這個CL的測試程式碼,測試程式碼總是和功能程式碼在一起。在檢查完成之後,Mondrian會給相應的CL審閱者傳送一封包含這個CL連結的通知郵件。隨後審閱者會進行程式碼審查,並把修改建議發回給SWE去處理。這個過程會反覆進行,直到提交者和審閱者都滿意為止。
提交佇列(譯註:submit queue)的主要功能是保持“綠色”的構建,這意味著所有測試必須全部通過。這是構建系統和版本控制系統之間的最後一道防線。通過在乾淨環境中編譯程式碼並執行測試,提交佇列系統可以捕獲在開發機器上無法發現的環境錯誤,但這會導致構建失敗,甚至是導致版本控制系統中的程式碼處於不可編譯的狀態。
規模較大的團隊可以利用提交佇列在同一個程式碼分支上進行開發。如果沒有提交佇列,通常在程式碼整合或每輪測試時都會把程式碼凍結,使用提交佇列就可以避免這個問題。在這種模式下,提交佇列可以使得規模較大團隊就像小團隊一樣,高效且獨立。由於這樣增加了開發提交程式碼的頻率,勢必給SET的工作帶來了較大難度,這可能是唯一的弊端。
- SET的工作流程:一個例項:
略,可以參考具體語言的單元測試。
- 測試執行
做程式碼編譯、測試執行、結果分析、資料儲存、報表展示的通用的測試框架
- 測試規模
小型測試是為了驗證一個程式碼單元的功能,一般與執行環境隔離,例如針對一個獨立的類或一組相關函式的測試。小型測試的執行不需要外部依賴。在Google之外,小型測試通常就是單元測試。
中型測試是驗證兩個或多個模組應用之間的互動。和小型測試相比,中型測試有著更大的範疇且執行所需要的時間也更久。小型測試會嘗試走遍單獨函式的所有路徑,而中型測試的主要目標是驗證指定模組之間的互動。在Google之外,中型測試經常被稱為“整合測試”。
在Google之外通常被稱為“系統測試”或“端到端測試”。大型測試在一個較高層次上執行,驗證系統作為一個整體是如何工作的。這涉及應用系統的一個或所有子系統,從前端介面到後端資料儲存。該測試也可能會依賴外部資源,如資料庫、檔案系統、網路服務等。
小型測試是為了驗證一個程式碼單元的功能。中型測試驗證兩個或多個模組應用之間的互動。大型測試是為了驗證整個系統作為一個整體是如何工作的。
- 測試平臺對測試規模的排程
使用Google測試執行平臺執行的一些通用任務如下。
#!python 開發人員編譯和執行小型測試,希望立刻就能知道執行結果。 開發人員希望執行一個專案的所有小型測試,並能夠快速知道執行結果。 開發人員只有在變更程式碼出現時,才希望去編譯執行相關的專案測試,並即刻得到執行結果。 工程師希望能夠知道一個專案的測試覆蓋率並檢視結果。 對專案的每次程式碼變更(CL),都能夠執行這個專案的小型測試,並將執行結果傳送給團隊成員以輔助進行程式碼審查。 在程式碼變更(CL)提交到版本控制系統之後,自動執行專案的所有測試。 團隊希望每週都能得到程式碼覆蓋率,並實時跟蹤覆蓋率的變化。
上面提及的所有任務,有可能同時併發提交到Google測試執行系統。一些測試可能極度消耗資源,使得公用測試機器處於不可用狀態達數小時。另外一些測試可能只需幾毫秒,而且可以和其他幾百個任務同時在一臺機器上併發執行。當每一個測試都被標記為小型、中型、大型的時候,排程執行這些測試任務就會變得相對簡單一些,因為排程器已經知道每個任務需要執行的時間,這樣可以優化任務佇列,達到合理利用的目的。
Google測試執行系統利用了測試規模的定義,把執行較快的任務從較慢的任務中挑選出來。測試規模在測試執行時間上規定了一個最大值,如表2.1所示;同時測試規模在測試執行消耗資源上也做了要求,如表2.2所示。Google測試執行系統在發現任何測試超時,或是消耗的資源超過這個測試規模應該使用的資源時,會把這個測試任務取消掉並報告這個錯誤。這會迫使工程師提供合適的測試規模標籤。精準的測試規模,可以使Google測試執行系統在排程時做出明智的決定。
類別| 小型測試 | 中型測試 | 大型測試 | 超大型測試
:---- ---:|:---- ---:|:---------------------:|:---------------------:
時間目標(每個函式)| 10毫秒以內 | 1秒以內 | 儘可能快 | 儘可能快
強制時間限制 | 1分鐘之後強制結束 | 5分鐘之後強制結束 | 15分鐘之後強制結束 | 1小時之後強制結束
資源使用
類別| 大型測試 | 中型測試 | 小型測試
:---- ---:|:---- ---:|:---------------------:
網路服務(建立一個連結)| 是 | 僅本地 | 模擬
資料庫 | 是 | 僅本地 | 模擬
訪問檔案系統 | 是 | 是 | 模擬
訪問使用者介面系統 | 是 | 不鼓勵 | 模擬
系統呼叫 | 是 | 不鼓勵 | 否
多執行緒 | 是 | 是| 不鼓勵
睡眠狀態 | 是 | 是| 否
系統屬性 | 是 | 是| 否
- 測試規模的優缺點
大型測試
#!python 測試最根本最重要的:在考慮外部系統的情況下應用系統是如何工作的。 由於對外部系統有依賴,因此它們是非確定性的。 很寬的測試範疇意味著如果測試執行失敗,尋找精準失敗根源就會比較困難。 測試資料的準備工作會非常耗時。 大型測試是較高層次的操作,如果想要走到特定的程式碼路徑區域是不切實際的,而這一部分卻是小型測試的專長。
中型測試
#!python 由於不需要使用mock技術,且不受執行時刻的限制,因此該測試是從大型測試到小型測試之間的一個過渡。 因為它們執行速度相對較快,所以可以頻繁地執行它們。 它們可以在標準的開發環境中執行,因此開發人員也可以很容易執行它們。 它們依賴外部系統。 由於對外部系統有依賴,因此它們本身就有不確定性。 它們的執行速度沒有小型測試快。
小型測試
#!python 為了更容易地就被測試到,程式碼應清晰乾淨、函式規模較小且重點集中。為了方便模擬,系統之間的介面需要有良好的定義。 由於它們可以很快執行完畢,因此在有程式碼變更發生的時候就可以立刻執行,從而可以較早地發現缺陷並提供及時的反饋。 在所有的環境下它們都可以可靠地執行。 它們有較小的測試範圍,這樣可以很容易地做邊界場景與錯誤條件的測試,例如一個空指標。 它們有特定的範疇,可以很容易地隔離錯誤。 不要做模組之間的整合測試,這是其他型別的測試要做的事情(中型測試)。 有時候對子系統的模擬是有難度的。 使用mock或fake環境,可以不與真實的環境同步。
小型測試帶來優秀的程式碼質量、良好的異常處理、優雅的錯誤報告;大中型測試會帶來整體產品質量和資料驗證。
檢驗一個專案裡小型測試、中型測試和大型測試之間的比率是否健康,一個好辦法是使用程式碼覆蓋率。測試程式碼覆蓋率可以針對小型測試、中大型測試分別單獨產生報告。覆蓋率報告會針對不同的專案展示一個可被接受的覆蓋率結果。如果中大型測試只有20%的程式碼覆蓋率,而小型測試有近100%的覆蓋率,則說明這個專案缺乏端到端的功能驗證。如果結果數字反過來了,則說明這個專案很難去做升級擴充套件和維護,由於小型測試較少,就需要大量的時間消耗在底層程式碼除錯查錯上。
Google有許多不同型別的專案,這些專案對測試的需求也不同,小型測試、中型測試和大型測試之間的比例隨著專案團隊的不同而不同。這個比例並不是固定的,總體上有一個經驗法則,即70/20/10原則:70%是小型測試,20%是中型測試,10%是大型測試。如果一個專案是面向使用者的,擁有較高的整合度,或者使用者介面比較複雜,他們就應該有更多的中型和大型測試;如果是基礎平臺或者面向資料的專案,例如索引或網路爬蟲,則最好有大量的小型測試,中型測試和大型測試的數量要求會少很多。
另外有一個用來監視測試覆蓋率的內部工具是Harvester。Harvester是一個視覺化的工具,可以記錄所有專案的CL歷史,並以圖形化的方式展示,例如測試程式碼和CL中新增程式碼的比率、程式碼變更的多少、按時間的變化頻率、按照開發人員的變化次數,等等。這些圖形的目的是展示隨著時間的變化,測試的變化趨勢是怎樣的。
- 測試執行要求
#!python 每個測試和其他測試之間都是獨立的,使它們就能夠以任意順序來執行。 測試不做任何資料持久化方面的工作。在這些測試用例離開測試環境的時候,要保證測試環境的狀態與測試用例開始執行之前的狀態是一樣的。
對於衝突:
#!python 兩個測試都要繫結同一個埠,用以接收來自網路的資料。 兩個測試需要在同一個路徑下建立相同的目錄。 一個測試希望建立並使用一個數據庫表,而另外一個測試想刪除這個資料庫表。
解決方案
#!python 在測試執行系統中,讓每個測試用例獲取一個未被使用的埠,並讓被測系統動態地繫結到這個埠上。 在測試執行之前,為每一個測試用例在臨時目錄下建立目錄和檔案,並使用獨一無二的目錄名。 每個測試執行在自己的資料庫例項之上,使用與環境隔離的目錄和埠。這些都由測試執行系統來控制。
Google全力維護其測試執行系統,甚至文件也非常詳盡。這些文件存放在Google的“測試百科全書”中,這裡有對其執行使用的資源所做的最終解釋。“測試百科全書”有點像IEEE RFC(譯註:IEEE定義的正式標準,RFC是Request for Comment的簡寫),明確使用“必須”或“應該”這樣的字樣,並在其中詳細解釋了角色、測試用例職責、測試執行者、集群系統、執行時刻的libc、檔案系統等。
構建系統能定位到錯誤由哪個提交引起,同時還儲存了構建依賴圖。
測試認證
招聘到技術能力強的測試人員只是剛剛開始的第一步,我們依然需要開發人員參與進來一起做測試。其中我們使用的一個關鍵方法就是被稱為“測試認證”。
測試認證級別摘要
#!python 級別1 使用測試覆蓋率工具。 使用持續整合。 測試分級為小型、中型、大型。 明確標記哪些測試是非確定性的測試。 建立冒煙測試集合。 級別2 如果有測試執行結果為紅色就不會做釋出。 在每次程式碼提交之前都要求通過冒煙測試。 各種型別測試的整體增量覆蓋率要大於50%。 小型測試的增量覆蓋率要大於10%。 每一個功能特性至少有一個與之對應的整合測試用例。 級別3 所有重要的程式碼變更都要經過測試。 小型測試的增量覆蓋率要大於50%。 新增的重要功能都要經過整合測試的驗證。 級別4 在提交任何新程式碼之前都會自動執行冒煙測試。 冒煙測試必須在30分鐘內執行完畢。 沒有不確定性的測試。 總體測試覆蓋率應該不小於40%。 小型測試的程式碼覆蓋率應該不小於25%。 所有重要的功能都應該被整合測試驗證到。 級別5 對每一個重要的缺陷修復都要增加一個測試用例與之對應。 積極使用可用的程式碼分析工具。 總體測試覆蓋率不低於60%。 小型測試的程式碼覆蓋率應該不小於40%。
最初這個計劃在一些測試意識較高的團隊中緩慢試水,這些團隊成員熱衷於改進他們的測試實踐。經過在這幾個團隊的成功試驗之後,一個規模更大的、公司級別的認證競賽開始推行起來了,然後在新加入的團隊中再推行這個計劃就變得容易的多。
#!python 開發團隊得到許多優秀測試人員的關注,這些測試人員一般都報名成為測試認證教練。在一個測試資源稀缺的文化氛圍裡,註冊參加這個專案會吸引到比一般團隊更多的測試人員的加入。 他們獲得專家的指導,並學習到如何更好地編寫小型測試。 他們知道哪個團隊在測試上做的比較好,並向這個團隊學習。 他們能夠向其他的認證級別較低的團隊進行炫耀。
經過公司級別的推進,絕大多數團隊都在不斷向前進步,並意識到這個計劃的重要性。一些在這個計劃中表現不錯的開發總監會得到工程生產力團隊的優秀反饋,而嘲笑這個計劃的團隊也會置自身於危險之中。換句話說,在一個測試資源相對稀缺的公司裡,哪個團隊會捨得與工程生產力團隊疏遠呢?但並非哪裡都是鮮花與掌聲,讓執行這個計劃的負責人來給我們講述完整的故事吧。
試點團隊::① 足夠感興趣;② 沒有太多的冗餘程式碼;③ 在團隊中有一個測試戰神(對測試足夠的瞭解的人)。
我們宣佈測試認證計劃“正式啟動”的時候,有15個試點團隊在這個計劃的不同級別上執行著。在正式宣佈之前,我們在山景城、紐約和其他地點的所有辦公大樓上張貼“神祕的測試認證”的大海報,每個海報上用圖片印著各個試點團隊名字,使用的是內部專案名稱,如Rubix、Bounty、Mondrian和Red Tape。海報上唯一的文字是“未來就是現在”和“至關重要,莫被遺棄”,還有一個連結。從喜愛猜謎的Google同事那裡,我們得到了大量點選訪問,多數人想去一探究竟,還有一些人想去驗證自己的猜測是否正確。同時我們也使用ToTT來宣傳這個新計劃,並把讀者指引到他們能夠得到資訊的地方。這是一個資訊閃電戰。
宣傳網站上有一些資訊,包括為什麼測試認證對於團隊很重要,以及使用者可以得到怎樣的幫助。裡面強調指出,參與團隊會從一個很大的測試專家社群裡得到一個測試認證教練,同時還會得到兩個禮物——一個表示構建狀態的發光魔法球,可以告訴團隊他們的(一般是新的)持續整合是通過(綠色)還是失敗(紅色);另外一個是一個漂亮的星球大戰土豆頭工具包。這個被稱為達斯土豆工具包裡有三個逐漸變大的格子,每當團隊達到新的測試認證級別時我們都會給予獎勵。各個團隊展示他們的魔法球和土豆頭,為這個計劃吸引來更多好奇的團隊和帶來更好的口碑。
測試圈子裡的成員是這個專案的第一批教練和發言人。隨著越來越多團隊的加入,有許多熱情的工程師幫助造勢,自己也成為其他團隊的教練。
每次我們嘗試說服更多的團隊加入這個計劃的時候,都會與他們逐一討論理由和原因。一些團隊是由於你能使他們信服每一個級別和教練都會幫助團隊在這個領域有所提高而加入的。一些團隊認為他們會有所改善,並堅信這種“官方”級別評定會使他們因為當前正在做的工作得到好評。另外的一些團隊,他們本身的測試成熟度已經很高了,但加入這個計劃,會給其他的團隊發出一種訊號,表示他們已經很重視測試了。
- SET的招聘(暫略)
參考資料
- 討論 釘釘群21745728 qq群144081101 567351477
- 本文最新版本地址
- 本文英文原版書籍
- 本文原始碼地址
- 本文涉及的python測試開發庫 謝謝點贊!
- 本文相關海量書籍下載