因為現(xiàn)在項目在開發(fā)新的API,我需要根據(jù)API方法論去校驗這個API的計算邏輯和計算結(jié)果是否正確,而且需要將計算邏輯用Excel記錄下來,所以就用了Excel的VBA。
1. 什么是VBA?

具體含義大家可以看百度百科,我就直接上圖了,每個單元格都是調(diào)用了VBA的宏計算語言函數(shù),我就簡稱這個Excel含有macro計算邏輯吧。
2.問題是什么?
大家都知道要比較一個API的準確性,我們需要自己根據(jù)方法論去把所有原始數(shù)據(jù)都推演計算一遍,得到結(jié)果。然后在跟開發(fā)做的API response做下對比,如果兩個結(jié)果相同,則表示這個API計算正確。
現(xiàn)在我們PO不讓我重寫一遍開發(fā)的計算邏輯了,規(guī)定所有計算相關(guān)的邏輯都在Excel里面做好計算模板sheet,然后我將所有原始數(shù)據(jù)都放到計算模板同一個文件夾下。在含有Marco計算邏輯的那個excel(計算模板sheet)里面完成數(shù)據(jù)的引用和計算。
然后將API返回的Response也寫入到同目錄下的一個Excel中(樣式跟計算模板計算出來的結(jié)果相同),模板里面將比較API response和Excel中的計算結(jié)果,然后輸出一個如上圖一樣的一個sheet頁(二維矩陣,單元格里的內(nèi)容是TRUE或者FALSE)。
我要做的就是:將原始數(shù)據(jù)放到規(guī)定名字和格式的Excel中,將最終API的response也放到Excel中,然后打開這個含有macro函數(shù)的excel,查看sheet頁中是否含有FALSE,如果有,告訴對應的行和列名稱并輸出。若是沒有FALSE,這說明比對通過,API pass。
難點是:
我用Python寫函數(shù),現(xiàn)在Python用pandas打開這個含有Macro函數(shù)的Excel后,讀出的數(shù)據(jù)永遠都是Nan,因為它不能識別那些macro函數(shù)。。。所以我無法判斷該API是否pass。
3. 手動操作Excel的時候要怎樣看到是TRUE或FALSE呢?

在打開這個有macro函數(shù)的Excel之前,我們需要打開所有它引用的其他Excel。然后回到這個Excel的時候,這些宏會自動引用其他excel相應的數(shù)據(jù),并得出計算結(jié)果。
4. 用Python要怎樣實現(xiàn)這一手動邏輯呢?
在Python中調(diào)用VBA去控制這些Excel即可。
5. 具體要怎樣實現(xiàn)呢?
a. 下載Python擴展包: pywin32 (這個有32和64位之分)
可以直接去下載zip文件,然后安裝;
但我建議直接用命令: pip install pywin32?
b. 在自己python文件中引用: ?from win32com import client
from win32com import client
c. 在python中寫VBA:
#打開Excel應用,并且依次打開該計算模板Excel依賴的所有excel文件,然后打開最終計算模板excel
xlApp = client.Dispatch('Excel.Application')
# xlApp.visible默認是0,就是不顯示所有Excel文件窗口哦
xlApp.visible = 1
# Open original excels in the given absolute path one by one
suite_name = suite_path.split(".")[-1]
file_names = filter(lambda x: x.find("File") > -1, input_params.keys())
for file_name in file_names:
? ? # excel = pd.ExcelFile("OutputExcel/%s/%s" % (suite_name, input_params[file_name]))
? ? xlApp.Workbooks.Open(r"%s\APG_API_RobotFramework\OutputExcel\%s\%s" % (workspace_path, suite_name, input_params[file_name]))
# Open the result excel and check data
xlBook = xlApp.Workbooks.Open("%s\APG_API_RobotFramework\OutputExcel\%s\%s" % (workspace_path, suite_name, RESULT_EXCEL))
xlsheet = xlBook.Worksheets("Result")
# 操作Excel可能會出錯,所以需要用到try, finally結(jié)構(gòu)塊
try:
? ? # Store calculation result into result_list
? ? rows = xlsheet.UsedRange.Rows.Count
? ? columns = xlsheet.UsedRange.Columns.Count
????# 讀取做好的比較數(shù)據(jù)模板sheet頁中的數(shù)據(jù)并放入二維數(shù)組中
? ? result_list = []
? ? for row in range(1, rows):
? ? ? ? temp_list = []
? ? ? ? for column in range(1, columns):
? ? ? ? ? ? temp_list.append(str(xlsheet.Cells(row, column)))
? ? ? ? result_list.insert(row-1, temp_list)
? ? # print result_list
? ? # Get row and column title, then remove titles' values and put left values into new_list
? ? row_title = [x[0] for x in result_list][1:]
? ? column_title = [y for y in result_list[0]][1:]
? ? # print("row title : ", row_title)
? ? # print("column title :", column_title)
? ? new_list = []
? ? for x in result_list[1:]:
? ? ? ? new_list.append(x[1:])
? ? # print new_list
????# 因為最終要提示用戶FALSE單元格對應的行和列名稱,所以我用pandas來構(gòu)造DataFrame,這樣效率很高
? ? # Put data into DataFrame then select values which are "FALSE"
? ? df = pd.DataFrame(data=new_list, index=row_title, columns=column_title)
? ? fail_list = []
? ? for index, row in df.iterrows():
? ? ? ? if row[0] == "False":
? ? ? ? ? ? fail_list.extend([index, row[0]])
????# 若找到FALSE單元格,則提示具體錯誤信息,否則打印比較成功的提示
? ? assert fail_list.__len__() == 0, "Failed cells are : "+str(fail_list)
? ? print "Compare successfully !"
finally:
? ? # Don't let the save dialog pop up when close (Since the result excel shouldn't be saved)
? ? xlApp.DisplayAlerts = 0
? ? # xlBook.Save()
? ? xlBook.Close()
? ? xlApp.Workbooks.Close()
? ? # xlApp.visible = 0
? ? xlApp.Quit()
finally中的語句非常關(guān)鍵,相當于open一個文件之后進行讀寫,最終一定要關(guān)閉對應的io流一樣!
那個計算模板是不允許改動的,所以在關(guān)閉那個xlBook的時候總是提示是否需要保存,在Jenkins上配置這個Project之后,所有相關(guān)操作肯定是無法手動干預的。所以我就采取了最直接的方式:
xlApp.DisplayAlerts = 0 ?
就是不彈出所有提示框。
先關(guān)閉計算模板Excel,然后關(guān)閉該Excel依賴的所有其他Excel。
最后退出Excel應用程序。
(若是最后退出程序以后發(fā)現(xiàn)還有一個空白的Excel窗口,這時候可以用 xlApp.visible=0 來隱藏)
所有這些都執(zhí)行完了以后,這些被操作過的文件就不會被鎖住了。(若是被鎖住,以后用python讀取的時候都會提示IOException哦~~)
最終的表現(xiàn)是:
系統(tǒng)會在運行該函數(shù)的時候先打開所有依賴的Excel文件,并打開最終的計算模板,在后臺讀出模板中比較數(shù)據(jù),然后查看是否有FALSE單元格,并關(guān)閉所有打開過的Excel,一切都是自動化的哦~
RobotFramework Test Case如下:

因為項目太忙了,所以寫的都是流水賬,如果大家有什么更好的建議或者疑問,可以給我留言哦,謝謝閱讀~~