自動化測試斷言失敗時,根據不同業務場景,可能需要立即終止或繼續執行。這里以 Appium + pytest 為例。
一. 斷言失敗立即終止
用途一:用例的預期結果是其他用例的前提條件時,assert 失敗需要立即終止,這是我們設計自動化測試用例時最常見的場景。
用途二:用例中的任何一個步驟執行失敗時,立即終止,因為步驟都執行失敗了,沒有繼續執行下一步的必要。方案:思路與用途一類似,這里把每個測試步驟當做都有一個預期結果(True),封裝每一個具體步驟,步驟結果返回布爾值。對該結果進行 assert,False時立即終止。
1 def click(self, step): 2 method_name = sys._getframe().f_code.co_name 3 try: 4 element = self.find_element(**step['element_loc']) 5 if step.has_key('times'): 6 for i in range(step['times']): 7 element.click() 8 else: 9 element.click() 10 return True 11 except: 12 print u'%s失敗' % method_name 13 return False
1 for step in self.case_steps: 2 assert self.operate(step), 'error in step: %s' % step
二. 斷言失敗繼續執行
主要使用了兩個函數 expect, assert_expectations 。
Demo: test_delayed_assert.py
1 from delayed_assert import expect, assert_expectations 2 3 def test_should_pass(): 4 expect(1 == 1, 'one is one') 5 assert_expectations() 6 7 def test_should_fail(): 8 expect(1 == 2) 9 x = 1 10 y = 2 11 expect(x == y, 'x:%s y:%s' % (x,y)) 12 expect(1 == 1) 13 assert_expectations()
Module: delayedAssert.py
1 ''' 2 Implements one form of delayed assertions. 3 4 Interface is 2 functions: 5 6 expect(expr, msg=None) 7 : Evaluate 'expr' as a boolean, and keeps track of failures 8 9 assert_expectations() 10 : raises an assert if an expect() calls failed 11 12 Usage Example: 13 14 from expectations import expect, assert_expectations 15 16 def test_should_pass(): 17 expect(1 == 1, 'one is one') 18 assert_expectations() 19 20 def test_should_fail(): 21 expect(1 == 2, 'one is two') 22 expect(1 == 3, 'one is three') 23 assert_expectations() 24 ''' 25 26 # --------------------------------------------------- 27 28 def expect(expr, msg=None): 29 'keeps track of failed expectations' 30 if not expr: 31 _log_failure(msg) 32 33 def assert_expectations(): 34 'raise an assert if there are any failed expectations' 35 if _failed_expectations: 36 assert False, _report_failures() 37 38 # --------------------------------------------------- 39 40 import inspect 41 import os.path 42 43 _failed_expectations = [] 44 45 def _log_failure(msg=None): 46 (filename, line, funcname, contextlist) = inspect.stack()[2][1:5] 47 filename = os.path.basename(filename) 48 context = contextlist[0] 49 _failed_expectations.append('file "%s", line %s, in %s()%s\n%s' % 50 (filename, line, funcname, (('\n%s' % msg) if msg else ''), context)) 51 52 def _report_failures(): 53 global _failed_expectations 54 if _failed_expectations: 55 (filename, line, funcname) = inspect.stack()[2][1:4] 56 report = [ 57 '\n\nassert_expectations() called from', 58 '"%s" line %s, in %s()\n' % (os.path.basename(filename), line, funcname), 59 'Failed Expectations:%s\n' % len(_failed_expectations)] 60 for i,failure in enumerate(_failed_expectations, start=1): 61 report.append('%d: %s' % (i, failure)) 62 _failed_expectations = [] 63 return ('\n'.join(report)) 64 65 # --------------------------------------------------- 66 # _log_failure() notes 67 # 68 # stack() returns a list of frame records 69 # 0 is the _log_failure() function 70 # 1 is the expect() function 71 # 2 is the function that called expect(), that's what we want 72 # 73 # a frame record is a tuple like this: 74 # (frame, filename, line, funcname, contextlist, index) 75 # we're mainly interested in the middle 4, 76 # ---------------------------------------------------