「我只是修改了一個 if 條件,沒有想到它致使持續集成失敗,部署也所以失敗,還影響了 QA 測試其它功能。」css
Web 應用的質量提高,是一個很是有意思的話題。咱們明知道有一系列的手段能夠提高代碼質量,可是限於多種緣由,咱們並不會去作。在我工做的第一個項目裏,因爲你們都是年輕人(Junior Consultant),咱們實施了一系列的基礎措施,來提高應用質量,諸如寫測試、追求測試覆蓋率、運行預提交腳本等等。前端
在最近的這個項目裏,咱們面臨着相似的問題——須要提高項目的代碼質量。因而,便想寫一篇文章介紹一個相關的內容。這篇文章大體能夠分爲這幾個部分:git
那麼,讓咱們繼續回到老生常談的 「Web 應用的質量問題」。bash
Web 應用一般面臨着上線和質量之間的博弈——只要不影響用戶體驗,小的 Bug 每每對於項目來講能夠 「容忍」 的。這樣一來講能夠早些上線,實現用戶價值。除此還有其開發的影響:一個是敏捷方式的開發週期,一個則是能夠屢次上線。app
故而,Web 開發與一些特殊領域及行業的軟件開發不一樣,在這些特殊的行業裏,一個開發成本上億的軟件,可能只會運行、部署一次,不會有第二次機會,如原子彈的控制系統。還有一些類型的案例,就是智能汽車上的自動駕駛系統,稍有不慎就是車損人忙。至關於 Web 應用雖然更新困難,可它們仍是能遠程更新的。可是在這些系統上,它們就更追求系統的質量,而不是開發速度。Web 應用部署失敗能夠回滾,雖然會帶來必定的錢力損失,可是極少帶來生命危險。編輯器
所以在質量和速度方面,在 Web 開發上所以保持着一個微妙的平衡。函數
可軟件開發不只僅只有質量和速度的問題,還有一個產品問題——即,能作出符合用戶需求的產品。因而,就變成了質量-速度-需求,一個更復雜的平衡。爲了交付出更符合用戶需求的產品,就不得不常常作一些需求變動。而取決於這些變動的時間,它每每會影響到代碼質量和開發速度——實現一個需求的時間越短,那麼其測試的時間越短,Bug 出現的可能性就更高。過去我遇到過,今晚上線,下午臨時改需求。可想而知,測試人員是沒有時間測試的。工具
在這個時候,持續集成只能顯式地告訴咱們,咱們的測試掛了,咱們的某些功能 broken 了,咱們不該該部署這個新版本。然而並非持續集成出問題了,咱們就不能部署,咱們仍然仍是能部署的。post
Blabla,那麼問題來了,最有效的方式呢?單元測試
用於保證這個項目的質量,在代碼提交以後,會通過一系列的測試:
若是隻是宏觀來看一個項目的測試的話,那麼在一個敏捷項目裏,測試能夠分爲這麼幾個階段:
若是一個 Web 應用能通過這麼一系列的測試,那麼它的質量在必定程度上是獲得保障的。因此,開發人員若是不想活得過久,就能夠 「不負責任」 地直接把功能扔給測試人員。笑~
但是,在有一些公司時吧,Bug 率但是會影響績效的,又或者是有這麼多 Bug 看上去不那麼專業,等等 blabla。
言而總之,總而言之,開發人員本身寫測試會更友好一些。按照測試金字塔理論來講,咱們須要三種類型的測試:
對於一個前端項目來講,咱們一般只須要兩種:單元測試
和 E2E 測試
。實際上,理論上應該還有 UI 組件的測試
,可是通常而言,咱們在選用 UI 組件的時候,會考慮到組件的穩定性。
但是在多數國內公司裏,寫測試每每是不可能的。退而求次,咱們就須要一種更簡單而友好的方式,來作這樣的事情。
在代碼提交以前,咱們還能夠進行一些常見的操做:
現代的編輯器(使用相應插件)、IDE 能夠提升很好的技術手段,在開發的過程當中靜態代碼分析,並隨時提升建議。如 Intellij IDEA 和 WebStorm 就會根據 TSLint,來提醒開發者 TypeScript 代碼的一些規範問題。
這些分析工具主要進行一些代碼上的分析,如《全棧應用開發:精益實踐》一書所說,通常會進行以下一系列的風格檢測:
而這些規範,若是沒有強制,那就是個遊戲。因而,咱們一般會依賴於 Git Hooks 來作這樣的事。對於一個使用 Git 來管理源碼的項目來講,Git Hooks 能夠作這麼一些事情,能夠在 .git/hooks
目錄下查看:
applypatch-msg post-merge pre-auto-gc prepare-commit-msg
commit-msg post-receive pre-commit push-to-checkout
post-applypatch post-rewrite pre-push update
post-checkout post-update pre-rebase
post-commit pre-applypatch pre-receive
複製代碼
通常而言,咱們只會在兩個階段作相應的事情:
pre-commit
,預本地提交。一般會在該提交以前,進行一些語法和 lint 的檢測。pre-push
,預遠程提交。一般會在該提交以前,運行一些測試。因而,在咱們的這個前端項目裏,咱們就又寫了這兩個 scripts
。對應的實現以下:
{
"precommit": "lint-staged",
"prepush": "ng test && ng build --prod"
}
複製代碼
在 precommit
時,咱們配合 lint-staged
和 prettier
來進行代碼格式化:
"lint-staged": {
"src/app/*.{css,scss}": [
"stylelint --syntax=scss",
"prettier --parser --write",
"git add"
],
"{src,test}/**/*.ts": [
"prettier --write --single-quote",
"git add"
]
}
複製代碼
事實上,使用 ng lint --fix
也是一個不錯的方式。
隨後,咱們在 push 代碼以前,即 prepush
,進行了測試及 Angular 的構建 production 的腳本。因爲單元測試運行得至關的快,它能夠在幾分鐘內完成,快速對問題作出響應。而不是等到持續集成出問題時,再去修復。
可是 Git 提升了這一種的種選項,也提供了一個 --no-verify
的參數。它可讓開發者不須要進行上面的驗證,就能提交代碼。
咱們每每沒法阻止別人作這樣的事情,特別是當出現多個團隊協做的時候。
本來,我想將標題取爲 「有風險的提交」,可是我以爲危險的提交更爲可靠。
常見的有要去吃飯了、要下班了、要開會了等等,臨走前提交了一下代碼。功能可能自己沒有問題,可是它 block 後續的一系列行爲。
固然了出現不可坑的因素,如地震、火災等的時候,就不須要考慮這些事情了。
只是有了這些規範和實踐,能夠幫助咱們開發出更穩定的 Web 應用。
開發速度和質量,是一個難以平衡的天平。在不一樣的時間裏,咱們應該作不一樣的技術決策。