几个使用UnitTest创建自动化测试框架的小想法
2017-07-28 本文已影响108人
slords
在使用当使用Unittest进行自动化测试框架构建时,会根据测试的种类和需要对测试用的class进行封装。所以,如何进行封转更为用户友好很重要,下面以url接口测试为需求,提出一些想法。
- 动态创建继承于tasecase的类。
import unittest
import requests
from types import MethodType
class TestFactroy():
def run_all_cases(self):
unittest.main()
def url_test(self, url, method='get', status_code=200):
def do_set_up():
def setUp(self):
pass
return setUp
def extra_test(self, resp, status_code):
self.assertEqual(resp.status_code, status_code, 'url test status_code fail')
return
def do_test_case(url, method, status_code):
def test_case(self):
resp = requests.request(url=url,method=method)
self.extra_test(resp, status_code)
return test_case
def add_url_case(cls, url, method='get', status_code=200):
def one_test_case(self):
resp = requests.request(url=url,method=method)
self.assertEqual(resp.status_code, status_code, 'url test status_code fail')
setattr(cls, "test_case_%s" % cls.case_num, one_test_case)
cls.case_num += 1
return
class TestUrlCase(unittest.TestCase):
pass
TestUrlCase.setUp = do_set_up()
TestUrlCase.test_case = do_test_case(url, method, status_code)
TestUrlCase.case_num = 1
TestUrlCase.extra_test= extra_test
TestUrlCase.add_url_case = MethodType(add_url_case, TestUrlCase)
return TestUrlCase
if __name__ == "__main__":
test_factory = TestFactroy()
test_case_1 = test_factory.url_test("http://www.acfun.cn")
test_case_2 = test_factory.url_test("http://www.bilibili.com")
test_case_1.add_url_case("http://www.tucao.tv")
test_factory.run_all_cases()
- 构建一个继承于unittest.TestCase的类用于接口测试。使用时继承该类。
import unittest
import requests
from enum import Enum
class UA(Enum):
Opera = "User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36 OPR/46.0.2597.39"
Firefox = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0"
chrome = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36"
def url_required(func):
def _url_required(self, *args, **kwargs):
if self.url is None:
raise(UrlRequiredException())
else:
return func(self, *args, **kwargs)
return _url_required
class UrlRequiredException(Exception):
def __init__(self):
Exception.__init__(self, 'url cannot be None')
class RequestException(Exception):
def __init__(self, e, http_options):
msg = "http request failed\n%s\n%s" % \
(('\n').join([(': ').join(item) for item in http_options.items()]), \
e.message)
Exception.__init__(self, msg)
class UrlTestModule(object):
method = "get"
url = None
authentication = False
encode =False
user_agent = None
headers = {}
params = {}
data = ""
ua = None
response = None
clear_response = False
assert_status_code = 200
exception_list = []
@staticmethod
def run_test_case():
unittest.main()
@classmethod
def set_response(cls, response):
cls.response = response
@classmethod
def remove_response(cls):
cls.response = None
@classmethod
def get_response(cls):
return cls.response
def setUp(self):
self._initialization()
self._do_request()
@url_required
def _do_request(self):
if self.response is not None:
return
http_options = {
'method': self.method,
'url': self.url,
'params': self.params,
'data': self.data
}
headers = {}
if self.ua:
headers.update({'User-Agent':self.ua})
if self.authentication:
headers.update(self._auth())
headers.update(self.headers)
http_options['headers'] = headers
if self.encode:
http_options = self._encode(http_options)
try:
response = requests.request(**http_options)
self.set_response(response)
except Exception as e:
raise( RequestException(e, http_options))
@url_required
def tearDown(self):
self._finish()
self._clear_response()
def _initialization(self):
if hasattr(self,'initialization'):
m = getattr(self,'initialization')
if hasattr(m, '__call__'):
m()
return
def _finish(self):
if hasattr(self,'finish'):
m = getattr(self,'finish')
if hasattr(m, '__call__'):
m()
return
def _clear_response(self):
if self.assert_status_code:
self.remove_response()
def _auth(self, *args, **kwargs):
return {}
def _encode(self, http_options):
return http_options
def _assert_response_status_code(self):
if self.assert_status_code:
if not isinstance(self.assert_status_code, int):
status_code = 200
else:
status_code = self.assert_status_code
self.assertEqual(self.response.status_code, status_code)
def _raiseExceptions(self):
if len(self.exception_list):
raise(Exception(('\n').join([e.message for e in self.exception_list])))
@url_required
def test_script(self):
self._assert_response_status_code()
assert_list = [attr for attr in dir(self) \
if ('check' == attr[:5]) and hasattr(getattr(self, attr),'__call__')]
assert_list.sort()
for m in assert_list:
try:
getattr(self, m)()
except Exception as e:
self.exception_list.append(e)
self._raiseExceptions()
class TestFactory(object):
@property
def UrlTest(self):
class UrlTestClass(UrlTestModule, unittest.TestCase):pass
return UrlTestClass
def run_test_case(self):
unittest.main()
test_factory = TestFactory()
if __name__ == "__main__":
class TestCase(test_factory.UrlTest):
url= "http://www.bilibili.com"
def initialization(self):
print("initialization start")
def check_if_the_site_is_BiliBili(self):
print('check if the site is BiliBili start')
self.assertRegex(self.response.content, "哔哩哔哩".encode('utf-8'))
def check_if_return_html(self):
print('check if return html start')
self.assertEqual(self.response.headers.get('Content-Type'), "text/html")
def finish(self):
print('finish start')
test_factory.run_test_case()
一些问题
- 当使用unittest.main()运行所有的 test cases 时, 会将所有class继承于unittest.TestCase的类全数测试一遍。使用继承类的方式生成测试用例,应采用方法生成的方式,避免继承时被再次调用。