軟件開發過程自動化原理及技術
一個簡單完整的自動化示例
1 概述
關於本文,最開始只是想寫一些關於 軟件自動化測試開發 的文章,但是后來寫着寫着,發現不先在宏觀上的軟件開發過程進行介紹,不會引起大家對 自動化 技術形成了解和重視。所以本文從軟件工程宏觀層次進行了介紹,並和傳統的實現方法做了一些對比,並附了一些代碼,讓有興趣的朋友對自動化的理念及具體的實現技術手段有一些初步的認識。
既然是要 自動化 那么肯定就是沖着 效率 來的。在正式開始系統化的自動化技術學習之前,先來一個完整的示例來有個對 自動化 的概念整體認識。
2 使用場景
可以先定義一個最簡單的場景:提供第三方前端js庫的產品(例如: jQuery)。
使用過 jQuery 的人,可以很清楚這樣的產品具有如下的特征:
- 靜態文件支持CDN方式的在線引用,可以不必下載成離線文件
- js文件后面有版本號標識
- 靜態文件是增量式發布,而非覆蓋替換式
下面是一些jquery的備注,方便讀者了解前面所談到的一些特點的具體表現形式。
jQuery 的CDN在線引用的方式
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
每個 jQuery 的庫文件都帶有版本號,例如: jquery-2.1.4.min.js
如果有新的文件版本發布,則增加一個帶新版本號的文件即可。
基本上這樣的產品的開發和上線的步驟如下:
- 開發工程師本地開發好js項目,並做好單元測試和功能性自測
- 使用構建工具打包成js文件(為簡化問題,此處假設最終只有一個文件)
- 發布工程師收到構建好的文件,向公網上發布靜態文件
- 檢查靜態文件是否成功部署成功且能正常被公網訪問
3 傳統方案
在前面所定義的步驟里面,傳統的方案就是:
-
開發人員開發完畢,並進行簡單自測,和 手動 功能測試
-
開發人員利用IDE 手動 打包
-
發布工程師將構建后的文件 手動 復制到公網服務器指定目錄
-
- 發布工程師在瀏覽器里面 手動 輸入文件的公網鏈接,確定可以訪問到相應的資源
-
有可能出現公網文件權限或者服務器配置問題,導致即使文件在那個位置,但是不一定能夠訪問到。比如出現 403forbidden 的情況
這樣的過程都是要通過程序員去手動完成,在現在講究快速迭代的軟件研究趨勢下,長期這樣手動重復的后果就是:
- 一直手工操作導致效率低下
- 重復工作會扼殺人的創造性
對於會持續做加法迭代的有穩定產品線路的項目,最好還是能夠做自動化的的操作,一方面是為了解放程序員,另外一方面也確實提升效率以適應現在的快速開發和迭代的客觀需求。
4 自動化方案
4.1 自動化單元測試
其實開發人員在開發過程,就是為了讓程序能夠達到預期的目標,那么就肯定是存在一定的自測過程。但是僅僅是當時自測之后是不行,還需要對於核心的算法函數進行單元測試代碼的編寫,以保證后續的迭代和重構的時候,不會出現拆東補西的情況。
此時的情況是:
- 核心函數---- 自動化 單元測試
- 界面功能---- 手動 功能性自測
一般情況,功能測試都特指 端到端 的直接面向用戶的界面型測試,由於界面存在太多的不確定性,這一塊不是適合編寫自動化測試代碼的,雖然對於界面的自動化已經有一部分的腳本錄制工具或者開發工具,但是都不提倡。
注意
自動化測試涉及到自動化代碼的編寫,這部分的額外付出成本是在 回歸測試 的時候收回的,回歸的次數越多,邊際成本就越小。所以只有相當穩定下來的功能才有回歸的價值。
由於目前很多產品的開發,都不再是獨立的系統,都往往會存在一些外部調用的接口,所以在自動化打包構建之前,還要在測試環境下進行接口測試。此處的在做自動化方案的時候,基本原理和單元測試差不多,所以本文略去不表,后面會專門有專門介紹自動化測試部分的內容。
4.2 自動化打包構建
有相當多的IDE提供了一些打包的可視化操作工具。但是這些工具需要人工在IDE里面根據向導,進行一步步地點擊操作,這樣的做的好處就是降低了打包構建的門檻,普通人也可以在不了解原理,不用編寫構建代碼的情況下,也能完成相應的構建工作。當然缺點就是: 無法實現無人值守的自動化。
基本上現在各種語言都有自己相應的成熟的構建工具,本文所舉的前端的開發的例子,就有 grunt 這樣的打包構建工具。
可以完成的自動化任務有:
- 去除掉js源碼里面的注釋
- 壓縮js
- 混淆js
- 合並文件
通過寫好相應的配置文件,運行grunt的相應參數命令,可以很好地實現開發構建階段的自動化工作流。
4.3 自動化發布
自動化發布的具體實現技術手段有很多種。
像腳本型的語言(php,python,nodejs)可以使用 Git 這樣的版本管理工具,使用調用shell命令,或者第三方操作庫(例如python語言的Gitpython)可以實現代碼的自動化部署。
對於一些構建的產物本身是很大的二進制文件的,比如exe文件,或者Android的apk應用,動轍是幾百M的,顯然不適合使用Git這樣的精細化的版本管理工具來進行發布。可以使用FTP或者SSH的第三方編程接口進行自動化的發布。此處可以推薦一款基於python的三方擴展 fabric,可以完成文件的遠程傳輸及遠端的服務器的命令行操作。
本文的的jQuery靜態js發布方案使用整體文件上傳到公網服務器的方式(使用fabric工具),以基本的流程如下:
- 掃描自動化構建的目錄
- 使用fabric上傳文件到N台指定的服務器的相應目錄
- 使用fabric操控N台服務器設置靜態文件的權限
以下是一段代碼示例(將本地的某個目錄下的文件上傳分發到N台服務器,並進行簡單的設置):
#!coding:utf8 """ 自動上傳文件到靜態服務器上,和測試服務器上面 """ from __future__ import with_statement import sys import os from fabric.api import lcd from fabric.operations import put, run from dtlib.dtlog import dlog server_folder_path = '/static_folder' local_folder_path = server_folder_path user_name = 'xxx'#服務器登錄用戶名 server_ssh_pwd = 'xxxxxxxx'#服務器登錄密碼 lcoal_dirlist = [] #所有的需要上傳文件的服務器的登錄信息列表 server_list = [ # (host,user,password) ('192.168.1.201', user_name, server_ssh_pwd), ('xxx.xxx.xxx.xxx', user_name, server_ssh_pwd) ] def scandir(): """ 上傳本地某個目錄到服務器的指定目錄 :return: """ list = os.listdir(local_folder_path) for i in list: dirpath = os.path.join(local_folder_path, i) if os.path.isdir(dirpath): lcoal_dirlist.append(i) dlog.debug(lcoal_dirlist) for j in lcoal_dirlist: dlog.debug("subdir:" + j) with lcd(local_folder_path): run('uname -s') put(j, server_folder_path, use_sudo=True) # 上傳本地文件到服務器端 # 在遠程機器上批量修改文件權限 run('chmod a+rw %s/js/jquery-2.1.4.min.js' % (server_folder_path)) # 修改文件權限為可讀寫 run('cp %s/js/jquery-2.1.4.min.js %s/js/jquery-2.1.4.min.js' % (server_folder_path, server_folder_path)) print '%s has synced' % j if __name__ == '__main__': currentpath = sys.path[0] for item in server_list: fab_cmd = 'fab -f scp_static.py -H %s -u %s -p %s scandir' % (item[0], item[1], item[2]) dlog.debug(fab_cmd) os.system(fab_cmd)
4.4 自動化檢測發布結果
關於指定的版本的靜態文件是否發布成功,最后還需要一道檢測,才能實現 閉環。當然,根據不同的要求,檢測的用例也會不同。一般情況下,如果前面的流程都比較規范,此處就不太需要對功能進行太多檢測了,但是需要對發布結果進行檢測:檢測指定版本的js是否能夠成功被公網訪問。
一般人可能不太理解,之前不是已經完成發布了么,此處為何還要多此一舉?經驗告訴我們,一個 開環 的系統的結果往往是存在不可預知的,往往是不可信的。特別是在遠程發布的時候,網絡環境穩定性、服務器的硬件配額(磁盤容量已滿)、web服務器配置(權限問題)都會成為發布失敗的原因。只有形成 閉環 才會形成可靠的交付。
發布的目的不是執行發布的流程,而是最終能夠讓開發產出物能夠提供正常的服務。
關於 jQuery 是否發布成功,本文設計了兩個測試用例:
- 能夠Http請求到正常的js源碼
- jQuery的頭部信息里面支持跨域
手工的檢測方式是在瀏覽器輸入鏈接:
https://code.jquery.com/jquery-2.1.4.min.js
觀看瀏覽器的顯示結果。
顯然:
-
瀏覽器的內容框里面顯示了正常的返回了js的內容
-
- 瀏覽器的調試框里面也可以看到頭部信息里面是支持跨域的
-
當然此處還是使用了稍微高級的數據層面的檢測方式,如果不了解http的原理,可能還會專門做一個測試頁面,看能夠正常加載到js文件。
這樣太耗時,所以本文推薦自動化的方案。上面的手式的方式,其實本質上就是利用瀏覽器對指定的http鏈接發起請求,然后用眼睛來判斷返回的數據結果,這一切都可以通過程序來實現。
做自動化的首要本領就是要會 透過現象看本質 ,即 透過界面看數據,以上兩個用例的主要的技術原理:
- 請求js資源,Http返回的狀態碼是200。當然如果要更精細化,可以對其返回內容做進一步嚴格的判斷。
- Http的請求頭部數據里面的 access-control-allow-origin 字段的值為 * (星號通配符)
下面貼上一段python的 pyunit 框架下的自動化檢測代碼:
# coding:utf-8 """ 測試靜態服務器文件是否發布成功 """ import requests import unittest __author__ = 'Harmo' class StaticServerTest(unittest.TestCase): """ 靜態文件請求 """ def setUp(self): pass def tearDown(self): pass def test_jquery_js_release(self): """http是否正常返回 :return: """ test_js_url = 'https://code.jquery.com/jquery-2.1.4.min.js' res = requests.get(test_js_url) self.assertEqual(200, res.status_code, msg='檢查是否正常返回') def test_http_static_allow_origin(self): """http下不應該支持跨域 :return: """ test_js_url = 'https://code.jquery.com/jquery-2.1.4.min.js' res = requests.get(test_js_url) self.assertNotEquals('*', res.headers["access-control-allow-origin"], msg='http不允許跨域')
上面的代碼是兩個小的自動化測試用例,為了作為對比,特意 做了一個運行成功的例子(成功請求到文件)和一個運行失敗的檢測例子(要求文件支持跨域,其實jquery是應該支持跨域引用的)。
為了簡單起見,在IDE下面運行此測試代碼並查看結果:
檢測服務器上面的靜態庫文件是否加載成功。 當然,正常的結果應該是這樣全成功的狀態:
如果檢測通過,那么就證明是成功發布了。
5 總結
本文的目的是為了說明什么叫自動化及自動化的好處,前面所介紹的內容的范圍並不局限於“測試自動化”,但是最后的落腳點還是要到 自動化測試 及現在高級的 測試 職責:持續集成。
自動化測試 還有如下一些需要深入研究的地方:
-
- 對不同的測試用例進行數據的抽象化,以達到自動化實現的目的
-
這需要比較扎實的計算機的基礎知識
-
- 能夠通過代碼組織好成規模(比如幾千幾萬)的自動化測試腳本
-
這個就需要一定的軟件工程基礎和系統開發能力
-
能夠掌握和其它系統集成的能力以達到持續集成的全自動化軟件生產過程
這些技能也不是此處簡單的只言片語就能道盡的,本文只能作為一個引子來進行后續內容的預熱吧。
持續集成 也是建立在前面所介紹的各個環節形成自動化之后,然后再使用一定的技術手段,將這一系列事件進行被扣,來觸發下一事件,從而環環相扣,形成穩定的軟件生產自動化 流水線。形成持續穩定的軟件交付物。
至於 持續集成 的好處,可以使用一個制造業的例子來描述:
1913年,福特將 流水線 應用到汽車組裝中,第一條流水線使每輛T型汽車的組裝時間由原來的12小時28分鍾縮短至10秒鍾,生產效率提高了4488倍!
在現代軟件工業領域也需要這樣:先自動化,然后持續集成,才可以實現快速迭代,以產生巨大的生產力,符合現代人對軟件工程的預期。希望相關從業人員一起努力吧,提升自己的知識結構的競爭力,也提升整體的行業的生產力。
(未完,待續。。。)
作者: | Harmo哈莫 |
---|---|
作者介紹: | https://zhengwh.github.io |
技術博客: | http://www.cnblogs.com/beer |
Email: | dreamzsm@gmail.com |
QQ: | 1295351490 |
時間: | 2015-11 |
版權聲明: | 歡迎以學習交流為目的讀者隨意轉載,但是請 【注明出處】 |
支持本文: | 如果文章對您有啟發,可以點擊博客右下角的按鈕進行 【推薦】 |