diff --git a/Tests/test_locust.py b/Tests/run_locust.py similarity index 100% rename from Tests/test_locust.py rename to Tests/run_locust.py diff --git a/Tests/test_baiduSearch.py b/Tests/test_baiduSearch.py new file mode 100644 index 0000000..76637bf --- /dev/null +++ b/Tests/test_baiduSearch.py @@ -0,0 +1,58 @@ +# encoding: utf-8 + +import requests +import re +from nose.tools import * + + +class check_response(): + @staticmethod + def check_title(response, key): + # 校验key是否匹配返回页面title + expect_title = key + u'_百度搜索' + re_title = re.compile('(.*)') # 搜索页面title正则表达式 + title = re.search(re_title, response).groups()[0] + print 'Search Result Title:%s' % title + eq_(title, expect_title, 'Title Check Error!%s != %s' % (title, expect_title)) + + @staticmethod + def check_results(response, key): + # 校验key是否匹配搜索结果的名称或者URL + re_name = re.compile('>(.*)') # 搜索结果name正则表达式 + re_url = re.compile('style="text-decoration:none;">(.*)', '').replace('', '') + url = url.replace('', '').replace('', '').replace(' ', '').replace('...', '') + print 'Search Results Name:%s\tURL:%s' % (name, url) + if key.lower() not in (name + url).lower(): + assert False, 'Search Results Check Error!%s not in %s' % (key, name + url) + return True + + +class test_baiduSearch(object): + """接口名称""" + + def __init__(self, ): + """Constructor for test_baiduSearch""" + + @staticmethod + def search(wd): + url = 'http://www.baidu.com/s' + params = dict(wd=wd) + r = requests.get(url, params=params) + + # 检查百度搜索返回页面标题 + check_response.check_title(r.text, wd) + # 检查百度页面返回内容 + check_response.check_results(r.text, wd) + + def test_BVT(self): + # 校验输入不同类型的wd时,百度是否均可正常搜索返回结果 + # wd分类:中文,英文,数字 + wd_list = [u'lovesoo', u'软件测试', u'12345'] + for wd in wd_list: + yield test_baiduSearch.search, wd diff --git a/Tests/test_demo.py b/Tests/test_demo.py index 7605ac8..aeffbf3 100644 --- a/Tests/test_demo.py +++ b/Tests/test_demo.py @@ -1,10 +1,10 @@ -# encoding: utf-8 +# coding=utf-8 import sys import os reload(sys) sys.setdefaultencoding("utf-8") -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))) # equal sys.path.append('../..') +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))) from Util import * from functools import partial diff --git a/Tests/test_doubanSearch.py b/Tests/test_doubanSearch.py new file mode 100644 index 0000000..a26c08c --- /dev/null +++ b/Tests/test_doubanSearch.py @@ -0,0 +1,228 @@ +# encoding: utf-8 + +import sys +import os +reload(sys) +sys.setdefaultencoding("utf-8") +import requests +import json +from datetime import datetime as dt +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from functools import partial +from nose.tools import * + + +def send_mail(): + # 读取测试报告内容 + with open(report_file, 'r') as f: + content = f.read().decode('utf-8') + + msg = MIMEMultipart('mixed') + # 添加邮件内容 + msg_html = MIMEText(content, 'html', 'utf-8') + msg.attach(msg_html) + + # 添加附件 + msg_attachment = MIMEText(content, 'html', 'utf-8') + msg_attachment["Content-Disposition"] = 'attachment; filename="{0}"'.format(report_file) + msg.attach(msg_attachment) + + msg['Subject'] = mail_subjet + msg['From'] = mail_user + msg['To'] = ';'.join(mail_to) + try: + # 连接邮件服务器 + s = smtplib.SMTP(mail_host, 25) + # 登陆 + s.login(mail_user, mail_pwd) + # 发送邮件 + s.sendmail(mail_user, mail_to, msg.as_string()) + # 退出 + s.quit() + except Exception as e: + print "Exceptioin ", e + + +class check_response(): + @staticmethod + def check_result(response, params, expectNum=None): + # 由于搜索结果存在模糊匹配的情况,这里简单处理只校验第一个返回结果的正确性 + if expectNum is not None: + # 期望结果数目不为None时,只判断返回结果数目 + eq_(expectNum, len(response['subjects']), '{0}!={1}'.format(expectNum, len(response['subjects']))) + else: + if not response['subjects']: + # 结果为空,直接返回失败 + assert False + else: + # 结果不为空,校验第一个结果 + subject = response['subjects'][0] + # 先校验搜索条件tag + if params.get('tag'): + for word in params['tag'].split(','): + genres = subject['genres'] + ok_(word in genres, 'Check {0} failed!'.format(word.encode('utf-8'))) + + # 再校验搜索条件q + elif params.get('q'): + # 依次判断片名,导演或演员中是否含有搜索词,任意一个含有则返回成功 + for word in params['q'].split(','): + title = [subject['title']] + casts = [i['name'] for i in subject['casts']] + directors = [i['name'] for i in subject['directors']] + total = title + casts + directors + ok_(any(word.lower() in i.lower() for i in total), + 'Check {0} failed!'.format(word.encode('utf-8'))) + + @staticmethod + def check_pageSize(response): + # 判断分页结果数目是否正确 + count = response.get('count') + start = response.get('start') + total = response.get('total') + diff = total - start + + if diff >= count: + expectPageSize = count + elif count > diff > 0: + expectPageSize = diff + else: + expectPageSize = 0 + + eq_(expectPageSize, len(response['subjects']), '{0}!={1}'.format(expectPageSize, len(response['subjects']))) + + +class test_doubanSearch(object): + """接口名称""" + + @staticmethod + def search(params, expectNum=None): + url = 'https://api.douban.com/v2/movie/search' + r = requests.get(url, params=params) + print 'Search Params:\n', json.dumps(params, ensure_ascii=False) + print 'Search Response:\n', json.dumps(r.json(), ensure_ascii=False, indent=4) + code = r.json().get('code') + if code > 0: + assert False, 'Invoke Error.Code:\t{0}'.format(code) + else: + if params.get('start') is not None or params.get('count') is not None: + # 传入start参数时,只校验翻页功能 + check_response.check_pageSize(r.json()) + else: + # 校验搜索结果是否与搜索词匹配 + check_response.check_result(r.json(), params, expectNum) + + def test_q(self): + # 校验搜索条件 q + qs = [u'白夜追凶', u'大话西游', u'周星驰', u'张艺谋', u'周星驰,吴孟达', u'张艺谋,巩俐', u'周星驰,大话西游', u'白夜追凶,潘粤明'] + for q in qs: + params = dict(q=q) + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + def test_tag(self): + # 校验搜索条件 tag + tags = [u'科幻', u'喜剧', u'动作', u'犯罪', u'科幻,喜剧', u'动作,犯罪'] + for tag in tags: + params = dict(tag=tag) + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + def test_param_combination(self): + # 校验组合搜索q,tag + params_list = [(dict(q='', tag=''), 0), + dict(q=u'刘德华', tag=''), + dict(q='', tag=u'动作'), + dict(q=u'刘德华', tag=u'动作')] + for params in params_list: + if isinstance(params, tuple): + f = partial(test_doubanSearch.search, params[0], params[1]) + f.description = json.dumps(params[0], ensure_ascii=False).encode('utf-8') + else: + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + def test_page(self): + # 校验接口翻页返回结果功能是否正常 + q = u'周星驰' + count = 15 + for page in range(10): + start = page * count + params = dict(q=q, start=start, count=count) + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + def test_param_q(self): + # 参数校验 q,搜索类型:中文、英文、数字、特殊符号、None、空 + qs = [u'战狼', (u'avatar', 20), u'2046', (u'~!@#$%^&*()', 0), (None, 0), ('', 0)] + for q in qs: + if isinstance(q, tuple): + params = dict(q=q[0]) + f = partial(test_doubanSearch.search, params, q[1]) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + else: + params = dict(q=q) + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + def test_param_tag(self): + # 参数校验 tag,搜索类型:中文、英文、数字、特殊符号、None、空 + tags = [u'喜剧', (u'action', 20), (u'2046', 20), (u'~!@#$%^&*()', 0), (None, 0), ('', 0)] + for tag in tags: + if isinstance(tag, tuple): + params = dict(tag=tag[0]) + f = partial(test_doubanSearch.search, params, tag[1]) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + else: + params = dict(tag=tag) + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + def test_param_start(self): + q = u'周星驰' + start_list = [None, 0, 10, 100, -1] + for start in start_list: + params = dict(q=q, start=start) + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + def test_param_count(self): + tag = u'喜剧' + count_list = [None, 20, 10, 100, 0, -10] + for count in count_list: + params = dict(tag=tag, count=count) + f = partial(test_doubanSearch.search, params) + f.description = json.dumps(params, ensure_ascii=False).encode('utf-8') + yield (f,) + + +if __name__ == '__main__': + # 邮件服务器 + mail_host = 'smtp.163.com' + # 发件人地址 + mail_user = 'xxx@163.com' + # 发件人密码 + mail_pwd = 'xxx' + # 邮件标题 + mail_subjet = u'NoseTests_测试报告_{0}'.format(dt.now().strftime('%Y%m%d')) + # 收件人地址list + mail_to = ['xxx@126.com', 'xxx@126.com'] + # 测试报告名称 + report_file = 'TestReport.html' + + # 运行nosetests进行自动化测试并生成测试报告 + print 'Run Nosetests Now...' + os.system('nosetests -v test_doubanSearch.py:test_doubanSearch --with-html --html-file={0}'.format(report_file)) + + # 发送测试报告邮件 + print 'Send Test Report Mail Now...' + send_mail()