自动化框架的两种断言设计(pytest 版)

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

参考:Delayed assert / multiple failures per test

原文地址:https://www.cnblogs.com/bilibang/p/7244931.html