seleinum框架
框架的思想:
解決我們測試過程中的問題:大量的重復步驟,用自動化來實現
1)配置和程序的分離
2)測試數據和程序的分離
3)不懂編程的人員可以方便使用:使用的時候不需要寫程序
4)有日志功能,實現無人值守
5)自動發報告
6)框架中不要有重復的代碼,實現高度的封裝和復用
推薦使用關鍵字驅動、混合驅動
為什么要編寫程序呢?
通用性的東西滿足不了個性化的需求
測試的工具:python+selenium
接口測試用例:excel
一、搭建自動化測試的目錄結構
分層如下:
1、Action包: 放置關鍵字文件
2、Config目錄: 所有配置文件,日志的配置文件;把所有的項目相關的配置均放到這里,用python支持較好的配置文件格式ini進行配置。實現配置與代碼的分離
3、Projvar包:項目所有的公共變量,如:目錄、自定義變量名稱;
4、ScreenCapture目錄:存放截屏目錄,按照年月日小時來建目錄;
5、TestData目錄:放測試將數據文件,可以把所有的testcase的參數化相關文件放在這里,一般采用xlsx、xml等格式。實現數據與代碼分離;
6、TestScript包:測試腳本,主程序
7、Util包:封裝的公共的類,包括讀取config的類,寫log的類,讀取excel、xml
的類、生成報告的類(如HTMLTestRunner)、數據庫的連接、發送郵件等類和方法,都在這里
8、ReadMe.txt(加個說明性文件,告訴團隊框架需要使用的環境及方法)
二、搭建步驟
1、在ProjVar包創建一個var.py用來存放公共變量
import os #瀏覽器驅動存放的位置 firefoxDriverFilePath = "e:\\geckodriver" chromeDriverFilePath = "e:\\chromedriver" ieDriverFilePath = "e:\\IEDriverServer" # 當前文件所在目錄的父目錄的絕對路徑 ProjDirPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) test_step_id_col_no = 0 test_step_result_col_no = 8 test_step_error_info_col_no = 9 test_step_capture_pic_path_col_no = 10 test_case_id_col_no= 0 test_case_sheet_name=2 test_case_is_executed_flag_col_no= 3 test_case_is_hybrid_test_data_sheet_col_no=4 test_case_start_time_col_no= 6 test_case_end_time_col_no= 7 test_case_elapsed_time_col_no= 8 test_case_result_col_no = 9 if __name__=="__mian__": print(ProjDirPath)
2、在Utli包里面創建公共的類、函數
2.1封裝excel的類
from openpyxl import * import os.path from openpyxl.styles import NamedStyle,Font, colors from ProjVar.var import * from Util.FromatTime import * class Excel: def __init__(self,excel_file_path): if os.path.exists(excel_file_path): self.excel_file_path = excel_file_path self.wb = load_workbook(self.excel_file_path) else: print("%s e文件的路勁不存在,請重新設定!" %excel_file_path) #通過sheet名字來獲取操作的sheet def set_sheet_by_name(self,sheet_name): if sheet_name in self.wb.sheetnames: self.sheet = self.wb[sheet_name] else: print("%s sheet不存在,請重新指定!" %sheet_name) #通過序號來獲取操作的sheet def set_sheet_by_index(self,index): if isinstance(index,int) and 1<= index <= len(self.get_all_sheet_names()): sheet_name = self.get_all_sheet_names()[index-1] self.sheet = self.wb[sheet_name] else: print("%s sheet 序號不存在,請重新設定" %index) #獲取當前sheet和title的名稱 def get_current_sheet_name(self): return self.sheet.title #獲取所有sheet的名稱 def get_all_sheet_names(self): return self.wb.sheetnames #獲取sheet的總行數,從0開始,返回list def get_rows_object(self): return list(self.sheet.rows) #獲取sheet的總列數,從0開始,返回list def get_cols_object(self): return list(self.sheet.columns) #獲取某行的對象,第一行從0開始 def get_row(self,row_no): return self.get_rows_object()[row_no] #獲取某一列對象,第一列從0開始 def get_col(self,col_no): return self.get_cols_object()[col_no] #獲取某個單元格對象 def get_cell_value(self,row_no,col_no): if isinstance(row_no,int) and isinstance(col_no,int) and \ 1<=row_no<=len(self.get_rows_object()) and \ 1 <= row_no <= len(self.get_cols_object()): return self.sheet.cell(row=row_no, column=col_no).value else: print("%s,%s 行號或者列號不存在,請重新設定行號或者列表讀取!" % (row_no,col_no)) #給某一個單元格寫入指定內容,行號、列號從1開始 #調用此方法時,excel不要處於打開狀態 def write_cell_value(self,row_no,col_no,value,color = None): if isinstance(row_no,int) and isinstance(col_no,int): if color is None: font = Font(bold=False, size=10, color=colors.BLACK) self.sheet.cell(row=row_no, column=col_no).font = font self.sheet.cell(row=row_no, column=col_no).value = value elif color == "green": font = Font(bold=True, size=13, color=colors.GREEN) self.sheet.cell(row=row_no, column=col_no).font = font self.sheet.cell(row=row_no, column=col_no).value = value elif color == "red": font = Font(bold=True, size=13, color=colors.RED) self.sheet.cell(row=row_no, column=col_no).font = font self.sheet.cell(row=row_no, column=col_no).value = value self.wb.save(self.excel_file_path) else: print("%s,%s 行號或者列號不是數字,請重新設定行號或者列表讀取!" % (row_no, col_no)) def write_current_time(self,row_no,col_no): if isinstance(row_no, int) and isinstance(col_no, int): self.sheet.cell(row=row_no, column=col_no).value = get_current_date_and_time() self.wb.save(self.excel_file_path) if __name__ == "__main__": excel_file_path = ProjDirPath+r"\TestData\126郵箱聯系人.xlsx" #print(excel_file_path ) excel_obj = Excel(excel_file_path) #Excel("e:\\a.xlsx") #測試路勁不存在的情況 # excel_obj.set_sheet_by_name("測試郵件") # excel_obj.set_sheet_by_name("測試郵件1111") excel_obj.set_sheet_by_index(1) # print(excel_obj.get_current_sheet_name()) #excel_obj.set_sheet_by_index(5) #print(excel_obj.get_rows_object()) #print(excel_obj.get_cols_object()) #print(excel_obj.get_row(2)) print(excel_obj.get_cell_value(2,2)) print(excel_obj.write_cell_value(5,7,"hello~~")) print(excel_obj.write_current_time(6,8))
2.2 封裝獲取頁面元素的類
from selenium.webdriver.support.ui import WebDriverWait import time #獲取單個頁面元素對象 def getElement(driver,localtorType,localtorExpression): try: element = WebDriverWait(driver,5).until(lambda x:x.find_element(by = localtorType,value=localtorExpression)) return element except Exception as e: raise e #獲取多個頁面元素對象 def getElement(driver,localtorType,localtorExpression): try: elements = WebDriverWait(driver,5).until(lambda x:x.find_elements(by=localtorType,value=localtorExpression)) return elements except Exception as e: raise e if __name__ =="__main__": from selenium import webdriver #進行單元測試 driver = webdriver.Firefox(executable_path="e:\\geckodriver") driver.maximize_window() driver.get("https://mail.126.com/") time.sleep(2) lb = getElement(driver,"id","lbNormal") print(lb) driver.quit()
2.3 封裝獲取當前日期、時間的類
import time import datetime import locale # 獲取當前的日期 def get_current_date(): time_tup = time.localtime() current_date = str(time_tup.tm_year) + "年" + \ str(time_tup.tm_mon) + "月" + str(time_tup.tm_mday)+"日" return current_date # 獲取當前的時間 def get_current_time(): time_str = datetime.datetime.now() locale.setlocale(locale.LC_CTYPE, 'chinese') now_time = time_str.strftime('%H點%M分鍾%S秒') return now_time # 獲取當前的時間 def get_current_hour(): time_str = datetime.datetime.now() now_hour = time_str.strftime('%H') return now_hour def get_current_date_and_time(): return get_current_date()+" "+get_current_time() if __name__ == "__main__": print( get_current_date()) print(get_current_time()) print(get_current_hour()) print(get_current_date_and_time())
2.4 封裝創建目錄的類
import os from Util.FromatTime import * from ProjVar.var import * def make_dir(dir_path): if not os.path.exists(dir_path): try: os.mkdir(dir_path) except Exception as e: print("創建%s目錄失敗" %dir_path) raise e def make_current_date_dir(default_dir_path = None): if default_dir_path is None: dir_path = get_current_date() else: dir_path = os.path.join(default_dir_path,get_current_date()) if not os.path.exists(dir_path): try: os.mkdir(dir_path) except Exception as e: print("創建%s目錄失敗" % dir_path) raise e return dir_path def make_current_hour_dir(default_dir_path = None): if default_dir_path is None: dir_path = get_current_hour() else: dir_path = os.path.join(default_dir_path,get_current_hour()) if not os.path.exists(dir_path): try: os.mkdir(dir_path) except Exception as e: print("創建%s目錄失敗" % dir_path) raise e return dir_path if __name__ == "__main__": make_dir(ProjDirPath+"\\"+"ScreenCapture\\"+"pic") dir_path = make_current_date_dir(ProjDirPath+"\\"+"ScreenCapture\\") dir_path=make_current_hour_dir(dir_path+"\\") print(dir_path)
2.5 封裝日志的類
#encoding=utf-8 import logging.config import logging from ProjVar.var import ProjDirPath print(ProjDirPath+"\\Conf\\"+"Logger.conf") #讀取日志配置文件 logging.config.fileConfig(ProjDirPath+"\\Conf\\"+"Logger.conf") #選擇一個日志格式 logger = logging.getLogger("example01") def debug(message): print ("debug") logger.debug(message) def info(message): logger.info(message) def error(message): print("error") logger.error(message) def warning(message): logger.warning(message) if __name__=="__main__": debug("hi") info("gloryroad") warning("hello") error("something error!")
2.6 封裝顯示等待的類
#encoding=utf-8 from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC class WaitUtil(object): def __init__(self,driver): self.locationTypeDict = { "xpath":By.XPATH, "id":By.ID, "name":By.NAME, "css_selector":By.CSS_SELECTOR, "class_name":By.CLASS_NAME, "tag_name":By.TAG_NAME, "link_text":By.LINK_TEXT, "partial_link_text":By.PARTIAL_LINK_TEXT, } self.driver = driver self.wait = WebDriverWait(driver,30) def presenceOfElementLocated(self,locatorMethod,locatorExpression,*args): """顯式等待頁面元素出現在DOM中,但並不一定可見,存在則返回該頁面元素""" try: #if self.locationTypeDict.has_key(locatorMethod.lower()): if locatorMethod.lower() in self.locationTypeDict: self.wait.until(EC.presence_of_element_located((self.locationTypeDict[locatorMethod.lower()],locatorExpression))) else: raise Exception(u"未找到定位方式,請確認定位方式是否書寫正確") except Exception as e: raise e def frameToBeAvailableAndSwitchToIt(self,locationType,locatorExpression,*args): """檢查frame是否存在,存在則切換進frame控件中""" try: self.wait.until(EC.frame_to_be_available_and_switch_to_it((self.locationTypeDict[locationType.lower()],locatorExpression))) except Exception as e: raise e def visibilityOfElementLocated(self,locationMethod,locatorExperssion,*args): """顯式等待頁面元素出現在DOM中,並且可見,存在則返回該頁面元素對象""" try: self.wait.until(EC.visibility_of_element_located((self.locationTypeDict[locationMethod.lower()],locatorExperssion))) except Exception as e: raise e if __name__ == "__main__": from selenium import webdriver driver = webdriver.Firefox(executable_path = "e:\\geckodriver") driver.get("https://mail.126.com/") waitUtil = WaitUtil(driver) driver.find_element_by_id("lbNormal").click() # waitUtil.presenceOfElementLocated("id","lbNormal") waitUtil.frameToBeAvailableAndSwitchToIt("xpath",'//iframe[contains(@id,"x-URS-iframe")]') waitUtil.visibilityOfElementLocated("xpath","//input[@name='email']") waitUtil.presenceOfElementLocated("xpath","//input[@name='email']") driver.quit()
## 根據需求如果還用其他的類,封裝好后放在此目下面 ##
3、在action包里面,創建關鍵字函數
#encoding=utf-8 from selenium import webdriver from ProjVar.var import * from Util.find import * from Util.KeyBoardUtil import KeyBoardKeys from Util.ClipboardUtil import Clipboard from Util.WaitUtil import WaitUtil from selenium.webdriver.firefox.options import Options from selenium.webdriver.chrome.options import Options import time from Util.FromatTime import * #定義全局變量driver driver = None #定義全局的等待類實例對象 waitUtil = None def open(browserName): #打開瀏覽器 global driver,waitUtil try: if browserName.lower() == "ie": driver = webdriver.Ie(executable_path = ieDriverFilePath) elif browserName.lower == "chrome": #創建Chrome瀏覽器的一個Options實例對象 chrome_options = Options() #添加屏蔽--ignore--certificate--errors提示信息的設置參數項 chrome_options.add_experimental_option("excludeSwitches",["ignore-certificate-errors"]) driver = webdriver.Chrome(executable_path = chromeDriverFilePath,chrome_options = chrome_options) else: driver = webdriver.Firefox(executable_path = firefoxDriverFilePath) #driver對象創建成功后,創建等待類實例對象 waitUtil = WaitUtil(driver) except Exception as e: raise e def visit(url): #訪問某個網站 global driver try: driver.get(url) except Exception as e: raise e def close_browser(): #關閉瀏覽器 global driver try: driver.quit() except Exception as e: raise e def sleep(sleepSeconds): #強制等待 try: time.sleep(int(sleepSeconds)) except Exception as e: raise e def clear(locationType,locatorExpression): #清空輸入框默認內容 global driver try: getElement(driver,locationType,locatorExpression).clear() except Exception as e: raise e def input_string(locationType,locatorExpression,inputContent): #在頁面輸入框中輸入數據 global driver try: getElement(driver,locationType,locatorExpression).send_keys(inputContent) except Exception as e: raise e def click(locationType,locatorExpression,*args): #點擊頁面元素 global driver try: getElement(driver,locationType,locatorExpression).click() except Exception as e: raise e def assert_string_in_pagesource(assertString,*args): #斷言頁面源碼是否存在某個關鍵字或關鍵字符串 global driver try: assert assertString in driver.page_source,u"%s not found in page source!" % assertString except AssertionError as e: raise AssertionError(e) except Exception as e: raise e def assert_title(titleStr,*args): #斷言頁面標題是否存在給定的關鍵字符串 global driver try: assert titleStr in driver.title,u"%s not found in page title!" % titleStr except AssertionError as e: raise AssertionError(e) except Exception as e: raise e def getTitle(*args): #獲取頁面標題 global driver try: return driver.title except Exception as e: raise e def getPageSource(*args): #獲取頁面源碼 global driver try: return driver.page_source except Exception as e: raise e def switch_to_frame(locationType,frameLocatorExpressoin,*args): #切換進frame global driver try: driver.switch_to.frame(getElement(driver,locationType,frameLocatorExpressoin)) except Exception as e: print("frame error!") raise e def switch_to_default_content(*args): #切換妯frame global driver try: driver.switch_to.default_content() except Exception as e: raise e def paste_string(pasteString,*args): #模擬Ctrl+V操作 try: Clipboard.setText(pasteString) #等待2秒,防止代碼執行過快,而未成功粘貼內容 time.sleep(2) KeyBoardKeys.twoKeys("ctrl","v") except Exception as e: raise e def press_tab_key(*args): #模擬tab鍵 try: KeyBoardKeys.oneKey("tab") except Exception as e: raise e def press_enter_key(*args): #模擬enter鍵 try: KeyBoardKeys.oneKey("enter") except Exception as e: raise e def maximize(*args): #窗口最大化 global driver try: driver.maximize_window() except Exception as e: raise e def capture(file_path): try: driver.save_screenshot(file_path) except Exception as e: raise e def waitPresenceOfElementLocated(locationType,locatorExpression,*args): """顯式等待頁面元素出現在DOM中,但不一定可見,存在則返回該頁面元素對象""" global waitUtil try: waitUtil.presenceOfElementLocated(locationType,locatorExpression) except Exception as e: raise e def waitFrameToBeAvailableAndSwitchToIt(locationType,locatorExprssion,*args): """檢查frame是否存在,存在則切換進frame控件中""" global waitUtil try: waitUtil.frameToBeAvailableAndSwitchToIt(locationType,locatorExprssion) except Exception as e: raise e def waitVisibilityOfElementLocated(locationType,locatorExpression,*args): """顯式等待頁面元素出現在Dom中,並且可見,存在返回該頁面元素對象""" global waitUtil try: waitUtil.visibilityOfElementLocated(locationType,locatorExpression) except Exception as e: raise e
4、在Config目錄下存放所有配置文件,比如:日志的配置文件;把所有的項目相關的配置均放到這里,實現配置與代碼的分離
日志配置文件
[loggers] keys=root,example01,example02 [logger_root] level=DEBUG handlers=hand01,hand02 [logger_example01] handlers=hand01,hand02 qualname=example01 propagate=0 [logger_example02] handlers=hand01,hand03 qualname=example02 propagate=0 ############################################### [handlers] keys=hand01,hand02,hand03 [handler_hand01] class=StreamHandler level=DEBUG formatter=form01 args=(sys.stderr,) [handler_hand02] class=FileHandler level=DEBUG formatter=form01 args=('AutoTestLog.log', 'a') [handler_hand03] class=handlers.RotatingFileHandler level=INFO formatter=form01 args=('AutoTestLog.log', 'a', 10*1024*1024, 5) ############################################### [formatters] keys=form01,form02 [formatter_form01] format=%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s datefmt=%Y-%m-%d %H:%M:%S [formatter_form02] format=%(name)-12s: %(levelname)-8s %(message)s datefmt=%Y-%m-%d %H:%M:%S
5、在ProjVar包里面存放項目所有的公共變量,如:目錄、自定義變量名稱;
import os #瀏覽器驅動存放的位置 firefoxDriverFilePath = "e:\\geckodriver" chromeDriverFilePath = "e:\\chromedriver" ieDriverFilePath = "e:\\IEDriverServer" # 當前文件所在目錄的父目錄的絕對路徑 ProjDirPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) test_step_id_col_no = 0 test_step_result_col_no = 8 test_step_error_info_col_no = 9 test_step_capture_pic_path_col_no = 10 test_case_id_col_no= 0 test_case_sheet_name=2 test_case_is_executed_flag_col_no= 3 test_case_is_hybrid_test_data_sheet_col_no=4 test_case_start_time_col_no= 6 test_case_end_time_col_no= 7 test_case_elapsed_time_col_no= 8 test_case_result_col_no = 9 if __name__=="__mian__": print(ProjDirPath)
6、ScreenCapture目錄:所有生成的日志、截屏報告均放在這里
7、TestData目錄:存放測試文件
126郵箱聯系人.xlsx
8、TestScript包用來創建測試腳本,主程序
#encoding=utf-8 import re from Util.dir_opration import make_current_date_dir, make_current_hour_dir from Util.Excel import * from Action.PageAction import * import traceback from Util.log import * def get_test_case_sheet(test_cases_excel_path): test_case_sheet_names = [] excel_obj = Excel(test_cases_excel_path) excel_obj.set_sheet_by_index(1) test_case_rows = excel_obj.get_rows_object()[1:] for row in test_case_rows: if row[3].value=='y': print(row[2].value) test_case_sheet_names.append((int(row[0].value)+1,row[2].value)) return test_case_sheet_names #print(get_test_case_sheet(ProjDirPath+"\\TestData\\126郵箱聯系人.xlsx")) def execute(test_cases_excel_path,row_no,test_case_sheet_name): excel_obj = Excel(test_cases_excel_path) excel_obj.set_sheet_by_name(test_case_sheet_name) #獲取除第一行之外的所有行對象 test_step_rows = excel_obj.get_rows_object()[1:] #拼接開始時間:當前年月日+當前時間 start_time = get_current_date_and_time() #開始計時 start_time_stamp = time.time() #設置默認用例時執行成功的,如果拋異常則說明用例執行失敗 test_result_flag = True for test_step_row in test_step_rows: if test_step_row[6].value == "y": test_action = test_step_row[2].value locator_method = test_step_row[3].value locator_exp = test_step_row[4].value test_value = test_step_row[5].value print(test_action,locator_method,locator_exp,test_value) if locator_method is None: if test_value is None: command = test_action + "()" else: command = test_action + "('%s')" %test_value else: if test_value is None: command = test_action + "('%s','%s')" %(locator_method,locator_exp) else: command = test_action + "('%s','%s','%s')" %(locator_method,locator_exp,test_value) print(command) eval(command) #處理異常 try: info(command) eval(command) excel_obj.write_cell_value(int(test_step_row[0].value) + 1, test_step_result_col_no, "執行成功") excel_obj.write_cell_value(int(test_step_row[0].value) + 1, test_step_error_info_col_no, "") excel_obj.write_cell_value(int(test_step_row[0].value) + 1, test_step_capture_pic_path_col_no, "") info("執行成功") # 加入日志信息 except Exception as e: test_result_flag = False traceback.print_exc() error(command + ":" + traceback.format_exc()) # 加入日志信息 excel_obj.write_cell_value(int(test_step_row[0].value) + 1, test_step_result_col_no, "失敗", "red") excel_obj.write_cell_value(int(test_step_row[0].value) + 1, test_step_error_info_col_no, \ command + ":" + traceback.format_exc()) dir_path = make_current_date_dir(ProjDirPath + "\\" + "ScreenCapture\\") dir_path = make_current_hour_dir(dir_path + "\\") pic_path = os.path.join(dir_path, get_current_time() + ".png") capture(pic_path) excel_obj.write_cell_value(int(test_step_row[0].value) + 1, test_step_capture_pic_path_col_no, pic_path) # 拼接結束時間:年月日+當前時間 end_time = get_current_date() + " " + get_current_time() # 計時結束時間 end_time_stamp = time.time() # 執行用例時間等於結束時間-開始時間;需要轉換數據類型int() elapsed_time = int(end_time_stamp - start_time_stamp) # 將時間轉換成分鍾;整除60 elapsed_minutes = int(elapsed_time // 60) # 將時間轉換成秒;除60取余 elapsed_seconds = elapsed_time % 60 # 拼接用例執行時間;分+秒 elapsed_time = str(elapsed_minutes) + "分" + str(elapsed_seconds) + "秒" # 判斷用例是否執行成功 if test_result_flag: test_case_result = "測試用例執行成功" else: test_case_result = "測試用例執行失敗" # 需要寫入的時第一個sheet excel_obj.set_sheet_by_index(1) # 寫入開始時間 excel_obj.write_cell_value(int(row_no), test_case_start_time_col_no, start_time) # 寫入結束時間 excel_obj.write_cell_value(int(row_no), test_case_end_time_col_no, end_time) # 寫入執行時間 excel_obj.write_cell_value(int(row_no), test_case_elapsed_time_col_no, elapsed_time) # 寫入執行結果; if test_result_flag: # 用例執行成功,寫入執行結果 excel_obj.write_cell_value(int(row_no), test_case_result_col_no, test_case_result) else: # 用例執行失敗,用red字體寫入執行結果 excel_obj.write_cell_value(int(row_no), test_case_result_col_no, test_case_result, "red") # 清理excel記錄的結果數據 def clear_test_data_file_info(test_data_excel_file_path): excel_obj = Excel(test_data_excel_file_path) excel_obj.set_sheet_by_index(1) test_case_rows = excel_obj.get_rows_object()[1:] for test_step_row in test_case_rows: excel_obj.set_sheet_by_index(1) if test_step_row[test_case_is_executed_flag_row_no].value == "y": excel_obj.write_cell_value( int(test_step_row[test_case_id_col_no].value) + 1, test_case_start_time_col_no, "") excel_obj.write_cell_value( int(test_step_row[test_case_id_col_no].value) + 1, test_case_end_time_col_no, "") excel_obj.write_cell_value( int(test_step_row[test_case_id_col_no].value) + 1, test_case_elapsed_time_col_no, "") excel_obj.write_cell_value( int(test_step_row[test_case_id_col_no].value) + 1, test_case_result_col_no, "") excel_obj.set_sheet_by_name(test_step_row[test_case_sheet_name].value) test_step_rows = excel_obj.get_rows_object()[1:] for test_step_row in test_step_rows: if test_step_row[test_step_id_col_no].value is None: continue excel_obj.write_cell_value( int(test_step_row[test_step_id_col_no].value) + 1, test_step_result_col_no, "") excel_obj.write_cell_value( int(test_step_row[test_step_id_col_no].value) + 1, test_step_error_info_col_no, "") excel_obj.write_cell_value( int(test_step_row[test_step_id_col_no].value) + 1, test_step_capture_pic_path_col_no, "") if __name__ == "__main__": test_data_excel_file_path = ProjDirPath + "\\TestData\\126郵箱聯系人.xlsx" print(get_test_case_sheet(test_data_excel_file_path)) execute(test_data_excel_file_path,2,"登錄")