對於項目中一些難以復現的bug,手工操作比較耗時耗力,而且還不一定能夠復現,如果知道操作步驟就可以用自動化來進行反復操作來復現該問題。
1.了解該問題的操作步驟
2.抓取日志
3.遇到問題時,抓取截圖
4.復現問題后停止執行命令,並停止日志。
首先想到的是使用monkey,可以通過自定義monkey來模擬操作步驟,由於能力有限,不知道monkey如何斷言,並且如果一直運行logcat抓取日志,日志又太多,無法准確定位,所以想到使用appium.
1.操作步驟,這里就不貼出了
2.抓取日志 (這里進行了封裝)
class logcat: #開啟adb命令 def start_logcat(self, name): data = time.strftime("%Y-%m-%d", time.localtime(time.time())) # path = "../../report/log/" + data dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) path = os.path.join(dir, 'report/' + name) type = '.txt' now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time())) filename = '' if os.path.exists(path): filename = path + "\\" + now + "_" + name + type else: os.makedirs(path) filename = path + "\\" + now + "_" + name + type global logcat_file logcat_file = open(filename, 'w') logcmd = "adb logcat -v time" global poplog poplog = subprocess.Popen(logcmd, stdout=logcat_file, stderr=subprocess.PIPE) # 結束adb命令 def stop_logcat(self): logcat_file.close() poplog.terminate()
3. 遇到問題時截圖
def take_screenShot(driver,dir, name): day = time.strftime("%Y-%m-%d", time.localtime(time.time())) fq = "../../report/" + dir # 上上級目錄 ../上級目錄 ./當前目錄 # dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # fq = os.path.join(dir, 'report/log/' + day) # fq =os.getcwd()[:-4] +'screenShots\\'+day 根據獲取的路徑,然后截取路徑保存到自己想存放的目錄下 tm = time.strftime("%Y-%m-%d_%H_%M_%S", time.localtime(time.time())) type = '.png' filename = "" if os.path.exists(fq): filename = fq + "\\" + tm + "_" + name + type else: os.makedirs(fq) filename = fq + "\\" + tm + "_" + name + type # c = os.getcwd() # r"\\".join(c.split("\\")) #此2行注銷實現的功能為將路徑中的\替換為\\ driver.get_screenshot_as_file(filename) print(name + "圖片保存成功")
4.循環該條用例
def choose_case(self): for i in range(1, 10000): ClearAllTestReport() # 可能執行次數過多,這里每次都會清空日志 print(u'第', i, u'執行用例') testunit = unittest.TestSuite() testunit.addTest(multi_run("test_cash")) runner = unittest.TextTestRunner() result = runner.run(testunit) #得到執行的結果 if not result.wasSuccessful(): # 如果執行結果為fail,停止執行 break
項目實戰
class multi_run(unittest.TestCase): @classmethod def setUp(cls): configure = driver_configure.driver_configure() cls.driver = configure.get_driver() cls.assert_result = assert_result() cls.logcat = logcat() def test_cash(self): ''' 現金消費輸入1 ''' name = "" dir = u"未返回給第三方" try: self.logcat.start_logcat(dir) # self.main = main_activity.main_activity(self.driver) # self.main.input_one() # time.sleep(1) # ''' # 注意調用方式: 1. self.assert_result.assert_equals(*****) assert_equals方法中的self不用傳 # 2. assert_result().assert_equals() 方法中的self不用傳 # 3. assert_result.assert_equals() 方法的self參數需要傳入 # ''' name = u"銀行卡" # 添加name變量 在每一次斷言 # self.main.click_card() self.out_call = out_call(self.driver) self.lack_paper = lack_paper(self.driver) self.cash = cash_second(self.driver) self.out_call.click_consume() # self.out_call.long_touch(self.driver) self.order = self.out_call.get_order_no() self.out_call.click_card() gesture_manipulation().swipe_up(self.driver) self.out_call.click_btn_consume() time.sleep(2) # self.lack_paper.click_know() # self.lack_paper.click_know2() self.cash.click_complete() self.content = self.out_call.result_content() time.sleep(2) self.assertIsNotNone(self.content) # self.assertIsNone(self.content) self.out_call.back_activity() self.out_call.click_refund() time.sleep(1) self.out_call.delete_out_trade_no(self.driver) time.sleep(1) self.out_call.input_order_no(self.order) time.sleep(1) self.driver.tap([(644, 717), (685, 749)], 500) self.out_call.click_refund1() self.out_call.click_btn_finish() self.logcat.stop_logcat() # 沒有發生異常也要關閉日志 # todo --------------- # 刪除不需要的日志,也就是正常的日志 except AssertionError as e: self.logcat.stop_logcat() # 發生異常時關閉日志 take_screenShot.take_screenShot(self.driver, dir, name) # self.out_call.kill_AppiumS() @classmethod def tearDownClass(cls): cls.driver.quit() class for_case: def choose_case(self): for i in range(1, 10000): ClearAllTestReport() print(u'第', i, u'執行用例') testunit = unittest.TestSuite() testunit.addTest(multi_run("test_cash")) runner = unittest.TextTestRunner() result = runner.run(testunit) if not result.wasSuccessful(): break if __name__ == "__main__": for_case().choose_case()