python+requests+unittest+htmltestrunner+Excel生成接口自动化的测试框架
Python+Requests+Unittest+Excel+HtmltestRunner生成自动化测试框架
流程
1.接口文档
2.读取接口文档
3.封装request的类
4.unittest类 testcase 就是读取文档类中的用例
5.htmltestrunner
1.接口文档
从开发获取接口文档整理编写测试用例(url,method,paramter,code,response)
2.读取接口文档
读取接口文档得到我们要发起请求的接口参数
3.封装request的类
封装request类,主要作用对浏览器发起请求(请求参数Excel表中获取)。assert断言预期结果是否达到
实际结果标准。
4.unittest类 testcase 就是读取文档类中的用例
unittest测试用例类,用于存放我们的测试用例。unittest.TestCase作用用例断言
5.htmltestrunner
实例化suit组,里面存放我们要测的用例。结合htmltestrunner生成测试用例报告
HTMLTestRunner.py
"""
A TestRunner for use with the Python unit testing framework. It
generates a HTML report to show the result at a glance.
The simplest way to use this is to invoke its main method. E.g.
import unittest
import HTMLTestRunner
... define your tests ...
if __name__ == '__main__':
HTMLTestRunner.main()
For more customization options, instantiates a HTMLTestRunner object.
HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g.
# output to a file
fp = file('my_report.html', 'wb')
runner = HTMLTestRunner.HTMLTestRunner(
stream=fp,
title='My unit test',
description='This demonstrates the report output by HTMLTestRunner.'
)
# Use an external stylesheet.
# See the Template_mixin class for more customizable options
runner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'
# run the test
runner.run(my_test_suite)
------------------------------------------------------------------------
Copyright (c) 2004-2007, Wai Yip Tung
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name Wai Yip Tung nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
# URL: http://tungwaiyip.info/software/HTMLTestRunner.html
__author__ = "Wai Yip Tung"
__version__ = "0.8.2"
"""
Change History
Version 0.8.2
* Show output inline instead of popup window (Viorel Lupu).
Version in 0.8.1
* Validated XHTML (Wolfgang Borgert).
* Added description of test classes and test cases.
Version in 0.8.0
* Define Template_mixin class for customization.
* Workaround a IE 6 bug that it does not treat <script> block as CDATA.
Version in 0.7.1
* Back port to Python 2.3 (Frank Horowitz).
* Fix missing scroll bars in detail log (Podi).
"""
# TODO: color stderr
# TODO: simplify javascript using ,ore than 1 class in the class attribute?
import datetime
import io
import sys
import time
import unittest
from xml.sax import saxutils
# ------------------------------------------------------------------------
# The redirectors below are used to capture output during testing. Output
# sent to sys.stdout and sys.stderr are automatically captured. However
# in some cases sys.stdout is already cached before HTMLTestRunner is
# invoked (e.g. calling logging.basicConfig). In order to capture those
# output, use the redirectors for the cached stream.
#
# e.g.
# >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector)
# >>>
class OutputRedirector(object):
""" Wrapper to redirect stdout or stderr """
def __init__(self, fp):
self.fp = fp
def write(self, s):
self.fp.write(s)
def writelines(self, lines):
self.fp.writelines(lines)
def flush(self):
self.fp.flush()
stdout_redirector = OutputRedirector(sys.stdout)
stderr_redirector = OutputRedirector(sys.stderr)
# ----------------------------------------------------------------------
# Template
class Template_mixin(object):
"""
Define a HTML template for report customerization and generation.
Overall structure of an HTML report
HTML
+------------------------+
|<html> |
| <head> |
| |
| STYLESHEET |
| +----------------+ |
| | | |
| +----------------+ |
| |
| </head> |
| |
| <body> |
| |
| HEADING |
| +----------------+ |
| | | |
| +----------------+ |
| |
| REPORT |
| +----------------+ |
| | | |
| +----------------+ |
| |
| ENDING |
| +----------------+ |
| | | |
| +----------------+ |
| |
| </body> |
|</html> |
+------------------------+
"""
STATUS = {
0: 'pass',
1: 'fail',
2: 'error',
}
DEFAULT_TITLE = 'Unit Test Report'
DEFAULT_DESCRIPTION = ''
# ------------------------------------------------------------------------
# HTML Template
HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%(title)s</title>
<meta name="generator" content="%(generator)s"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
%(stylesheet)s
</head>
<body>
<script language="javascript" type="text/javascript"><!--
output_list = Array();
/* level - 0:Summary; 1:Failed; 2:All */
function showCase(level) {
trs = document.getElementsByTagName("tr");
for (var i = 0; i < trs.length; i++) {
tr = trs[i];
id = tr.id;
if (id.substr(0,2) == 'ft') {
if (level < 1) {
tr.className = 'hiddenRow';
}
else {
tr.className = '';
}
}
if (id.substr(0,2) == 'pt') {
if (level > 1) {
tr.className = '';
}
else {
tr.className = 'hiddenRow';
}
}
}
}
function showClassDetail(cid, count) {
var id_list = Array(count);
var toHide = 1;
for (var i = 0; i < count; i++) {
tid0 = 't' + cid.substr(1) + '.' + (i+1);
tid = 'f' + tid0;
tr = document.getElementById(tid);
if (!tr) {
tid = 'p' + tid0;
tr = document.getElementById(tid);
}
id_list[i] = tid;
if (tr.className) {
toHide = 0;
}
}
for (var i = 0; i < count; i++) {
tid = id_list[i];
if (toHide) {
document.getElementById('div_'+tid).style.display = 'none'
document.getElementById(tid).className = 'hiddenRow';
}
else {
document.getElementById(tid).className = '';
}
}
}
function showTestDetail(div_id){
var details_div = document.getElementById(div_id)
var displayState = details_div.style.display
// alert(displayState)
if (displayState != 'block' ) {
displayState = 'block'
details_div.style.display = 'block'
}
else {
details_div.style.display = 'none'
}
}
function html_escape(s) {
s = s.replace(/&/g,'&');
s = s.replace(/</g,'<');
s = s.replace(/>/g,'>');
return s;
}
/* obsoleted by detail in <div>
function showOutput(id, name) {
var w = window.open("", //url
name,
"resizable,scrollbars,status,width=800,height=450");
d = w.document;
d.write("<pre>");
d.write(html_escape(output_list[id]));
d.write("\n");
d.write("<a href='javascript:window.close()'>close</a>\n");
d.write("</pre>\n");
d.close();
}
*/
--></script>
%(heading)s
%(report)s
%(ending)s
</body>
</html>
"""
# variables: (title, generator, stylesheet, heading, report, ending)
# ------------------------------------------------------------------------
# Stylesheet
#
# alternatively use a <link> for external style sheet, e.g.
# <link rel="stylesheet" href="$url" type="text/css">
STYLESHEET_TMPL = """
<style type="text/css" media="screen">
body { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }
table { font-size: 100%; }
pre { }
/* -- heading ---------------------------------------------------------------------- */
h1 {
font-size: 16pt;
color: gray;
}
.heading {
margin-top: 0ex;
margin-bottom: 1ex;
}
.heading .attribute {
margin-top: 1ex;
margin-bottom: 0;
}
.heading .description {
margin-top: 4ex;
margin-bottom: 6ex;
}
/* -- css div popup ------------------------------------------------------------------------ */
a.popup_link {
}
a.popup_link:hover {
color: red;
}
.popup_window {
display: none;
position: relative;
left: 0px;
top: 0px;
/*border: solid #627173 1px; */
padding: 10px;
background-color: #E6E6D6;
font-family: "Lucida Console", "Courier New", Courier, monospace;
text-align: left;
font-size: 8pt;
width: 500px;
}
}
/* -- report ------------------------------------------------------------------------ */
#show_detail_line {
margin-top: 3ex;
margin-bottom: 1ex;
}
#result_table {
width: 80%;
border-collapse: collapse;
border: 1px solid #777;
}
#header_row {
font-weight: bold;
color: white;
background-color: #777;
}
#result_table td {
border: 1px solid #777;
padding: 2px;
}
#total_row { font-weight: bold; }
.passClass { background-color: #6c6; }
.failClass { background-color: #c60; }
.errorClass { background-color: #c00; }
.passCase { color: #6c6; }
.failCase { color: #c60; font-weight: bold; }
.errorCase { color: #c00; font-weight: bold; }
.hiddenRow { display: none; }
.testcase { margin-left: 2em; }
/* -- ending ---------------------------------------------------------------------- */
#ending {
}
</style>
"""
# ------------------------------------------------------------------------
# Heading
#
HEADING_TMPL = """<div class='heading'>
<h1>%(title)s</h1>
%(parameters)s
<p class='description'>%(description)s</p>
</div>
""" # variables: (title, parameters, description)
HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s:</strong> %(value)s</p>
""" # variables: (name, value)
# ------------------------------------------------------------------------
# Report
#
REPORT_TMPL = """
<p id='show_detail_line'>Show
<a href='javascript:showCase(0)'>Summary</a>
<a href='javascript:showCase(1)'>Failed</a>
<a href='javascript:showCase(2)'>All</a>
</p>
<table id='result_table'>
<colgroup>
<col align='left' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
</colgroup>
<tr id='header_row'>
<td>Test Group/Test case</td>
<td>Count</td>
<td>Pass</td>
<td>Fail</td>
<td>Error</td>
<td>View</td>
</tr>
%(test_list)s
<tr id='total_row'>
<td>Total</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td> </td>
</tr>
</table>
""" # variables: (test_list, count, Pass, fail, error)
REPORT_CLASS_TMPL = r"""
<tr class='%(style)s'>
<td>%(desc)s</td>
<td>%(count)s</td>
<td>%(Pass)s</td>
<td>%(fail)s</td>
<td>%(error)s</td>
<td><a href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td>
</tr>
""" # variables: (style, desc, count, Pass, fail, error, cid)
REPORT_TEST_WITH_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'>
<td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" >
%(status)s</a>
<div id='div_%(tid)s' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_%(tid)s').style.display = 'none' " >
[x]</a>
</div>
<pre>
%(script)s
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
""" # variables: (tid, Class, style, desc, status)
REPORT_TEST_NO_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'>
<td class='%(style)s'><div class='testcase'>%(desc)s</div></td>
<td colspan='5' align='center'>%(status)s</td>
</tr>
""" # variables: (tid, Class, style, desc, status)
REPORT_TEST_OUTPUT_TMPL = r"""
%(id)s: %(output)s
""" # variables: (id, output)
# ------------------------------------------------------------------------
# ENDING
#
ENDING_TMPL = """<div id='ending'> </div>"""
# -------------------- The end of the Template class -------------------
TestResult = unittest.TestResult
class _TestResult(TestResult):
# note: _TestResult is a pure representation of results.
# It lacks the output and reporting ability compares to unittest._TextTestResult.
def __init__(self, verbosity=1):
TestResult.__init__(self)
self.stdout0 = None
self.stderr0 = None
self.success_count = 0
self.failure_count = 0
self.error_count = 0
self.verbosity = verbosity
# result is a list of result in 4 tuple
# (
# result code (0: success; 1: fail; 2: error),
# TestCase object,
# Test output (byte string),
# stack trace,
# )
self.result = []
def startTest(self, test):
TestResult.startTest(self, test)
# just one buffer for both stdout and stderr
self.outputBuffer = io.StringIO()
stdout_redirector.fp = self.outputBuffer
stderr_redirector.fp = self.outputBuffer
self.stdout0 = sys.stdout
self.stderr0 = sys.stderr
sys.stdout = stdout_redirector
sys.stderr = stderr_redirector
def complete_output(self):
"""
Disconnect output redirection and return buffer.
Safe to call multiple times.
"""
if self.stdout0:
sys.stdout = self.stdout0
sys.stderr = self.stderr0
self.stdout0 = None
self.stderr0 = None
return self.outputBuffer.getvalue()
def stopTest(self, test):
# Usually one of addSuccess, addError or addFailure would have been called.
# But there are some path in unittest that would bypass this.
# We must disconnect stdout in stopTest(), which is guaranteed to be called.
self.complete_output()
def addSuccess(self, test):
self.success_count += 1
TestResult.addSuccess(self, test)
output = self.complete_output()
self.result.append((0, test, output, ''))
if self.verbosity > 1:
sys.stderr.write('ok ')
sys.stderr.write(str(test))
sys.stderr.write('\n')
else:
sys.stderr.write('.')
def addError(self, test, err):
self.error_count += 1
TestResult.addError(self, test, err)
_, _exc_str = self.errors[-1]
output = self.complete_output()
self.result.append((2, test, output, _exc_str))
if self.verbosity > 1:
sys.stderr.write('E ')
sys.stderr.write(str(test))
sys.stderr.write('\n')
else:
sys.stderr.write('E')
def addFailure(self, test, err):
self.failure_count += 1
TestResult.addFailure(self, test, err)
_, _exc_str = self.failures[-1]
output = self.complete_output()
self.result.append((1, test, output, _exc_str))
if self.verbosity > 1:
sys.stderr.write('F ')
sys.stderr.write(str(test))
sys.stderr.write('\n')
else:
sys.stderr.write('F')
class HTMLTestRunner(Template_mixin):
"""
"""
def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None):
self.stream = stream
self.verbosity = verbosity
if title is None:
self.title = self.DEFAULT_TITLE
else:
self.title = title
if description is None:
self.description = self.DEFAULT_DESCRIPTION
else:
self.description = description
self.startTime = datetime.datetime.now()
def run(self, test):
"Run the given test case or test suite."
result = _TestResult(self.verbosity)
test(result)
self.stopTime = datetime.datetime.now()
self.generateReport(test, result)
print(sys.stderr, '\nTimeElapsed: %s' % (self.stopTime-self.startTime))
return result
def sortResult(self, result_list):
# unittest does not seems to run in any particular order.
# Here at least we want to group them together by class.
rmap = {}
classes = []
for n,t,o,e in result_list:
cls = t.__class__
if not cls in rmap:
rmap[cls] = []
classes.append(cls)
rmap[cls].append((n,t,o,e))
r = [(cls, rmap[cls]) for cls in classes]
return r
def getReportAttributes(self, result):
"""
Return report attributes as a list of (name, value).
Override this to add custom attributes.
"""
startTime = str(self.startTime)[:19]
duration = str(self.stopTime - self.startTime)
status = []
if result.success_count: status.append('Pass %s' % result.success_count)
if result.failure_count: status.append('Failure %s' % result.failure_count)
if result.error_count: status.append('Error %s' % result.error_count )
if status:
status = ' '.join(status)
else:
status = 'none'
return [
('Start Time', startTime),
('Duration', duration),
('Status', status),
]
def generateReport(self, test, result):
report_attrs = self.getReportAttributes(result)
generator = 'HTMLTestRunner %s' % __version__
stylesheet = self._generate_stylesheet()
heading = self._generate_heading(report_attrs)
report = self._generate_report(result)
ending = self._generate_ending()
output = self.HTML_TMPL % dict(
title = saxutils.escape(self.title),
generator = generator,
stylesheet = stylesheet,
heading = heading,
report = report,
ending = ending,
)
self.stream.write(output.encode('utf8'))
def _generate_stylesheet(self):
return self.STYLESHEET_TMPL
def _generate_heading(self, report_attrs):
a_lines = []
for name, value in report_attrs:
line = self.HEADING_ATTRIBUTE_TMPL % dict(
name = saxutils.escape(name),
value = saxutils.escape(value),
)
a_lines.append(line)
heading = self.HEADING_TMPL % dict(
title = saxutils.escape(self.title),
parameters = ''.join(a_lines),
description = saxutils.escape(self.description),
)
return heading
def _generate_report(self, result):
rows = []
sortedResult = self.sortResult(result.result)
for cid, (cls, cls_results) in enumerate(sortedResult):
# subtotal for a class
np = nf = ne = 0
for n,t,o,e in cls_results:
if n == 0: np += 1
elif n == 1: nf += 1
else: ne += 1
# format class description
if cls.__module__ == "__main__":
name = cls.__name__
else:
name = "%s.%s" % (cls.__module__, cls.__name__)
doc = cls.__doc__ and cls.__doc__.split("\n")[0] or ""
desc = doc and '%s: %s' % (name, doc) or name
row = self.REPORT_CLASS_TMPL % dict(
style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass',
desc = desc,
count = np+nf+ne,
Pass = np,
fail = nf,
error = ne,
cid = 'c%s' % (cid+1),
)
rows.append(row)
for tid, (n,t,o,e) in enumerate(cls_results):
self._generate_report_test(rows, cid, tid, n, t, o, e)
report = self.REPORT_TMPL % dict(
test_list = ''.join(rows),
count = str(result.success_count+result.failure_count+result.error_count),
Pass = str(result.success_count),
fail = str(result.failure_count),
error = str(result.error_count),
)
return report
def _generate_report_test(self, rows, cid, tid, n, t, o, e):
# e.g. 'pt1.1', 'ft1.1', etc
has_output = bool(o or e)
tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid+1,tid+1)
name = t.id().split('.')[-1]
doc = t.shortDescription() or ""
desc = doc and ('%s: %s' % (name, doc)) or name
tmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL
# o and e should be byte string because they are collected from stdout and stderr?
if isinstance(o,str):
# TODO: some problem with 'string_escape': it escape \n and mess up formating
# uo = unicode(o.encode('string_escape'))
uo = e
else:
uo = o
if isinstance(e,str):
# TODO: some problem with 'string_escape': it escape \n and mess up formating
# ue = unicode(e.encode('string_escape'))
ue = e
else:
ue = e
script = self.REPORT_TEST_OUTPUT_TMPL % dict(
id = tid,
output = saxutils.escape(uo+ue),
)
row = tmpl % dict(
tid = tid,
Class = (n == 0 and 'hiddenRow' or 'none'),
style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'),
desc = desc,
script = script,
status = self.STATUS[n],
)
rows.append(row)
if not has_output:
return
def _generate_ending(self):
return self.ENDING_TMPL
##############################################################################
# Facilities for running tests from the command line
##############################################################################
# Note: Reuse unittest.TestProgram to launch test. In the future we may
# build our own launcher to support more specific command line
# parameters like test title, CSS, etc.
class TestProgram(unittest.TestProgram):
"""
A variation of the unittest.TestProgram. Please refer to the base
class for command line parameters.
"""
def runTests(self):
# Pick HTMLTestRunner as the default test runner.
# base class's testRunner parameter is not useful because it means
# we have to instantiate HTMLTestRunner before we know self.verbosity.
if self.testRunner is None:
self.testRunner = HTMLTestRunner(verbosity=self.verbosity)
unittest.TestProgram.runTests(self)
main = TestProgram
##############################################################################
# Executing this module from the command line
##############################################################################
if __name__ == "__main__":
main(module=None)
Read_excel.py---->用于读取Excel表中数据
'''
安装 pip install xlrd
打开文件 x1 = xlrd.open_workbook("data.xlsx")
获取sheet对象
print 'sheet_names:', x1.sheet_names() # 获取所有sheet名字
print 'sheet_number:', x1.nsheets # 获取sheet数量
print 'sheet_object:', x1.sheets() # 获取所有sheet对象
print 'By_name:', x1.sheet_by_name("test") # 通过sheet名查找
print 'By_index:', x1.sheet_by_index(3) # 通过索引查找
'''
'''
从excel文件中获取接口数据
1.打开文件
2.通过sheet名查找定位 一般在Excel表最下面
3.取第一行作为key值
4.获取总行数
5.获取总列数
6.通过方法循环字典获取列表中的值(每行的data) ---->从excel里面读取测试数据,返回字典格式
'''
import xlrd
class ExcelUtil():
def __init__(self, excelPath, sheetName="Sheet1"):
#打开文件
self.data = xlrd.open_workbook(excelPath)
#通过sheet名查找
self.table = self.data.sheet_by_name(sheetName)
# 获取第一行作为key值
self.keys = self.table.row_values(0)
# 获取总行数
self.rowNum = self.table.nrows
# 获取总列数
self.colNum = self.table.ncols
'''
1.首先判断excel表中总行数是否大于1,excel表中第一行一般都是类似于标题取第一行作为key,其余一般是内容
'''
def dict_data(self):
if self.rowNum <= 1:
print("总行数小于1")
else:
r = []
j = 1
for i in list(range(self.rowNum-1)):
s = {}
# 从第二行取对应values值
s['rowNum'] = i+2
values = self.table.row_values(j)
for x in list(range(self.colNum)):
s[self.keys[x]] = values[x]
r.append(s)
j += 1
return r
if __name__ == "__main__":
filepath = "./Excel_Data/jiekou.xls"
sheetName = "Sheet1"
data = ExcelUtil(filepath, sheetName)
print(data.dict_data())
ReqstCase.py----->封装requests请求类接收请求参数发起请求
"""
封装request请求方法
1.把从excel读取处理的数据作为请求参数,封装request请求方法,传入请求参数,并返回结果
2.为了不污染测试的数据,出报告的时候先将测试的excel复制到新的excel xlwd
3.把测试返回的结果,在新的Excel里面写入数据
"""
#requests请求库,对浏览器发起请求
import requests
#python自带单元测试模块
import unittest
#导包 excel中处理的数据
from Read_excel import ExcelUtil
#定义发送请求类
class SendReq():
def sedrq(self,data):
#获取excel中请求方法
'''
因为获取到的值是列表套字典,所以我们要循环依此遍历,得到具体行的具体参数
:param data:
:return:
'''
codelist = []
for da in data:
method = da['method']
# 获取excel中请求地址
url = da['url']
#获取excel中请求数据
paramter = eval(da['parameter']) #eval()执行字符串表达式,并返回表达式的值
#requests.request里面参数 method url 参数(请求方式,请求地址,请求参数)
# params-->接收请求参数
rq = requests.request(method,url,params=paramter)
codelist.append(rq.status_code)
# print(rq.status_code)
# print(codelist)
return codelist
if __name__ == '__main__':
'''接收Excel中处理数据'''
re = ExcelUtil('./Excel_Data/jiekou.xls')
'''接收请求参数'''
data = re.dict_data()
'''定义请求类'''
srq = SendReq()
srq.sedrq(data)
code = srq.sedrq(data)
for c in code:
print(c)
test_mathfunc.py---->用例断言(我们要测试的用例方法)
'''
1.导入unittest模块
2.导包我们来判断断言以及requests发起请求的响应结果是否一致
'''
import xlrd
#Python自带unittest单元测试报告
import unittest
#用来接收从excel中读取出来的数据
from Read_excel import ExcelUtil
#用来接收request请求发送的请求响应信息
from ReqstCase import SendReq
class TestMathFunc(unittest.TestCase):
def setUp(self) -> None:
print('开始')
def test_1(self):
'''第一个接口测试用例'''
rex = ExcelUtil('./Excel_Data/jiekou.xls')
data = rex.dict_data()
#第一个接口参数值
da = data[0]
code = da['yuqi_code']
# print(da)
srq = SendReq()
rq_code = srq.sedrq(data)[0]
# res = srq.sedrq(da)
# print(res)
assert rq_code == code
def test_2(self):
'''第二个接口测试用例'''
rex = ExcelUtil('./Excel_Data/jiekou.xls')
data = rex.dict_data()
# 第二个接口参数值
da = data[1]
code = da['yuqi_code']
# print(da)
srq = SendReq()
rq_code = srq.sedrq(data)[1]
# res = srq.sedrq(da)
# print(res)
assert rq_code == code
def tearDown(self) -> None:
print('结束')
if __name__ == '__main__':
unittest.main()
suitcase.py---->生成测试报告
import unittest
from test_mathfunc import TestMathFunc
from Common.HTMLTestRunner import HTMLTestRunner
class Test():
# tp = Tptest()
def tps(self):
suit = unittest.TestSuite()
test = [TestMathFunc('test_1'),TestMathFunc('test_2')]
suit.addTests(test)
with open("./inter.html", "wb") as f:
HTMLTestRunner(
stream=f,
title="接口测试",
description="python + unittest + excel + requests + Htmltestrunner",
verbosity=2
).run(suit)
#python+requests+unittest+htmltestrunner+ecl 接口自动化的测试框架
t = Test()
t.tps()
jiekou.xls ----->接口参数请求数据来源

inter.html ------->测试报告用例样式

python+requests+unittest+htmltestrunner+Excel生成接口自动化的测试框架的更多相关文章
- 基于Python+Requests+Pytest+YAML+Allure实现接口自动化
本项目实现接口自动化的技术选型:Python+Requests+Pytest+YAML+Allure ,主要是针对之前开发的一个接口项目来进行学习,通过 Python+Requests 来发送和处理H ...
- Python+Selenium----使用HTMLTestRunner.py生成自动化测试报告2(使用PyCharm )
1.说明 在我前一篇文件(Python+Selenium----使用HTMLTestRunner.py生成自动化测试报告1(使用IDLE ))中简单的写明了,如何生产测试报告,但是使用IDLE很麻烦, ...
- 某互联网后台自动化组合测试框架RF+Sikuli+Python脚本
某互联网后台自动化组合测试框架RF+Sikuli+Python脚本 http://www.jianshu.com/p/b3e204c8651a 字数949 阅读323 评论1 喜欢0 一.**Robo ...
- Python+Excel+Unittest+HTMLTestRunner实现数据驱动接口自动化测试(一)
整个流程: 使用HTMLTestRunner的Run方法执行用例,用例调用Excel读取方法,将测试数据导入到unittest用例中执行,测试结果返回给HTMLTestRunner. 因为刚接触接口自 ...
- Python+requests+unittest+excel实现接口自动化测试框架
一.框架结构: 工程目录 二.Case文件设计 三.基础包 base 3.1 封装get/post请求(runmethon.py) import requests import json class ...
- Python+requests+unittest+excel实现接口自动化测试框架(摘录)
一.框架结构: 工程目录 二.Case文件设计 三.基础包 base 3.1 封装get/post请求(runmethon.py) 1 import requests 2 import json 3 ...
- Python+requests+unittest+excel实现接口自动化测试框架(转
一.框架结构:工程目录 二.Case文件设计三.基础包 base 3.1 封装get/post请求(runmethon.py) import requests import json class Ru ...
- 使用python+requests+unittest实现接口自动化测试
这两天一直在找直接用python做接口自动化的方法,在网上也搜了一些博客参考,今天自己动手试了一下. 一.整体结构 上图是项目的目录结构,下面主要介绍下每个目录的作用. Common:公共方法:主要放 ...
- python+requests+unittest执行自动化接口测试
1.安装requests.xlrd.json.unittest库 <1>pip 命令安装: pip install requestspip install xlrdpip install ...
- python+requests+unittest 接口ddt测试
以数据驱动的形式,将用例维护在py文件中 源码分析: 变量定义 publicParameters.py """ 公共参数 , 按照各公司实情,自行编写 "&qu ...
随机推荐
- Util应用框架基础(五) - 异常处理
本节介绍Util应用框架如何处理系统错误. 概述 系统在运行过程中可能发生错误. 系统错误可以简单分为两类: 系统异常 系统本身出现的错误. 业务异常 不满足业务规则出现的错误. 如何处理系统异常 如 ...
- Linux中修改文件权限方法
在此记录一下,看到的一篇写的比较好的帮我解决问题的文章 这里也补充一下,如果要修改当前目录下的所有文件时,文件名用 * 代替,如:chmod 755 *(即可修改当前文件下所有文件的权限为:-rwxr ...
- ALSA Compress-Offload API
概述 从 ALSA API 的早期开始,它就被定义为支持 PCM,或考虑到了 IEC61937 等固定比特率的载荷.参数和返回值以帧计算是常态,这使得扩展已有的 API 以支持压缩数据流充满挑战. 最 ...
- C语言一辆卡车撞人逃逸。现场三人目击事件,只记下车的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的;丙是位数学家说:四位的车号正好是一个整数的平方
#include <stdio.h> #include <math.h> void main() { int a, b, c, d, n, h; double t; for ( ...
- Python输入三个整数x,y,z,请把这三个数由小到大输出。
break_out = False while 1: s = [] for i in range(3): x = int(input('请输入一个数:\n')) if x == -1: # 设计一个退 ...
- python计算代码运行时间
记录一下自己用python编写计算运行时间的代码 时间类 import time import numpy as np # 编写时间类来方便操作 class Timer: def __init__(s ...
- 基于OpenAi通用特定领域的智能语音小助手
无穷尽的Q&A 钉钉...钉钉... 双双同学刚到工位,报销答疑群的消息就万马纷沓而来.她只能咧嘴无奈的摇摇头.水都还没有喝一口就开始"人工智能"的去回复.原本很阳光心情开 ...
- C# 基础编程题集锦
简单字符串加密 编写一个应用程序用来输入的字符串进行加密,对于字母字符串加密规则如下: 'a→d' 'b'→'e' 'w'→z' ...... x'→'a' 'y'→b' 'z→c' 'A'→'D' ...
- Scrapy-CrawlSpider爬虫类使用案例
CrawlSpider类型的爬虫会根据指定的rules规则自动找到url比自动爬取. 优点:适合整站爬取,自动翻页爬取 缺点:比较难以通过meta传参,只适合一个页面就能拿完数据的. import s ...
- ModuleNotFoundError: No module named '_pytest.resultlog'
新环境运行Python时报错 ModuleNotFoundError: No module named '_pytest.resultlog' 上网查,看到解决方法 https://www.cnbl ...