CI/CD笔记:《持续交付:发布可靠软件的系统方法》
生活随笔
收集整理的這篇文章主要介紹了
CI/CD笔记:《持续交付:发布可靠软件的系统方法》
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
《持續(xù)交付:發(fā)布可靠軟件的系統(tǒng)方法》
- 前言
- 軟件交付的問題
- 配置管理
- 持續(xù)集成
- 測試策略的實現(xiàn)
- 部署流水線解析
- 構(gòu)建與部署的腳本化
- 提交階段
- 自動化驗收測試
- 非功能需求的測試
- 應(yīng)用程序的部署與發(fā)布
- 基礎(chǔ)設(shè)施與環(huán)境管理
- 數(shù)據(jù)管理
- 組件和依賴管理
- 版本控制進階
- 持續(xù)交付管理
前言
- 自動化是關(guān)鍵,它讓開發(fā)人員、測試人員和運營人員能夠通過一鍵式操作完成軟件創(chuàng)建和部署過程中的所有常見任務(wù)。
- 我們的目標是改變軟件交付方式,將其由開發(fā)人員的手工操作變成一種可靠、可預(yù)期、可視化的過程并在很大程度上實現(xiàn)了自動化的流程,而且它要具備易于理解與風險可量化的特點。
- 敏捷宣言的第一原則:“我們的首要任務(wù)是盡早持續(xù)交付有價值的軟件并讓客戶滿意。”這也反映了這樣一個現(xiàn)實:對于成功的軟件,首次發(fā)布只是交付過程的開始。
- 書中描述的所有技術(shù)都與交付軟件新版本給客戶相關(guān),旨在減少時間和降低風險。這些技術(shù)的核心是增加反饋,改進負責交付的開發(fā)、測試和運維人員之間的協(xié)作。這些技術(shù)能確保當需要修改應(yīng)用程序(也許是修復(fù)缺陷,也許是開發(fā)新功能)時,從修改代碼到正式部署上線之間的時間盡可能短,盡早發(fā)現(xiàn)缺陷以便快速修復(fù),并更好地了解與本次修改相關(guān)的風險。
軟件交付的問題
- 對于應(yīng)用程序的配置、源代碼、環(huán)境或數(shù)據(jù)的每個變更都會觸發(fā)創(chuàng)建一個新流水線實例的過程。流水線的首要步驟之一就是創(chuàng)建二進制文件和安裝包,而其余部分都是基于第一步的產(chǎn)物所做的一系列測試,用于證明其達到了發(fā)布質(zhì)量。每通過一步測試,我都會更加相信這些二進制文件、配置信息、環(huán)境和數(shù)據(jù)所構(gòu)成的特殊組合可以正常工作。如果這個產(chǎn)品通過了所有的測試環(huán)節(jié),那么它就可以發(fā)布了。
- 部署流水線的目標有三個。首先,它讓軟件構(gòu)建、部署、測試和發(fā)布過程對所有人可見,促進了合作。其次,它改善了反饋,以便在整個過程中,我們能夠更早地發(fā)現(xiàn)并解決問題。最后,它使團隊能夠通過一個完全自動化的過程在任意環(huán)境上部署和發(fā)布軟件的任意版本。
- 手工部署過程依賴于部署專家。如果專家去度假或離職了,那你就有麻煩了。盡管手工部署枯燥且極具重復(fù)性,但仍需要有相當程度的專業(yè)知識。若要求專家做這些無聊、重復(fù),但有技術(shù)要求的任務(wù)則必定會出現(xiàn)各種我們可以預(yù)料到的人為失誤,同時失眠,酗酒這種問題也會接踵而至。然而自動化部署可以把那些成本高昂的資深高技術(shù)人員從過度工作中解放出來,讓他們投身于更高價值的工作活動當中。
- 我們的對策就是將測試、部署和發(fā)布活動也納入到開發(fā)過程中,讓它們成為開發(fā)流程正常的一部分。這樣的話,當準備好進行系統(tǒng)發(fā)布時就幾乎很少或不會有風險了,因為你已經(jīng)在很多種環(huán)境,甚至類生產(chǎn)環(huán)境中重復(fù)過很多次,也就相當于測試過很多次了。而且要確保每個人都成為這個軟件交付過程的一份子,無論是構(gòu)建發(fā)布團隊、還是開發(fā)測試人員,都應(yīng)該從項目開始就一起共事。
- 軟件發(fā)布能夠(也應(yīng)該)成為一個低風險、頻繁、廉價、迅速且可預(yù)見的過程。
- 有用性的一個重要部分是質(zhì)量。我們的軟件應(yīng)該滿足它的業(yè)務(wù)目的。質(zhì)量并不等于完美,正如伏爾泰所說“追求完美是把事情做好的大敵”,但我們的目標應(yīng)該一直是交付質(zhì)量足夠高的軟件,給客戶帶來價值。因此,盡快地交付軟件很重要,保證一定的質(zhì)量是基礎(chǔ)。
- 持續(xù)集成:每次提交都對應(yīng)用程序進行構(gòu)建并測試,這稱作持續(xù)集成。
- 流程反饋:它是指完全以自動化方式盡可能地測試每一次變更。
- 人力資源是昂貴且非常有價值的,所以我們應(yīng)該集中人力來生產(chǎn)用戶所需要的新功能,盡可能快速地交付這些新功能,而不是做枯燥且易出錯的工作。像回歸測試、虛擬機的創(chuàng)建和部署這類工作最好都由機器來完成。
- 盡可能全面,即75%左右的代碼庫覆蓋率。只有這樣,這些測試通過以后,我們才對自己寫的軟件比較有信心。
- 對于快速交付高質(zhì)量的軟件來說,基于持續(xù)改進的過程是非常關(guān)鍵的。迭代過程有助于為這類活動建立規(guī)律性,例如每個迭代至少開一次回顧會議,在會上每個人都應(yīng)參與討論如何在下一個迭代中改進交付過程。
- 精益制造的目標是確保快速地交付高質(zhì)量的產(chǎn)品,它聚焦于消除浪費,減少成本。
- 部署流水線的一個關(guān)鍵點是,它是一個“拉動”(pull)系統(tǒng),它使測試人員、運維人員或支持服務(wù)人員能夠做到自服務(wù),即他們可以自行決定將哪個版本的應(yīng)用程序部署到哪個環(huán)境中。
- 減少壓力的關(guān)鍵在于擁有一個我們前面所描述的自動化部署過程,并頻繁地運行它,當部署失敗后還能夠快速恢復(fù)到原來狀態(tài)。
- 在每次以同一種方式部署應(yīng)用軟件時,也是驗證我們的部署機制是否正確的時機。事實上,向其他任何環(huán)境的任何一次部署過程都是生產(chǎn)環(huán)境部署的一次演練。
- 如果在軟件開發(fā)中的某個任務(wù)令你非常痛苦,那么解決痛苦的方法只有更頻繁地去做,而不是回避。因此,我們應(yīng)該頻繁做集成,事實上應(yīng)該在每次提交修改后都做集成。持續(xù)集成這個實踐將頻繁集成發(fā)揮到了極至,而“持續(xù)集成”轉(zhuǎn)變了軟件開發(fā)過程。持續(xù)集成會及時檢測到任何一次破壞已有系統(tǒng)或者不滿足客戶驗收測試的提交。一旦發(fā)生這種情況,團隊就立刻去修復(fù)問題(這是持續(xù)集成的首要規(guī)則)
- 軟件發(fā)布的可重復(fù)性和可靠性來自于以下兩個原則:(1)幾乎將所有事情自動化;(2)將構(gòu)建、部署、測試和發(fā)布軟件所需的東西全部納入到版本控制管理之中。
- 驗收測試是可以自動化的,數(shù)據(jù)庫的升級和降級也是可以自動化的,甚至網(wǎng)絡(luò)和防火墻配置也是可以自動化的。你應(yīng)該盡可能自動化所有的東西。
- 如果創(chuàng)建應(yīng)用程序的說明文檔是你的痛點,那么每開發(fā)一個功能時就應(yīng)寫好文檔,而不是留到最后一起寫。把一個功能的說明文檔也作為“DONE”的一個驗收條件,并盡可能自動化這個過程。
- 越早發(fā)現(xiàn)缺陷,修復(fù)它們的成本越低。如果在沒有提交代碼到版本控制之前,我們就能發(fā)現(xiàn)并修復(fù)缺陷的話,代價是最小的。
- “內(nèi)建質(zhì)量”還有另外兩個推論。(1)測試不是一個階段,當然也不應(yīng)該開發(fā)結(jié)束之后才開始。如果把測試留在最后,那就為時晚矣,因為可能根本沒有時間修復(fù)那些剛被發(fā)現(xiàn)的問題。(2)測試也不純粹或主要是測試人員的領(lǐng)域。交付團隊的每個人都應(yīng)該對應(yīng)用程序的質(zhì)量負責。
- 理想情況下,團隊中的成員應(yīng)該有共同的目標,并且每個成員應(yīng)在工作中互相幫助來實現(xiàn)這一目標。無論成功還是失敗,其結(jié)果都屬于這個團隊,而非個人。
- 關(guān)鍵在于組織中的每個人都要參與到持續(xù)改進過程當中。如果只在自己所在角色的內(nèi)部進行反饋環(huán),而不是在整個團隊范圍內(nèi)進行的話,就必將產(chǎn)生一種“頑疾”:以整體優(yōu)化為代價的局部優(yōu)化,最終導(dǎo)致互相指責。
配置管理
- 我們所討論的有關(guān)加快發(fā)布周期和提高軟件質(zhì)量的所有實踐,從持續(xù)集成、自動化測試,到一鍵式部署,都依賴于下面這個前提:與項目相關(guān)的所有東西都在版本控制庫中。
- 只要能從版本控制庫中取出所需要的一切,就能保證為開發(fā)、測試,甚至生產(chǎn)環(huán)境提供一個穩(wěn)定的平臺。然后你可以將整個環(huán)境(包括配置基線上的操作系統(tǒng))做成一個虛擬鏡像,放在版本控制庫中,這可以作為更高級別的保證措施,而且可以提高部署的簡單性。
- 這種很長時間才提交的做法是有問題的。因為提交越頻繁,越能夠體現(xiàn)出版本控制的好處。除非每個人都頻繁提交,否則“安全地對系統(tǒng)進行重構(gòu)”這件事基本上是不可能完成的任務(wù)。因為長時間不提交代碼會讓合并工作變得過于復(fù)雜。如果你頻繁提交,其他人可以看到你的修改且可與之交互,你也可以清楚地知道你的修改是否破壞了應(yīng)用程序,而且每次合并工作的工作量會一直很小,易于管理。
- 任何改變應(yīng)用程序的行為,無論修改了什么,都算是編程,即使只是修改一行配置信息。你進行修改所使用的語言可能或多或少地受到限制,但此時仍是在編程。根據(jù)定義,要為用戶提供的軟件配置能力越強,你能置于系統(tǒng)配置的約束就應(yīng)越少,而你的編程環(huán)境也會變得越復(fù)雜。
- 將那些特定于測試環(huán)境或生產(chǎn)環(huán)境的實際配置信息存放于與源代碼分離的單獨代碼庫中通常是非常必要的。因為這些信息與源代碼的變更頻率是不同的。
- 如果應(yīng)用程序所依賴的任何部分沒有準備好,部署或安裝腳本都應(yīng)該報錯,這相當于配置設(shè)置的冒煙測試。
- 我們通常在需要時才臨時決定如何管理配置信息,其后果是每個應(yīng)用的配置信息被放在不同的位置,而應(yīng)用程序又以不同的方式獲取這些配置。這會給確定“哪些環(huán)境中有哪些配置”帶來不必要的困難。
- 環(huán)境管理的關(guān)鍵在于通過一個全自動過程來創(chuàng)建環(huán)境,使創(chuàng)建全新的環(huán)境總是要比修復(fù)已受損的舊環(huán)境容易得多。
- 即便很微小的變化也可能把環(huán)境破壞掉。任何變更在上線之前都必須經(jīng)過測試,因而要將其編成腳本,放在版本控制系統(tǒng)中。這樣,一旦該修改被認可,就可以通過自動化的方式將其放在生產(chǎn)環(huán)境中。
- 沒有配置管理,根本談不上持續(xù)集成、發(fā)布管理以及部署流水線。它對交付團隊內(nèi)部的協(xié)作也會起到巨大的促進作用。
持續(xù)集成
- 持續(xù)集成要求每當有人提交代碼時,就對整個應(yīng)用進行構(gòu)建,并對其執(zhí)行全面的自動化測試集合。而且至關(guān)重要的是,假如構(gòu)建或測試過程失敗,開發(fā)團隊就要停下手中的工作,立即修復(fù)它。持續(xù)集成的目標是讓正在開發(fā)的軟件一直處于可工作狀態(tài)。
- 持續(xù)集成不是一種工具,而是一種實踐。它需要開發(fā)團隊能夠給予一定的投入并遵守一些準則,需要每個人都能以小步增量的方式頻繁地將修改后的代碼提交到主干上,并一致認同“修復(fù)破壞應(yīng)用程序的任意修改是最高優(yōu)先級的任務(wù)”。如果大家不能接受這樣的準則,則根本無法如預(yù)期般通過持續(xù)集成提高質(zhì)量。
- 單元測試用于單獨測試應(yīng)用程序中某些小單元的行為(比如一個方法、一個函數(shù),或一小組方法或函數(shù)之間的交互)。它們通常不需要啟動整個應(yīng)用程序就可以執(zhí)行,而且也不需要連接數(shù)據(jù)庫(如果應(yīng)用程序需要數(shù)據(jù)庫的話)、文件系統(tǒng)或網(wǎng)絡(luò)。它們也不需要將應(yīng)用程序部署到類生產(chǎn)環(huán)境中運行。單元測試應(yīng)該運行得非常快,即使對于一個大型應(yīng)用來說,整個單元測試套件也應(yīng)該在十分鐘之內(nèi)完成。
- 組件測試用于測試應(yīng)用程序中幾個組件的行為。與單元測試一樣,它通常不必啟動整個應(yīng)用程序,但有可能需要連接數(shù)據(jù)庫、訪問文件系統(tǒng)或其他外部系統(tǒng)或接口(這些可以使用“樁”,即stub技術(shù))。組件測試的運行時間通常較長。
- 驗收測試最好采用將整個應(yīng)用程序運行于類生產(chǎn)環(huán)境的運作方式。當然,驗收測試的運行時間也較長。一個驗收測試套件連續(xù)運行一整天是很平常的事兒。
- 在使用持續(xù)集成之前,很多開發(fā)團隊都使用每日構(gòu)建(nightly build)。當時,微軟使用這個實踐已經(jīng)很多年了。誰破壞了構(gòu)建,就要負責監(jiān)視后續(xù)的構(gòu)建過程,直至發(fā)現(xiàn)下一個破壞了構(gòu)建的人。
- 在提交代碼時,做出了這一代碼的開發(fā)人員應(yīng)該監(jiān)視這個構(gòu)建過程,直到該提交通過了編譯和提交測試之后,他們才能開始做新任務(wù)。在這短短幾分鐘的提交階段結(jié)束之前,他們不應(yīng)該離開去吃午飯或開會,而應(yīng)密切注意構(gòu)建過程并在提交階段完成的幾秒鐘內(nèi)了解其結(jié)果。
- 在這里需要澄清一下,我們并不建議你工作到很晚來修復(fù)失敗的構(gòu)建,而是希望你有規(guī)律地盡早提交代碼,給自己足夠的時間處理可能出現(xiàn)的問題。或者,你可以第二天再提交。很多有經(jīng)驗的開發(fā)人員在下班前一小時內(nèi)不再提交代碼,而是把它作為第二天早上的第一件事情。如果所有手段都不好使,那么把版本控制庫中的代碼回滾到上一次成功構(gòu)建的狀態(tài),并在本地保留一份失敗的代碼就可以了。
- 如果某次提交失敗了,無論采取什么樣的行動,最重要的是盡快讓一切再次正常運轉(zhuǎn)起來。如果無法快速修復(fù)問題,無論什么原因,我們都應(yīng)該將它回滾到版本控制庫中前一個可工作的版本上,之后再在本地環(huán)境中修復(fù)它。
- 那些已經(jīng)成功運行了一段時間的測試失敗時,失敗的原因可能很難找。這種失敗是否真的意味著發(fā)現(xiàn)了一個回歸問題呢?也許這個測試不再是有效的測試了,也許是因為原有功能因需求變化被改變了。找出真正的失敗原因可能需要向很多人了解情況,并且需要花上一段時間,但這是值得的。我們的選擇是要么修復(fù)代碼(如果是回歸問題的話),要么修改測試(如果該測試以前的某個假設(shè)不成立了),或者刪除它(如果被測試的功能已經(jīng)不存在了)。
- 假如提交代碼后,你寫的測試都通過了,但其他人的測試失敗了,構(gòu)建結(jié)果還是會失敗。通常這意味著,你引入了一個回歸缺陷。你有責任修復(fù)因自己的修改導(dǎo)致失敗的那些測試。
- 只有非常高的單元測試覆蓋率才有可能保證快速反饋(這也是持續(xù)集成的核心價值)。完美的驗收測試覆蓋率當然也很重要,但是它們運行的時間會比較長。根據(jù)我們的經(jīng)驗,能夠達到完美單元測試覆蓋率的唯一方法就是使用測試驅(qū)動開發(fā)。盡管我們盡量避免在本書中教條式地提及敏捷開發(fā)實踐,但我們認為測試驅(qū)動開發(fā)是持續(xù)交付實踐成為可能的關(guān)鍵。
- 所謂測試驅(qū)動開發(fā)是指當開發(fā)新的功能或修復(fù)缺陷時,開發(fā)人員首先要寫一個測試,該測試應(yīng)該是該功能的一個可執(zhí)行規(guī)范。這些測試不但驅(qū)動了應(yīng)用程序的設(shè)計,而且既可以作為回歸測試使用,也是一份代碼的說明文檔,描述了應(yīng)用程序預(yù)期的行為。
- 重構(gòu)是指通過一系列小的增量式修改來改善代碼結(jié)構(gòu),而不會改變軟件的外部行為。通過持續(xù)集成和測試驅(qū)動開發(fā)可以確保這些修改不會改變系統(tǒng)的行為,從而使重構(gòu)成為可能。
- 只要你指定某個倉庫作為主庫(master),每次更改這個倉庫就觸發(fā)持續(xù)集成服務(wù)器上的一次構(gòu)建,并讓每個人都將其修改推送到這個倉庫中來實現(xiàn)共享。很多使用分布式系統(tǒng)的項目都使用這種方式,而且非常成功。
- 持續(xù)集成的使用會為團隊帶來一種開發(fā)模式上的轉(zhuǎn)變。沒有持續(xù)集成的話,直到驗證前,應(yīng)用程序可能一直都處于無法工作的狀態(tài),而有了持續(xù)集成之后,應(yīng)用程序就應(yīng)該是時刻處于可工作狀態(tài)的了,雖然這種自信取決于自動化測試覆蓋率。
測試策略的實現(xiàn)
- 測試是跨職能部門的活動,是整個團隊的責任,應(yīng)該從項目一開始就一直做測試。
- 質(zhì)量內(nèi)嵌是指從多個層次(單元、組件和驗收)上寫自動化測試,并將其作為部署流水線的一部分來執(zhí)行,即每次應(yīng)用程序的代碼、配置或環(huán)境以及運行時所需軟件發(fā)生變化時,都要執(zhí)行一次。
- 手工測試也是質(zhì)量內(nèi)嵌的關(guān)鍵組成部分,如演示、可用性測試和探索性測試在整個項目過程中都應(yīng)該持之以恒地做下去
- 測試策略的設(shè)計主要是識別和評估項目風險的優(yōu)先級,以及決定采用哪些行動來緩解風險的一個過程。
- 回歸測試是自動化測試的全集。它們用來確保任何修改都不會破壞現(xiàn)有的功能,還會讓代碼重構(gòu)變得容易些,因為可以通過回歸測試來證明重構(gòu)沒有改變系統(tǒng)的任何行為。
- 一般我們將代碼覆蓋率高于80%的測試視為“全面的”測試,但測試質(zhì)量也非常重要,單單使用覆蓋率這一指標是不夠的。
- 一個很好的經(jīng)驗法則就是,一旦對同一個測試重復(fù)做過多次手工操作,并且你確信不會花太多時間來維護這個測試時,就要把它自動化
- 一般來說,驗收測試都是端到端的測試,并運行在一個與生產(chǎn)環(huán)境相似的真實工作環(huán)境中。
- 單元測試不應(yīng)該訪問數(shù)據(jù)庫、使用文件系統(tǒng)、與外部系統(tǒng)交互。或者說,單元測試不應(yīng)該有系統(tǒng)組件之間的交互。這會讓單元測試運行非常快,因此可以得到更早的反饋,了解自己的修改是否破壞了現(xiàn)有的任何功能。這些測試也應(yīng)該覆蓋系統(tǒng)中每個代碼分支路徑(最少達到80%)。這樣,它們就組成了回歸測試套件的主要部分。
- 部署測試用于檢查部署過程是否正常。換句話說,就是應(yīng)用程序是否被正確地安裝、配置,是否能與所需的服務(wù)正確通信,并得到相應(yīng)的回應(yīng)。
- 探索性測試是一個創(chuàng)造性的學(xué)習過程,并不只是發(fā)現(xiàn)缺陷,它還會致使創(chuàng)建新的自動化測試集合,并可以用于覆蓋那些新的需求。
- 非功能測試是指除功能之外的系統(tǒng)其他方面的質(zhì)量,比如容量、可用性、安全性等。
- 樁(stub)是在測試中為每個調(diào)用提供一個封裝好的響應(yīng),它通常不會對測試之外的請求進行響應(yīng),只用于測試。
- 盲目地用書寫差勁的驗收條件實現(xiàn)自動化測試是產(chǎn)生不易維護的驗收的測試套件的主要原因之一。
- 假如你發(fā)現(xiàn)對同一個功能重復(fù)進行了多次的手工測試,就要判斷一下這個功能是否還會被修改。如果不會的話,就將這個測試自動化。
- 坐下來與用戶一起識別系統(tǒng)中高價值的功能是非常重要的。利用前面一節(jié)所說的技術(shù),創(chuàng)建一套廣泛的自動化測試,覆蓋這些高價值的核心功能。
- 對于遺留系統(tǒng)來說,這些覆蓋核心功能的測試就是非常重要的冒煙測試了。
- 與沒有考慮可測試性的那些系統(tǒng)相比,在設(shè)計時就考慮到可測試性的系統(tǒng),其標準組件化的傾向更強,而且更容易測試。
- 當軟件需要在很多不同的環(huán)境上運行時,情況就不同了。此時,自動化測試和類生產(chǎn)環(huán)境的自動化部署相結(jié)合,會給項目帶來巨大的價值,因為可以把腳本直接指向需要測試的環(huán)境,從而節(jié)省大量的手工測試時間與精力。
- 在組件測試和集成測試之間的分界線并不十分清晰(尤其當“集成測試”這個詞被賦予了太多的意義)。我們所說的“集成測試”是指那些確保系統(tǒng)的每個獨立部分都能夠正確作用于其依賴的那些服務(wù)的測試。
- 這些自動化集成測試可以當成向生產(chǎn)環(huán)境部署系統(tǒng)時的冒煙測試,也可以作為一種診斷方法來監(jiān)控生產(chǎn)環(huán)境中的系統(tǒng)行為。
- 我們可以把缺陷分為嚴重(critical)、阻塞(blocker)、中(medium)和低(low)四個級別。
- 測試主要是建立反饋環(huán),而這個反饋環(huán)會驅(qū)動開發(fā)、設(shè)計和發(fā)布等活動。將測試推遲到項目后期的計劃最終都會失敗,因為它破壞了產(chǎn)生高質(zhì)量、高生產(chǎn)率,以及(最重要的)反映項目進展情況的反饋環(huán)。
部署流水線解析
- 持續(xù)集成主要關(guān)注于代碼是否可以編譯成功以及是否可通過單元測試和驗收測試。但持續(xù)集成并不足以滿足我們的需要。持續(xù)集成的主要關(guān)注對象是開發(fā)團隊。持續(xù)集成系統(tǒng)的輸出通常作為手工測試流程和后續(xù)發(fā)布流程的輸入
- 由于很容易將應(yīng)用程序部署到測試環(huán)境中,所以團隊可以同時得到軟件功能和部署流程兩個方面的快速反饋。
- 從精益的角度來看,我們實現(xiàn)了一個“拉式系統(tǒng)”(pull system),即測試團隊只要自己單擊按鈕,就能將某個特定的軟件版本部署到測試環(huán)境中。運維人員也可以通過單擊一下按鈕就把軟件部署到試運行環(huán)境和生產(chǎn)環(huán)境中。
- 部署流水線是指軟件從版本控制庫到用戶手中這一過程的自動化表現(xiàn)形式。
- 二進制包應(yīng)該只在構(gòu)建流水線的提交階段生成一次。這些二進制包應(yīng)該保存在文件系統(tǒng)的某個位置上,讓流水線的后續(xù)階段能夠輕松地訪問到這個位置,但要注意不要放在版本控制庫中,因為它只是一個版本的衍生品,并不是原生態(tài)的定義。
- 我們不想在那些明顯有問題的版本上花時間和精力,所以當開發(fā)人員提交變更到版本控制系統(tǒng)后,我們希望盡快地評估一下這個最新版本。提交者要一直等到構(gòu)建結(jié)果,然后才能做下一項工作。
- 當缺陷還比較容易修復(fù)時,盡快得到反饋是非常重要的,而不應(yīng)花更大的代價得到全面的反饋。
- 對于在這個待發(fā)布的候選版本,第一階段的成功是一個重要的里程碑,它是這個部署流水線的一個關(guān)卡。一旦通過這個關(guān)卡,開發(fā)人員就被從上一個任務(wù)中釋放出來,開始做下一個任務(wù)了。然而,他們?nèi)耘f有責任監(jiān)視后續(xù)階段的運行狀況。即使后續(xù)階段出了問題,修復(fù)失敗的構(gòu)建仍舊是開發(fā)團隊的首要任務(wù)。我們賭自己能成功,可一旦賭輸了,也已準備好去償還技術(shù)債。
- 生產(chǎn)環(huán)境中的大多數(shù)問題往往是由不充分的控制導(dǎo)致的。正如我們在第11章中所講的,生產(chǎn)環(huán)境應(yīng)該是完全受控的,即對生產(chǎn)環(huán)境的任何修改都應(yīng)該通過自動化過程來完成。這不僅包括應(yīng)用程序的部署,還包括對配置、軟件棧、網(wǎng)絡(luò)拓撲以及狀態(tài)的所有修改。只有在這種方式下,我們才可能對它們進行可靠地審計和問題診斷,并在可預(yù)計的時間內(nèi)修復(fù)它們。隨著系統(tǒng)復(fù)雜性的增加,不同類型服務(wù)器的增多,以及不斷提高的性能需求,我們就更需要這種程度的控制力。
- 實現(xiàn)部署流水線的第一步是將構(gòu)建和部署流程自動化。構(gòu)建過程的輸入是源代碼,輸出結(jié)果是二進制包。
- 每當有人提交后,持續(xù)集成服務(wù)器就應(yīng)執(zhí)行構(gòu)建,持續(xù)集成服務(wù)器應(yīng)該監(jiān)視版本控制系統(tǒng),每當發(fā)現(xiàn)有新提交的代碼時,就簽出或更新源代碼,運行自動化構(gòu)建流程,并將生成的二進制包放在文件系統(tǒng)的某個地方,使整個團隊都能通過持續(xù)集成服務(wù)器的用戶界面獲取。
- 部署活動可能包含:(1)為應(yīng)用程序打包,而如果應(yīng)用程序的不同組件需要部署在不同的機器上,就要分別打包;(2)安裝和配置過程應(yīng)該實現(xiàn)自動化;(3)寫自動化部署測試腳本來驗證部署是否成功了。部署流程的可靠性是非常重要的,因為它是自動化驗收測試的前提條件。
- 在開發(fā)構(gòu)建和部署系統(tǒng)的過程中,一定要確保遵循前面說過的那些原則,如只生成一次二進制包,將配置信息與二進制包分離,以便在不同環(huán)境的部署中可以使用相同的二進制包。這能確保配置管理有一個健全的基礎(chǔ)。
- 開發(fā)部署流水線的下一步就是實現(xiàn)全面的提交階段,也就是運行單元測試、進行代碼分析,并對每次提交都運行那些挑選出來的驗收測試和集成測試
- 因為單元測試并不需要訪問文件系統(tǒng)或數(shù)據(jù)庫(與之對應(yīng)的是組件測試),所以運行速度應(yīng)該很快。這也是構(gòu)建應(yīng)用程序之后就直接運行單元測試的原因。與此同時,還可以運行一些靜態(tài)分析工具,得到一些有用的分析數(shù)據(jù),比如代碼風格、代碼覆蓋率、圈復(fù)雜度、耦合度等。
- 反饋是所有軟件交付流程的核心。改善反饋的最佳方法是縮短反饋周期,并讓結(jié)果可視化。你應(yīng)該持續(xù)度量,并把度量結(jié)果以一種讓人無法回避的方式傳播出去。
構(gòu)建與部署的腳本化
- 所有構(gòu)建工具都有一個共同的核心功能,即可以對依賴關(guān)系建模。在執(zhí)行過程中,它能以正確的順序執(zhí)行一系列的任務(wù),計算如何達到你所指定的目標,而且被依賴的任務(wù)也僅需要運行一次。
- 這種流行的“慣例勝于配置”(convention over configuration)的原則意味著,只要項目按Maven指定的方式進行組織,它就幾乎能用一條命令執(zhí)行所有的構(gòu)建、部署、測試和發(fā)布任務(wù),卻不用寫很多行的XML。
- 功能驗收測試腳本會調(diào)用部署工具,將應(yīng)用程序部署到適當環(huán)境中,并準備相關(guān)數(shù)據(jù),之后再運行驗收測試。你還可再用一個腳本運行任何非功能測試,比如壓力測試和安全測試。
- 事實上,當你查看我們的部署系統(tǒng)時會發(fā)現(xiàn),它只是由一組非常簡單的、增量的步驟組成的復(fù)雜系統(tǒng),而這些步驟也是隨著項目的進行不斷完善的。我們想說的是,并不是完成所有的步驟之后才能獲得價值。事實上,當你第一次寫了一個腳本用于在本地的開發(fā)環(huán)境上部署應(yīng)用程序,并將其分享給整個團隊時,就已經(jīng)節(jié)省了很多開發(fā)人員的時間。
- 我們應(yīng)該遵循Java命名習慣,如包名用PascalCase方式,而類名使用camelCase方式。在代碼提交階段做代碼分析時應(yīng)利用一些開源工具(比如CheckStyle或FindBugs)來做檢查,迫使大家遵循這些命名習慣
- 單元測試應(yīng)該放在與包名相對應(yīng)的目錄中。也就是說,某個類的測試應(yīng)該與該類放在同一個包中
- 環(huán)境管理的核心原則之一就是:對測試和生產(chǎn)環(huán)境的修改只能由自動化過程執(zhí)行。也就是說,我們不應(yīng)該手工遠程登錄到這些環(huán)境上執(zhí)行部署工作,而應(yīng)該將其完全腳本化。
- 構(gòu)建中最常見的錯誤就是默認使用絕對路徑。這會讓構(gòu)建流程和某臺特定機器的配置形成強依賴,從而很難被用于配置和維護其他服務(wù)器。
- 假如我們已經(jīng)讓你深入理解了構(gòu)建腳本化,并使你了解到各種各樣的可能性的話(更重要的是激發(fā)你走向自動化),我們的目的也就達到了。
提交階段
- 對于開發(fā)人員來說,提交階段是開發(fā)環(huán)節(jié)中最重要的一個反饋循環(huán)。它會為開發(fā)人員引入的最常見錯誤提供迅速反饋。
- 修復(fù)那些在提交階段發(fā)現(xiàn)的問題,要比修復(fù)那些由后續(xù)運行大量測試的階段發(fā)現(xiàn)的問題簡單得多。
- 只有在某個錯誤讓提交階段的其他任務(wù)無法執(zhí)行時,我們才會讓提交階段停下來,比如編譯錯誤,否則就直至提交階段全部運行完后,才匯總所有的錯誤和失敗報告,以便可以一次性地修復(fù)它們。
- 有人認為,在提交階段結(jié)束時,應(yīng)該提供更豐富的信息,比如關(guān)于代碼覆蓋率和其他度量項的一些圖表。實際上,這些信息可以使用一系列閾值聚合成一個“交通燈信號”(紅色、黃色、綠色),或者浮動的衡量標度。比如,當單元測試覆蓋率低于60%就令提交階段失敗,但是如果它高于60%,低于80%的話,就令提交階段成功通過,但顯示成黃色。
- 隨著項目的進行,要不斷努力地改進提交階段腳本的質(zhì)量、設(shè)計和性能。一個高效、快速、可靠的提交階段是提高團隊生產(chǎn)效率的關(guān)鍵,所以只要花點兒時間和精力在這上面,讓它處于良好的工作狀態(tài),就會很快收回這些投入成本。
- 不能低估專家們的專業(yè)知識,但他們的目標應(yīng)該是建立并使用良好的結(jié)構(gòu)、模式和技術(shù),并將他們的知識傳授給交付團隊。一旦建立了這些基本規(guī)則,只有對腳本結(jié)構(gòu)進行較大修改時才需要他們的專業(yè)知識,而日常構(gòu)建維護工作不應(yīng)該由他們來做。
- 提交測試中,絕大部分應(yīng)由單元測試組成。單元測試最重要的特點就是運行速度非常快。有時候,我們會因為測試套件運行不夠快而令構(gòu)建失敗。第二個重要的特點是它們應(yīng)覆蓋代碼庫的大部分(經(jīng)驗表明一般為80%左右),讓你有較大的信心,能夠確定一旦它通過后,應(yīng)用程序就能正常工作。當然,每個單元測試只測試應(yīng)用程序的一小部分,而且無須啟動應(yīng)用程序。因此,根據(jù)定義,單元測試套件無法給你絕對信心說“應(yīng)用程序可以工作”,而這正是部署流水線后續(xù)部分的任務(wù)。
- 我們建議盡量消除提交階段測試中的異步測試。依賴于基礎(chǔ)設(shè)施(比如消息機制或是數(shù)據(jù)庫)的測試可以算做組件測試,而不是單元測試。更復(fù)雜、運行得更慢的組件測試應(yīng)該是驗收測試的一部分,而不應(yīng)該屬于提交階段。
- 打樁是指利用模擬代碼來代替原系統(tǒng)中的某個部分,并提供已封裝好的響應(yīng)。樁并不對外界作出響應(yīng)
- 在一些簡單的斷言中,你能指定測試中期望該模擬類作出什么行為。這是模擬技術(shù)和樁技術(shù)的根本不同。使用樁時,我們不需要關(guān)心樁是如何被調(diào)用的,而使用模擬對象時,可以驗證我們的代碼是否以期望的方式與模擬對象進行交互。
- 很容易落入一個陷阱,即為了支撐測試,精心地建立起一堆難以理解和維護的數(shù)據(jù)結(jié)構(gòu)。理想的測試應(yīng)該能很容易和快速地進行測試準備,而清理工作也應(yīng)該更快、更容易。對于結(jié)構(gòu)良好的代碼來說,其測試代碼往往也非常整潔有序。如果測試看起來繁瑣復(fù)雜,那可能是系統(tǒng)設(shè)計有問題。
自動化驗收測試
- 一旦正確實施自動化驗收測試,你就是在測試應(yīng)用程序的業(yè)務(wù)驗收條件,即驗證應(yīng)用程序是否為用戶提供了有價值的功能。驗收測試通常是在每個已通過提交測試的軟件版本上執(zhí)行的。
- 對于一個單獨的驗收測試,它的目的是驗證一個用戶故事或需求的驗收條件是否被滿足
- “驗收與我們的單元測試有什么區(qū)別?”其不同點在于驗收測試是針對業(yè)務(wù)的,而不是面向開發(fā)的。它能在一個類生產(chǎn)環(huán)境中的應(yīng)用程序運行版本上一次性地測試所有的故事。單元測試的確是自動化測試策略的關(guān)鍵部分,但是,它通常并不足以使人們確信程序能夠發(fā)布。而驗收測試的目標就是要證明應(yīng)用程序的確實現(xiàn)了客戶想要的,而不是以編程人員所認為的正確方式來運行的。雖然有時單元測試也會實現(xiàn)同樣的目標,但并不總是這樣的。
- 除驗收測試外,沒有哪種測試能夠基本上代替生產(chǎn)環(huán)境中的實際運行來證明軟件能為客戶提供他們所期望的業(yè)務(wù)價值。單元測試和組件測試都不測試用戶場景,因此也無法發(fā)現(xiàn)那種用戶與應(yīng)用程序進行一系列交互后呈現(xiàn)出來的缺陷。而驗收測試就是為這而設(shè)計的.
- 驗收測試在以下幾個方面也表現(xiàn)出不俗的查錯能力:線程問題、以事件驅(qū)動方式實現(xiàn)的應(yīng)用程序出現(xiàn)的緊急行為(emergent behavior),以及由架構(gòu)問題或環(huán)境及配置問題造成的其他類型的bug。這類缺陷很難通過手工測試發(fā)現(xiàn),更不用說單元測試和組件測試了。
- 選擇放棄自動化驗收測試的團隊會令測試人員的負擔非常重,測試人員必須在惱人且重復(fù)的回歸測試上花費相當多的時間。
- 根據(jù)我們的經(jīng)驗,與完全由開發(fā)人員編寫的自動化驗收測試相比,那些有測試人員參與編寫的自動化驗收測試能更好地發(fā)現(xiàn)用戶場景中的缺陷。
- 將可測試性銘記在心,寫出來的應(yīng)用程序就會有一個API,使GUI和測試用具(test harness)都能用它來驅(qū)動應(yīng)用程序。如果應(yīng)用程序能夠做到這一點的話,我們建議直接基于業(yè)務(wù)層執(zhí)行測試,這是一個合理的策略。唯一的要求就是開發(fā)團隊在這方面的紀律性,即讓表現(xiàn)層只負責展現(xiàn),不要涉足業(yè)務(wù)領(lǐng)域或應(yīng)用邏輯。
- 在迭代交付方法中,分析人員會花大量時間定義驗收條件。團隊用這些驗收條件來評判某個具體需求是否被滿足。
- 行為驅(qū)動開發(fā)的核心理念之一就是驗收測試應(yīng)該以客戶期望的應(yīng)用程序行為的方式來書寫。這樣,就可以拿這些寫好的驗收條件直接在應(yīng)用程序之上運行,來驗證它是否滿足規(guī)格說明了。
- 測試用例的工作就是讓應(yīng)用程序達到“假如”中所述的狀態(tài),然后執(zhí)行“當……”中所描述的動作,最后驗證應(yīng)用程序是否處于“那么”中所描述的狀態(tài)。
- 原子測試會創(chuàng)建它所需要的一切,并在運行后清理干凈。除了是否成功以外,不會留下其他東西。
- 剛接觸自動化測試的人會發(fā)現(xiàn),想讓代碼可測試,必須修改對它的設(shè)計,事實的確如此。
- 自動化測試會給你壓力,讓你的代碼更趨向于模塊化和更好的封裝性。但是如果你通過破壞封裝性讓它變得可測試,那么通常就會錯過達到同一目的的好方法。
- 自動化驗收測試與用戶驗收測試并不完全一樣。其中一個不同點就是:自動化驗收測試不應(yīng)該運行在包含所有外部系統(tǒng)集成點的環(huán)境中。相反,應(yīng)該為自動化驗收測試提供一個受控環(huán)境,并且被測系統(tǒng)應(yīng)該能在這個環(huán)境上運行。這里所說的“受控”是指,可以為每個測試創(chuàng)建正確的初始化狀態(tài)。如果與真正的外部系統(tǒng)集成,我們很可能就無法做到這一點。
- 令驗收測試失敗的構(gòu)建版本不能被部署。在部署流水線模式中,只有已經(jīng)通過這一階段的候選發(fā)布版本才能走向后續(xù)階段。而后續(xù)階段常常被認為是需要人為評判的:在大多數(shù)項目中,如果某個候選發(fā)布版本無法通過容量測試,就會有人來決定這次失敗是否足以嚴重到要取消這個候選版本的發(fā)布資格,還是讓它繼續(xù)走下去。可是,對于驗收測試,不應(yīng)該提供這種人為評定的機會。如果成功,就可以繼續(xù),如果失敗,就不能向前。
- 不斷運行這些復(fù)雜的驗收測試,的確會花費開發(fā)團隊很多時間。然而,根據(jù)我們的經(jīng)驗,這種成本投入是一種投資,會節(jié)省很多倍的維護成本。當對應(yīng)用程序進行大范圍修改時,它就是一張防護網(wǎng),而且軟件質(zhì)量也會得到保證。這也符合我們的總原則:將流程中的痛點盡量提前。
- 當某個驗收測試失敗時,團隊要停下來立即評估問題。它是一個脆弱的測試,還是由于環(huán)境配置問題,或者是由于應(yīng)用程序的某個修改使原有的假設(shè)不成立了,還是一個真正的失敗?然后,讓某人立即采取行動,使測試通過。
- 我們認為,持續(xù)地關(guān)注維護驗收測試套件,以保持它的良好結(jié)構(gòu)和連貫性是非常重要的,但是自動化驗收測試的全面性要比測試在10分鐘內(nèi)運行完成更重要。
- 通常,驗收測試套件花幾個小時而不是幾分鐘才能運行完。這是可以接受的,很多項目的驗收測試階段都要花幾個小時,但也運行良好。但是,仍舊有辦法可以提高效率。有一系列的技術(shù)能用來縮短從驗收測試階段得到運行結(jié)果的時間,從而提高團隊的整體效率。
- 自動化驗收測試通常要比單元測試復(fù)雜,需要更多的時間進行維護。而且,由于它在修復(fù)某個失敗與使所有驗收測試套件成功通過之間那種固有的滯后性,所以與單元測試相比,它處于失敗狀態(tài)的時間要長一些。
- 雖然在我們參與的項目中,確保驗收測試持續(xù)運行是一項很困難的工作,而且?guī)砹艘恍?fù)雜問題,但是,我們從來沒有后悔使用驗收測試。它使我們能對系統(tǒng)安全地進行大規(guī)模重構(gòu)。我們還堅信,在開發(fā)團隊中鼓勵關(guān)注這種測試的是軟件成功交付的有力武器。
- 手工測試是軟件行業(yè)中的一種基準,并且常常是一個團隊進行測試的唯一形式。我們發(fā)現(xiàn),手工測試的成本不但極其昂貴,而且也不足以確保生產(chǎn)出高質(zhì)量的軟件。當然,手工測試有其自己的位置,如探索性測試、易用性測試和用戶驗收測試和演示。人類生來就不適合做那種索然無味的、需要不斷重復(fù)但卻非常復(fù)雜的工作,然而,不幸的是,這些恰恰都是做手工回歸測試所需要的。這種低質(zhì)量過程必然生產(chǎn)出低質(zhì)量的軟件。
非功能需求的測試
- “性能”是對處理單一事務(wù)所花時間的一種度量,既可以單獨衡量,也可以在一定的負載下衡量。“吞吐量”是系統(tǒng)在一定時間內(nèi)處理事務(wù)的數(shù)量,通常它受限于系統(tǒng)中的某個瓶頸。在一定的工作負載下,當每個單獨請求的響應(yīng)時間維持在可接受的范圍內(nèi)時,該系統(tǒng)所能承擔的最大吞吐量被稱為它的容量。
- 把非功能需求與功能需求區(qū)別對待,就很容易把它從項目計劃中移除,或者不給予它們足夠的分析。然而,這可能就是一個災(zāi)難,因為非功能需求常常是項目風險的來源之一。在交付過程的后期才發(fā)現(xiàn)應(yīng)用程序因基本的安全漏洞或很差的性能而導(dǎo)致項目無法驗收,這種常見現(xiàn)象會導(dǎo)致項目推遲交付甚至被取消。
- 過早且過分地關(guān)注應(yīng)用程序的容量優(yōu)化是低效且昂貴的。而且,最終交付的應(yīng)用系統(tǒng)也很少是高性能的。更糟糕的是,它甚至可能讓項目無法交付。
- 現(xiàn)代軟件系統(tǒng)中,最昂貴的是網(wǎng)絡(luò)通信或磁盤存儲。在性能和應(yīng)用程序的穩(wěn)定性方面,跨進程或網(wǎng)絡(luò)邊界的通信是昂貴的,所以這類通信應(yīng)該盡量最小化。
- 為了能夠獲得項目成功,必須避免兩個極端:一是假設(shè)自己能在項目后期解決所有容量問題;二是因害怕未來可能出現(xiàn)的容量問題而寫一些具有防范性的、過分復(fù)雜的代碼。
- 如果對于應(yīng)用程序來說,性能或吞吐量是一個重要指標的話,我們就需要用一些測試來斷言系統(tǒng)能夠滿足業(yè)務(wù)需求,而不是通過技術(shù)經(jīng)驗來猜測某個特定組件的吞吐量應(yīng)該是多少。
- 假如對某應(yīng)用程序來說,容量或性能是一個非常關(guān)鍵的問題,那么就一定要有所投入,為該系統(tǒng)的核心部分準備一個生產(chǎn)環(huán)境的副本。使用相同的軟硬件規(guī)格要求,遵循我們關(guān)于如何管理配置信息的建議,以確保每個環(huán)境中都使用相同的配置文件,包括網(wǎng)絡(luò)配置、中間件及操作系統(tǒng)的配置。
- 要記住:代碼的修改對系統(tǒng)容量的影響與其對功能的影響一樣重要。當做了修改之后,要盡早掌握容量會下降多少,這樣就能快速且有效地修復(fù)它。這就要在部署流水線中加入一個階段,即容量測試階段。
- 我們要一直遵守這樣的格言,即做最少的工作達到我們的目標,這也是YAGNI(“You Ain’t Gonna NeedIt”)原則所暗示的。YAGNI提醒我們,增加防御性行為都有可能成為浪費。如果遵循高德納的格言,應(yīng)該直到明確需要優(yōu)化而且到了最后時刻才做優(yōu)化。另外,還要基于應(yīng)用程序運行時分析結(jié)果,直接解決最重要的瓶頸問題。
應(yīng)用程序的部署與發(fā)布
- 創(chuàng)建發(fā)布策略的最重要部分是在項目計劃階段就與應(yīng)用程序的所有干系人會面。討論的關(guān)鍵在于,要對整個應(yīng)用程序的生命周期中的部署與維護達成共識。然后把這個共識作為發(fā)布策略寫下來。在整個生命周期中,干系人應(yīng)該對該文檔進行更新和維護。
- 要讓軟件的部署活動能以一種可靠且一致的方式進行,其關(guān)鍵在于每次部署時都使用同樣的實踐方法,即使用相同的流程向每個環(huán)境進行部署,包括生產(chǎn)環(huán)境在內(nèi)。在首次向測試環(huán)境部署時就應(yīng)該使用自動化部署。寫個簡單的腳本來做這件事,而不是手工將軟件部署到環(huán)境中。
- 我們認為,項目首個迭代的主要目標之一就是在迭代結(jié)束時,讓部署流水線的前幾個階段可以運行,且能夠部署并展示一些成果,即使可展示的東西非常少。盡管我們不建議讓技術(shù)價值的優(yōu)先級高于業(yè)務(wù)價值的優(yōu)先級,但此時是個例外。你可以把這一策略看做實現(xiàn)部署流水線的“抽水泵”。
- 當制定發(fā)布回滾計劃時,需要遵循兩個通用原則。首先,在發(fā)布之前,確保生產(chǎn)系統(tǒng)的狀態(tài)(包括數(shù)據(jù)庫和保存在文件系統(tǒng)中的狀態(tài))已備份。其次,在每次發(fā)布之前都練習一下回滾計劃,包括從備份中恢復(fù)或把數(shù)據(jù)庫備份遷移回來,確保這個回滾計劃可以正常工作。
- 金絲雀發(fā)布就是把應(yīng)用程序的某個新版本部署到生產(chǎn)環(huán)境中的部分服務(wù)器中,從而快速得到反饋。就像發(fā)現(xiàn)一只煤礦坑道里的金絲雀那樣,很快就會發(fā)現(xiàn)新版本中存在的問題,而不會影響大多數(shù)用戶。像藍綠部署一樣,你要先部署新版本到一部分服務(wù)器上,而此時用戶不會用到這些服務(wù)器。然后就在這個新版本上做冒煙測試,如果必要,還可以做一些容量測試。最后,你再選擇一部分用戶,把他們引導(dǎo)到這個新版本上。有些公司會首先選擇一些“超級用戶”來使用這個新版本。甚至可以在生產(chǎn)環(huán)境中部署多個版本,根據(jù)需要將不同組的用戶引導(dǎo)到不同的版本上。
基礎(chǔ)設(shè)施與環(huán)境管理
- 強調(diào)合作是DevOps運動的核心原則之一。DevOps運動的目標是將敏捷方法引入到系統(tǒng)管理和IT運營世界中。這場運動的另一個核心原則是,利用敏捷技術(shù)對基礎(chǔ)設(shè)施進行有效管理。
數(shù)據(jù)管理
- 測試獨立性是指確保每個測試都具有原子性。也就是說,每個測試不應(yīng)該用其他測試的結(jié)果建立它的初始狀態(tài),并且其他測試也不應(yīng)該以任何形式影響該測試的成功或失敗
- 我們通過測試來斷言我們所開發(fā)的應(yīng)用程序的行為符合我們期望的結(jié)果。我們運行單元測試來避免剛做的修改破壞已有的應(yīng)用程序。我們運行驗收測試來斷言應(yīng)用程序交付了用戶所期望的價值。我們執(zhí)行容量測試來斷言應(yīng)用程序滿足我們的容量需求。可能,我們還會通過運行一套集成測試來確認應(yīng)用程序與其依賴的第三方服務(wù)可以正常通信。
組件和依賴管理
- 對于“應(yīng)用程序功能的可用性”這個問題,持續(xù)集成可以給你某種程度上的自信。而部署流水線(持續(xù)集成的擴展)用于確保軟件一直處于可發(fā)布狀態(tài)。但是,這兩個實踐都依賴于一件事,即主干開發(fā)模式[插圖]。
- 為了在變更的同時還能保持應(yīng)用程序的可發(fā)布,有如下四種應(yīng)對策略。? 將新功能隱蔽起來,直到它完成為止。? 將所有的變更都變成一系列的增量式小修改,而且每次小的修改都是可發(fā)布的。? 使用通過抽象來模擬分支(branch by abstraction)的方式對代碼庫進行大范圍的變更。? 使用組件,根據(jù)不同部分修改的頻率對應(yīng)用程序進行解耦。
- “通過抽象來模擬分支”是一次性實現(xiàn)復(fù)雜修改或分支開發(fā)的替代方法。它讓團隊在持續(xù)集成的支撐下持續(xù)開發(fā)應(yīng)用程序的同時替換其中的一大塊代碼,而且這一切都是在主干上完成的。如果代碼庫的某一部分需要修改,首先要找到這部分代碼的入口(一個縫隙),然后放入一個抽象層,讓這個抽象層代理對當前實現(xiàn)方式的調(diào)用。然后,開發(fā)新的實現(xiàn)方式。到底使用哪種實現(xiàn)方式由一個配置選項來決定,可以在部署時或者運行時對這個選項進行修改。
- 區(qū)分組件和庫:庫是指團隊除了選擇權(quán)以外,沒有控制權(quán)的那些軟件包,它們通常很少更新。相反,組件是指應(yīng)用程序所依賴的部分軟件塊,但它通常是由你自己的團隊或你公司中的其他團隊開發(fā)的。組件通常更新頻繁。
- 一個相當有爭議的陳述是這樣的:“組件是可重用的代碼,它可以被實現(xiàn)了同樣API的其他代碼所代替,同時可獨立部署,并封裝了一些相關(guān)的行為和系統(tǒng)的部分職能。”
- 依據(jù)功能領(lǐng)域而不是組件來組建團隊確保了每個人都有權(quán)力修改代碼庫的任何部分,同時在團隊之間定期交換人員,確保團隊之間有良好的溝通。這種方法還有一個好處,即確保所有的組件能組合在一起正常工作是所有人的責任,而不只是最后負責集成的那個團隊的責任。
版本控制進階
- 分支的唯一目的就是可以對代碼進行增量式或“通過抽象來模擬分支”方式的修改。
- 如果一個團隊的不同成員在不同分支或流上工作的話,那么根據(jù)定義,他們就不是在做持續(xù)集成。讓持續(xù)集成成為可能的一個最重要實踐就是每個人每天至少向主干提交一次。因此,如果你每天將分支合并到主線一次(而不只是拉分支出去),那就沒什么。如果你沒這么做,你就沒有做持續(xù)集成。
- 在開發(fā)過程中,通過頻繁向主干提交的方式做這種增量式修改幾乎總是最正確的做事方法,所以請一直把它作為備選列表中的第一項。
- 從一個代碼庫上挑選一些變更發(fā)送給另一個代碼庫,這個過程叫做摘櫻桃(cherry-picking)。也就是說,與其總是要合并整個分支,不如只合并想要的那些特性.
持續(xù)交付管理
- 通過確保交付團隊能得到應(yīng)用程序在類生產(chǎn)環(huán)境上的不斷反饋,是部署流水線達成“執(zhí)行度”這個目標的方法和手段。部署流水線使交付流程更加透明,來幫助團隊達成符合度。
- 團隊組建與磨合常常會經(jīng)歷五個階段:創(chuàng)建期(forming)、風暴期(storming)、規(guī)范期(norming)、運轉(zhuǎn)期(performing)和調(diào)整/重組期(mourning/reforming)
- “啟動階段”是對開始寫產(chǎn)品代碼前這段時間最簡單的描述。一般來說,此時會對需求進行收集和分析,并對項目的范圍和計劃進行初步規(guī)劃。
- 迭代開發(fā)提供的是項目進展情況的客觀度量,它是用開發(fā)團隊能夠供給用戶可工作的軟件,并且該軟件完成了多少被用戶認可,滿足用戶目標的功能來衡量項目進度的。
- 對于每個項目的成功來說,管理都是至關(guān)重要的。良好的管理所創(chuàng)建的流程令軟件更高效地交付,同時確保風險被適當?shù)毓芾?#xff0c;規(guī)章制定被嚴格遵守。
總結(jié)
以上是生活随笔為你收集整理的CI/CD笔记:《持续交付:发布可靠软件的系统方法》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: r型电源变压器的哪些参数很重要?
- 下一篇: 搞掉Windows Media Play