自动化测试断言失败时,根据不同业务场景,可能需要立即终止或继续执行。这里以 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 # ---------------------------------------------------