python unittest自动化测试框架

Байду номын сангаас
• base.py • 主要存放一些对页面操作的基础的方法。 • 例如,查找页面元素,点击一个按钮,向输 入框输入内容......
• page.py文件 • 存放一个对页面某个模块的操作,例如注册 模块,登录模块,实名认证模块......
• start_*.py文件 • 所有的测试用例都会放入到一个文件夹里, 组成一个测试用例集。
• • • • • • • •
测试用例集 创建一个用例集: suite=unittest.TestSuite() 方法1: unittest.defaultTestLoader.discover()方法 方法2: suite.addtest(unittest.makesuite(start_logi n.login)) 方法3: suite.addtest(login("test_wrongNameLogin "))
谢谢大家~
• 测试用例start_*.py详解 • class login(unittest.TestCase):
def setUpClass(cls): .......... def setUp(self): ........ def test_wrongNameLogin(self): . . def setDown(self): ....... def setDownClass(cls): .....
• python的基础知识 • 数据库的基本操作 • 前端的知识html/css ,javascript
case.xls
djr.py
base.py
page.py
run.py
start_*.py
repoort.html
测试用例的存放
• 将测试用例转化为Excel
• djr.py文件 • 这个文件主要是读取case.xls中的测试用例, 方便别的方法的调用。
run.py文件 运行测试用例,生成测试报告。 测试报告的生成引用第三方库文件 HTMLTestRunner生成一个html文件的测试报 告。
runner.run(suite)
• 多线程运行测试用例 • 创建一个线程: • threading.Tread()
• 分布式执行测试用例 • Selenium Grid 允许用户将测试案例分布在 几台机器上并行执行。用户可以在一个集中 控制点控制不同的环境。 • 启动一个hub节点 • 启动一个或者多个的node节点
合集下载

unittest的beautifulreport

unittest的beautifulreport

unittest的beautifulreport一、什么是u n i t t e s t?u n it te st是P yt hon中的一个测试框架,用于编写和运行单元测试。

它提供了一套用例管理、执行和断言等功能,帮助开发者对代码进行测试和验证,确保代码的质量和稳定性。

二、为什么要使用unitt est?使用un it te st可以有效地进行自动化测试,提高代码的可测试性和可维护性。

通过编写测试用例,可以验证代码的正确性、健壮性和性能等方面,提早发现潜在的问题,并且可以在代码进行修改时快速进行回归测试,确保修改不会引入新的错误。

三、unittes t的基本用法1.安装u n i t t e s tu n it te st是P yt hon的标准库,无需额外安装。

2.编写测试用例首先,我们需要编写测试用例来验证待测代码的功能。

测试用例是使用u ni tt es t提供的T es tC as e类编写的,每个测试用例通常是一个函数,函数名以"t es t_"开头。

例如,我们要测试一个名为`ad d`的函数,用于对两个数进行求和:i m po rt un it te std e fa dd(a,b):r e tu rn a+bc l as sA dd Te st Ca se(u ni tt es t.Te st Cas e):d e ft es t_ad d(se lf):r e su lt=a dd(2,3)s e lf.a ss er tE qu al(r es ul t,5)i f__na me__=='__ma i n__':u n it te st.m ai n()在上述示例中,我们编写了一个名为`Add T es tC as e`的测试用例类,其中定义了一个名为`t es t_ad d`的测试方法。

在测试方法中,我们调用了待测的`a dd`函数,并使用`a ss er tE qu a l`断言方法来验证返回结果是否等于预期值。

常见自动化测试工具及框架的选用

常见自动化测试工具及框架的选用

常见⾃动化测试⼯具及框架的选⽤作者:cai.ruiying[ZSK]⼀、⾃动化测试简介1、什么是⾃动化测试软件测试是软件产品开发过程中不可或缺的环节,众所周知,软件测试的分类⽅法⾮常多,根据不同的分类,测试可以分为很多种不同的测试⽅式。

如果根据不同的测试点分类,可以将测试分类划分为功能测试、性能测试,这也是我们最常见的的软件测试范畴。

⽽我们的⾃动化测试,⼀般意义上来说,是指对功能、性能进⾏脱离⼿⼯的⾃动化的测试。

对于⾃动化测试,更⼴泛的意义,是对界⾯功能的⾃动化测试。

因此,按照对软件测试的⾃动化程度,可以分为⼿⼯测试、⾃动化测试。

再进⼀步细分,界⾯⾃动化测试,⼜可根据平台的不同,分为Web⾃动化测试、移动端⾃动化测试,⽽他们的测试⼯具及框架基本是⼤相径庭的。

本⽂,我将依托Web UI⾃动化测试(⽹页界⾯功能⾃动化测试),简单谈谈我对⼏款常⽤的⾃动化⼯具及框架的看法。

2、它可以做⾃动化测试么关于⾃动化测试的适⽤性,⼀定要明确⼀点,那就是:不是所有的系统都适合做⾃动化测试!甚⾄有的系统根本⽆法做⾃动化测试。

那么什么样的系统适合做⾃动化测试呢?总结⼏点重要因素,如下图所⽰。

⼆、⼯具篇1、UFT(QTP)UFT 就是以前最常⽤的⾃动化测试⼯具QTP,⽤来进⾏Web UI⾃动化测试的。

QTP实现的是独占屏幕操作,仿真实际⽤户操作,⼀般⽤于回归测试和新版本测试。

它的特点是:⽀持Windows平台,使⽤VBScript编写测试脚本,相⽐Java/C#这类语⾔,显然更受测试⼈员欢迎。

它的测试流程是:【制定测试计划】-【创建测试脚本】-【增强测试脚本】-【运⾏测试】-【分析测试结果】。

QTP的脚本⽣成是通过轨迹录制,再进⾏增强优化,最后实现回放。

因此VBScript脚本的逻辑⽐较松散,因此对于复杂页⾯情况的处理能⼒⽐较弱,脚本维护的成本就⾮常⾼。

最重要的是,QTP是收费的,QTP11.5版本发布改名为UFT。

下图是UFT的⼯作台界⾯。

有哪些推荐的 Python 库或框架可用于接口自动化?

有哪些推荐的 Python 库或框架可用于接口自动化?

Python 作为一门高效、易用的编程语言,被广泛应用于接口自动化测试领域。

在Python 中,有许多优秀的库和框架可供选择,能够帮助测试人员快速、高效地完成接口自动化测试工作。

下面,我们将介绍一些推荐的 Python 库或框架,供大家参考。

1.requestsrequests 是 Python 中最常用的 HTTP 库之一,它提供了简单易用的 API,能够方便地发送 HTTP 请求和处理响应。

requests 支持 GET、POST、PUT、DELETE 等常用的 HTTP 方法,能够设置请求头、请求体、超时时间等参数,还支持自动处理cookies 和重定向。

requests 的文档详细、示例丰富,是 Python 接口自动化测试的必备库之一。

2.unittestunittest 是Python 自带的测试框架,它提供了丰富的断言方法和测试运行器,能够方便地编写和运行单元测试。

unittest 支持测试套件、测试用例、测试装置等概念,能够方便地组织测试代码。

unittest 还支持测试报告生成、测试覆盖率统计等高级功能,是Python 接口自动化测试的常用框架之一。

3.pytestpytest 是一个第三方的Python 测试框架,它提供了简单易用的API 和丰富的插件机制,能够方便地编写和运行各种类型的测试。

pytest 支持自动发现测试文件和测试函数,支持参数化测试、测试装置、测试标记等高级功能,能够方便地扩展测试功能。

pytest 还支持测试报告生成、测试覆盖率统计等高级功能,是Python 接口自动化测试的优秀框架之一。

4.PyMySQLPyMySQL 是 Python 中最常用的 MySQL 客户端库之一,它提供了简单易用的 API,能够方便地连接 MySQL 数据库、执行 SQL 语句和处理结果。

PyMySQL 支持事务、预编译语句、结果集转换等高级功能,能够方便地操作MySQL 数据库。

unittest.defaulttestloader用法

unittest.defaulttestloader用法

unittest.defaulttestloader用法「unittest.defaultTestLoader用法」是一个关于Python中unittest模块的一个具体应用。

unittest是Python内置的一个测试框架,用于编写自动化测试脚本。

在使用unittest进行单元测试时,defaultTestLoader 是一个用于加载测试用例的模块。

本文将详细介绍defaultTestLoader的用法,并一步一步回答关于该主题的问题。

一、unittest模块简介unittest是Python自带的一个测试框架,用于编写自动化测试脚本。

它提供了一系列的assert断言方法和测试执行器,可以方便地进行单元测试、集成测试和功能测试等。

unittest模块是基于Java语言的JUnit框架设计的,因此使用起来很类似于Java中的JUnit。

二、defaultTestLoader概述defaultTestLoader是unittest模块中的一个类,用于加载测试用例。

它提供了一系列的方法,可以帮助我们方便地从指定的目录或模块中获取测试用例,并生成一个测试套件用于执行。

三、defaultTestLoader的方法介绍unittest.defaultTestLoader主要提供了以下几个方法:# 1. loadTestsFromModule(module, pattern='test*')该方法用于从指定的模块中加载测试用例。

它会自动查找模块下的所有以"test"开头的函数,并将其作为一个测试用例添加到测试套件中。

参数说明:- module:指定的模块,可以是模块的引用或模块的名称。

- pattern(可选):指定用于匹配测试函数的模式,默认为"test*"(以"test"开头的函数)。

使用示例:import unittestclass MyTestCase(unittest.TestCase):def test_add(self):self.assertEqual(1 + 2, 3)def test_subtract(self):self.assertEqual(6 - 3, 3)if __name__ == '__main__':suite =unittest.defaultTestLoader.loadTestsFromModule(MyTestCase)runner = unittest.TextTestRunner()runner.run(suite)# 2. loadTestsFromName(name, module=None)该方法用于从指定的模块中加载一个指定名称的测试用例。

unittest 日志记录

unittest 日志记录

unittest 日志记录
unittest是Python自带的一个标准库,是一个单元测试框架,可以用来进行单元测试和自动化测试。

在使用 unittest进行日志记录时,可以参考以下方法:
- 测试类:测试类必须导入 unittest,并且必须继承 unittest.TestCase。

测试类中的方法名必须以`test_`开头,并且按照ASCII码顺序排列,因为测试运行顺序是按ASCII 进行的。

- 测试用例:测试用例是一个继承 unittest.TestCase的类,类中的方法才是实际的测试用例。

- 测试套件:测试套件可以看作测试用例的集合,可以将测试用例加入到测试套件中。

- 测试运行器:测试运行器的`run`方法用于运行测试。

- 测试加载器:测试加载器用于加载和查找测试用例。

可以通过 unittest 属性调用默认加载器进行加载查找,或者通过 Discover(test_dir, pattern='test*.py')方法通过文件所在目录加载查找测试用例并加到套件中。

- 测试夹具:测试夹具类似一个测试环境的容器,可以对测试环境进行初始化和销毁。

有三个控制级别,即方法级别、类级别和模块级别,常用的是方法级别和类级别。

- 断言:用于判断测试用例结果是否符合预期,符合则通过测试,否则测试不通过。

常用的断言有`assertEqual`等。

通过使用 unittest 框架并结合适当的日志记录方法,可以方便地记录和跟踪测试过程中的问题和错误,提高测试效率和质量。

Python自动化测试框架——生成测试报告

Python自动化测试框架——生成测试报告

Python⾃动化测试框架——⽣成测试报告如何才能让⽤例⾃动运⾏完之后,⽣成⼀张直观可看易懂的测试报告呢?⼩编使⽤的是unittest的⼀个扩展HTMLTestRunner环境准备使⽤之前,我们需要下载点击HTMLTestRunner后进⼊的是⼀个写满代码的⽹页,⼩编推荐操作:右键 --> 另存为,⽂件名称千万不要改python3使⽤上述HTMLTestRunner可能会报错,可以替换如下⽂件"""A TestRunner for use with the Python unit testing framework. Itgenerates 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 unittestimport 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 filefp = 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 optionsrunner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'# run the testrunner.run(my_test_suite)------------------------------------------------------------------------Copyright (c) 2004-2007, Wai Yip TungAll rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions aremet:* 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 copyrightnotice, this list of conditions and the following disclaimer in thedocumentation and/or other materials provided with the distribution.* Neither the name Wai Yip Tung nor the names of its contributors may beused to endorse or promote products derived from this software withoutspecific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "ASIS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITEDTO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR APARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNEROR 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, ORPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDINGNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS__author__ = "Wai Yip Tung"__version__ = "0.8.2""""Change HistoryVersion 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 datetimeimport ioimport sysimport timeimport unittestfrom 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 = fpdef 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)# ----------------------------------------------------------------------# Templateclass Template_mixin(object):"""Define a HTML template for report customerization and generation.Overall structure of an HTML reportHTML+------------------------+|<html> || <head> || || STYLESHEET || +----------------+ || | | || +----------------+ || || </head> || || <body> || || HEADING || +----------------+ || | | || +----------------+ || +----------------+ || || ENDING || +----------------+ || | | || +----------------+ || || </body> ||</html> |+------------------------+"""STATUS = {0: 'pass',1: 'fail',2: 'error',}DEFAULT_TITLE = 'Unit Test Report'DEFAULT_DESCRIPTION = ''# ------------------------------------------------------------------------# HTML TemplateHTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="/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 = '';}}}if (displayState != 'block' ) {displayState = 'block'details_div.style.display = 'block'}else {details_div.style.display = 'none'}}function html_escape(s) {s = s.replace(/&/g,'&amp;');s = s.replace(/</g,'&lt;');s = s.replace(/>/g,'&gt;');return s;}/* obsoleted by detail in <div>function showOutput(id, name) {var w = window.open("", //urlname,"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;}/* -- 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>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'>&nbsp;</div>"""# -------------------- The end of the Template class -------------------TestResult = unittest.TestResultclass _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 = Noneself.stderr0 = Noneself.success_count = 0self.failure_count = 0self.error_count = 0self.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 stderrself.outputBuffer = io.StringIO()stdout_redirector.fp = self.outputBufferstderr_redirector.fp = self.outputBufferdef complete_output(self):"""Disconnect output redirection and return buffer.Safe to call multiple times."""if self.stdout0:sys.stdout = self.stdout0sys.stderr = self.stderr0self.stdout0 = Noneself.stderr0 = Nonereturn 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. plete_output()def addSuccess(self, test):self.success_count += 1TestResult.addSuccess(self, test)output = plete_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 += 1TestResult.addError(self, test, err)_, _exc_str = self.errors[-1]output = plete_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 += 1TestResult.addFailure(self, test, err)_, _exc_str = self.failures[-1]output = plete_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 = streamself.verbosity = verbosityif title is None:self.title = self.DEFAULT_TITLEelse:self.title = titleif description is None:self.description = self.DEFAULT_DESCRIPTIONelse:self.description = descriptionself.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, '\nTime Elapsed: %s' % (self.stopTime-self.startTime) print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))return resultdef sortResult(self, result_list):# unittest does not seems to run in any particular order.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 rdef 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_TMPLdef _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 headingdef _generate_report(self, result):rows = []sortedResult = self.sortResult(result.result)for cid, (cls, cls_results) in enumerate(sortedResult):# subtotal for a classnp = nf = ne = 0for n,t,o,e in cls_results:if n == 0: np += 1elif n == 1: nf += 1else: ne += 1# format class descriptionif 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 namerow = self.REPORT_CLASS_TMPL % dict(style = ne > 0 and'errorClass'or nf > 0 and'failClass'or'passClass', desc = desc,count = np+nf+ne,)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 reportdef _generate_report_test(self, rows, cid, tid, n, t, o, e):# e.g. 'pt1.1', 'ft1.1', etchas_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 nametmpl = 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 = o.decode('latin-1')uo = eelse:uo = oif isinstance(e,str):# TODO: some problem with 'string_escape': it escape \n and mess up formating# ue = unicode(e.encode('string_escape'))# ue = e.decode('latin-1')ue = eelse:ue = escript = self.REPORT_TEST_OUTPUT_TMPL % dict(id = tid,output = saxutils.escape(str(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:returndef _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 baseclass 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)HTMLTestRunner⽬录结构如下:将HTMLTestRunner.py⽂件存放到package包下,将test_login.py存放到testcase⽬录下,⽤于编写测试⽤例,建⽴testreport包,⽤于存放测试报告,在email ⽬录下建⽴run_test.py,⽤于执⾏测试HTMLTestRunner的使⽤⽅法在代码注释中介绍和解释【test_login.py】from selenium import webdriverimport unittest,timeclass Login(unittest.TestCase):def setUp(self):#打开百度,搜索“163⽹易邮箱”,登录driver=webdriver.Firefox()driver.implicitly_wait(5)self.driver=driverdriver.get("https:///")driver.find_element_by_id("kw").send_keys("163邮箱登录")driver.find_element_by_id("su").click()name = driver.find_element_by_id("op_email3_username")password = driver.find_element_by_class_name("op_email3_password")login = driver.find_element_by_css_selector(".c-btn")#如下操作可以使setUp中的变量被其他模块调⽤=nameself.password=passwordself.login=logindef tearDown(self):self.driver.quit()def switch_window(self):#切换窗⼝for handle in self.driver.window_handles:self.driver.switch_to.window(handle)#j增加等待时间,可以提⾼测试⽤例执⾏的健壮性time.sleep(2)time.sleep(3)#成功登录def test_right_login(self):#账号密码⾃⾏填写.send_keys("xxx")self.password.send_keys("xxx")self.login.click()self.switch_window()#t通过新窗⼝的title验证⽤例是否通过self.assertEqual(self.driver.title,"⽹易邮箱6.0版","登录失败")#密码为空登录def test_null_psw_login(self):.send_keys("xxx")time.sleep(3)self.login.click()self.switch_window()# t通过新窗⼝的title验证⽤例是否通过self.assertEqual(self.driver.title,"⽹易帐号中⼼ > ⽤户验证","未跳转⾄⽤户验证界⾯")【run_test.py】#导⼊HTMLTestRunner的包from package import HTMLTestRunner#导⼊test_login的包,执⾏测试⽤例时需使⽤from testcase.test_login import *#定义要执⾏的测试⽤例的路径test_dir = './testcase'#定义要执⾏的测试⽤例的路径和名称格式#test_*.py的意思是,./testcase路径下⽂件名称格式为test_*.py的⽂件,*为任意匹配,路径下有多少的test_*.py格式的⽂件,就依次执⾏⼏个#开始执⾏if__name__ == '__main__':suit=unittest.TestSuite()suit.addTest(Login("test_right_login"))suit.addTest(Login("test_null_psw_login"))#以wb(可写的⼆进制⽂件)形式,打开⽂件,若⽂件不存在,则先执⾏创建,再执⾏打开 fp = open(filename, 'wb')#调⽤HTMLTestRunner⽣成报告runner = HTMLTestRunner.HTMLTestRunner(# 指定测试报告的⽂件stream=fp,# 测试报告的标题title=u"登录⽹易邮箱测试报告",# 测试报告的副标题description=u'⽤例执⾏情况(win7 64位)')#执⾏⽤例runner.run(discover)报告展⽰。

unittest测试框架

unittest测试框架1.unittest是python⾃带的⼀个⾃动化测试框架,有四个核⼼的概念: (1)testcase:测试⽤例,提供了基本类TestCase,可以⽤来创建新的测试⽤例,⼀个TestCase实例就是⼀个测试⽤例,其中的测试⽤例⽅法都以test开头,且执⾏顺序会按照⽅法名的ASCII值排序。

(2)testsuite:测试套件,把需要⼀起执⾏的⽤例放到⼀块执⾏,相当于⼀个篮⼦。

(3)testrunner:⽤来执⾏测试⽤例,并返回测试⽤例的执⾏结果,可以⽤图形或者⽂本接⼝将测试结果形象地展现出来,如HTMLTestRunner。

(4)testfixure:测试夹具,⽤来测试⽤例环境的搭配和销毁。

(避免下⼀条测试⽤例的执⾏受到上⼀条⽤例执⾏的影响)。

2.unittest断⾔: unittest中提供了⼀些⾃带的断⾔⽅式,使⽤⾃带的断⾔可以将⽤例的错误信息捕获到,主要有以下⼏种:⽅法检查assertEqual(a, b,msg=None)a ==bassertNotEqual(a, b) a !=bassertTrue(x)bool(x) is TrueassertFalse(x)Bool(x) is FalseassertIs(a, b) a is bassertIsNot(a, b) a is not bassertIsNone(x)x is NoneassertIsNotNone(x)x is not NoneassertIn(a, b) a in bassertNotIn(a, b) a not in bassertIsInstance(a, b)isinstance(a,b)assertNotIsInstance(a, b)not isinstance(a,b) 如果断⾔失败则会抛出异常,AssertionError(断⾔错误异常),成功则标识为通过,其中,断⾔时msg参数为异常信息,默认为None,若指定,则会将指定的值作为失败的错误信息返回。

Pytest单元测试

Pytest单元测试⼀、pytest单元测试框架1.什么是单元测试框架?单元测试是指在软件开发当中针对软件的最⼩单位(函数、⽅法)进⾏正确性的检查测试2.单元测试框架有哪些?Java:junit 和 testingpython:unittest 和 pytest3.单元测试框架主要做什么?1).测试发现:从多个⽂件⾥⾯去找到我们的测试⽤例2).测试执⾏:按照⼀定的顺序和规则去执⾏,并⽣成结果3).测试判断:通过断⾔判断预期结果和实际结果的差异4).测试报告:统计测试进度、耗时、通过率、⽣成测试报告⼆、单元测试框架和⾃动化测试框架有什么关系1.什么是⾃动化测试框架?把在⾃动化测试过程中⽤到的⼀些功能或者⼯具,分装成各个模块,包括如何进⾏⾃动化脚本编写以及分层功能的基础模块,进⾏持续集成、定时任务的管理模块,发送测试报告、进⾏测试结果统计分析的统计模块等,将这些模块组成⼀套可重⽤的⾻架2.作⽤1)提⾼测试效率,降低维护成本2)减少⼈⼯⼲预,提⾼测试的准确性,增加代码的重⽤性3)核⼼思想是:让不懂代码的⼈也能够通过这个框架去实现⾃动化测试3.pytest单元测试框架和⾃动化测试框架的关系1)单元测试框架:只是⾃动化测试框架中的组成部分之⼀2)pom设计模式:只是⾃动化测试框架中的组成部分之⼀3)数据驱动、关键字驱动、全局配置⽂件的封装、⽇志监控、selenium,requests⼆次封装、断⾔、报告邮件等等三、pytest简介1).pytest是⼀个⾮常成熟的python的单元框架,⽐unittest更灵活,容易上⼿2).pytest可以和selenium、requests、appium结合实现web⾃动化、接⼝⾃动化、app⾃动化3).pytest可以实现测试⽤例的跳过以及reruns失败⽤例重试4).pytest可以和allure⽣成⾮常美观的测试报告5).pytest可以和Jenkins持续集成6).pytest有很多⾮常强⼤的插件,并且这些插件能够实现很多的使⽤的操作# 如:pytestpytest-html # (⽣成html格式的⾃动化测试报告)pytest-xdist # (测试⽤例分布式执⾏,多CPU分发)pytest-ordering # (⽤于改变测试⽤例的执⾏顺序)pytest-rerunfailures # (⽤例失败后重跑)allure-pytest # (⽤于⽣成美观的测试报告)四、安装pytest安装pytest: pip install pytest五、pytest的命名规则1).模块名必须以test_开头或者以test_结尾2).测试类名必须以Test开头,并且不能有init⽅法3).测试⽅法必须以test开头六、pytest测试⽤例的运⾏⽅式和执⾏顺序1.运⾏⽅式1.主函数模式1).运⾏所有: pytest.main()2).指定模块: pytest.main(["test_01.py"])3).指定⽬录: pytest.main(["./test_py"])4).通过nodeid指定⽤例运⾏: nodeid有模块名、分隔符、类名、⽅法名、函数名组成pytest.main(["test_01.py::Test01Class"]) # 指定到类名pytest.main(["test_01.py::Test01Class::test003"]) # 指定到⽅法名2.命令⾏模式1).运⾏所有: pytest2).指定模块: pytest test_01.py3).指定⽬录: pytest ./test_py4).通过nodeid指定⽤例运⾏: pytest test_01.py::Test01Class::test0033.通过读取pytest.ini配置⽂件来运⾏pytest.ini这个⽂件他是pytest单元测试框架的核⼼配置⽂件 1).位置:⼀般放在项⽬的根⽬录 2).编码:必须是ANSI,可以使⽤notepad++修改编码格式 3).作⽤:改变pytest默认的⾏为 4).运⾏规则:不管是主函数的模式运⾏,还是命令⾏模式运⾏,都会去读取这个配置⽂件2.执⾏顺序unittest:根据Ascll的⼤⼩来绝对的执⾏的顺序pytest:默认从上到下改变默认执⾏顺序:使⽤mark标记@pytest.mark.run(order=3)七、Pytest⽣成⾃带的html测试报告安装pytest-html: pip install pytest-html1.直接执⾏pytest.main() 【⾃动查找当前⽬录下,以test开头的⽂件或者以test结尾的py⽂件】pytest.main([‘--html=./report.html’])2.pytest.main("模块.py")【运⾏指定模块下,运⾏所有test开头的类和测试⽤例】 pytest.main(["--html=./report.html","模块.py"])3.运⾏指定模块指定类指定⽤例,冒号分割,并⽣成测试报告pytest.main([‘--html=./report.html’,‘模块.py::类::test_a_001'])4.Pytest调⽤语句pytst.main(['-x','--html=./report.html','t12est000.py'])-x出现⼀条测试⽤例失败就退出测试-s:显⽰print内容-v:显⽰更详细的信息-vs:这两个参数⼀起使⽤-n:⽀持多线程或者分布式运⾏测试⽤例-reruns NUM: 失败⽤例重跑-x:只要有⼀个⽤例报错,那么测试停⽌--maxfail=2:出现两个⽤例失败就停⽌-k:根据测试⽤例的部分字符串指定测试⽤例5.使⽤@pytest.mark.skip()跳过该⽤例(函数)class Test01Class():@pytest.mark.skip # 跳过test001def test001(self):assert 5 == 4 # 断⾔6.pytest运⾏结果字符意义. 点号,表⽰⽤例通过F 表⽰失败 FailureE 表⽰⽤例中存在异常 ErrorS 表⽰跳过 skipped⼋、读取⽂件1.读取csv⽂件import csv #导⼊csv模块class ReadCsv():def read_csv(self):item =[] #定义⼀个空列表c = csv.reader(open("../commonDemo/test1.csv","r")) #得到csv⽂件对象for csv_i in c:item.append(csv_i) #将获取的数据添加到列表中return itemr = ReadCsv()print(r.read_csv())具体步骤:"""1.拿到开发的代码"""class CalcClass():def xf(self, a, b):c = a * breturn cdef cf(self, a, b):c = a / breturn c# cc =CalcClass()# ff = cc.xf(1,2)# print(ff)# gg = cc.cf(1,2)# print(gg)"""2.要测试的数据"""2,3,6"""3.读取CSV⽂件"""import csv # 导⼊csv模块class ReadCsv():def read_csv(self):item = [] # 定义⼀个空列表c = csv.reader(open("../dataDemo/a.csv", "r", encoding="utf-8")) # 得到csv⽂件对象for csv_i in c:item.append(csv_i) # 将获取的数据添加到列表中return item# r = ReadCsv()# print(r.read_csv())"""4.测试⽤例+⽣成测试报告代码"""from readDemo.readcsv import ReadCsvimport pytestfrom demo.calcDemo import CalcClassimport osimport allurer = ReadCsv()rr = r.read_csv()c = CalcClass()class TestCsv():def testcsv(self):for i in rr:bl = c.xf(int(i[0]), int(i[1]))assert bl == int(i[-1])if__name__ == '__main__':pytest.main(["--html=./Csvreport.html", "test_csv.py"])"""5.⽣成测试报告"""2.读取xml⽂件from xml.dom import minidomclass Readxml():def read_xml(self,filename,onename,twoname):root =minidom.parse(filename)firstnode =root.getElementsByTagName(onename)[0]secondnode=firstnode.getElementsByTagName(twoname)[0].firstChild.datareturn secondnode九、allure是⼀款轻量级并且⾮常灵活的开源测试报告框架。

Python自动化测试框架unittest与pytest的区别

Python⾃动化测试框架unittest与pytest的区别unittest pytest⽤例编写规则1)测试⽂件必须先importunittest2)测试类必须继承unittest.TestCase3)测试⽅法必须以“test_”开头4)测试类必须要有unittest.main()⽅法1)测试⽂件名必须以“test_”开头或者"_test"结尾(如:test_ab.py)2)测试⽅法必须以“test_”开头3)测试类命名以"Test"开头⽤例分类执⾏默认执⾏全部⽤例,也可以通过加载testsuit,执⾏部分⽤例可以通过@pytest.mark来标记类和⽅法,pytest.main加⼊参数("-m")可以只运⾏标记的类和⽅法⽤例前置和后置提供了setUp/tearDown,只能针对所有⽤例pytest中的fixture显然更加灵活。

可以任意⾃定义⽅法函数,只要加上@pytest.fixture()这个装饰器,那么被装饰的⽅法就可以被使⽤参数化需依赖ddt库使⽤@pytest.mark.parametrize装饰器断⾔很多断⾔格式(assertEqual、assertIn、assertTrue、assertFalse)只有assert⼀个表达式,⽤起来⽐较⽅便报告使⽤HTMLTestRunnerNew库有pytest-HTML、allure插件失败重跑⽆此功能pytest⽀持⽤例执⾏失败重跑,pytest-rerunfailures插件总体来说,unittest⽤例格式复杂,兼容性⽆,插件少,⼆次开发⽅便。

pytest更加⽅便快捷,⽤例格式简单,可以执⾏unittest风格的测试⽤例,⽆须修改unittest⽤例的任何代码,有较好的兼容性。

pytest插件丰富,⽐如flask插件,可⽤于⽤例出错重跑,还有xdist插件,可⽤于设备并⾏执⾏,效率更⾼。

Python3+Selenium3+PO+Yaml+ddt+UnittestUI自动化测试框架

Python3+Selenium3+PO+Yaml+ddt+UnittestUI⾃动化测试框架设计思路: 本⽂整理归纳以往的⼯作中⽤到的东西,现汇总成基础测试框架提供分享。

框架采⽤python3 + selenium3 + PO + yaml + ddt + unittest等技术编写成基础测试框架,能适应⽇常测试⼯作需要。

1、使⽤Page Object模式将页⾯定位和业务操作分开,分离测试对象(元素对象)和测试脚本(⽤例脚本),⼀个页⾯建⼀个对象类,提⾼⽤例的可维护性; 2、使⽤yaml管理页⾯控件元素数据和测试⽤例数据。

例如元素ID等发⽣变化时,不需要去修改测试代码,只需要在对应的页⾯元素yaml⽂件中修改即可; 3、分模块管理,互不影响,随时组装,即拿即⽤。

测试框架分层设计把常见的操作和查找封装成基础类,不管是什么产品,可直接拿来复⽤业务层主要是封装对象页⾯类,⼀个页⾯建⼀个类,业务层页⾯继承基础层⽤例层针对产品页⾯功能进⾏构造摸拟执⾏测试框架层提供基础组件,⽀撑整个流程执⾏及功能扩展,给⽤例层提供各页⾯的元素数据、⽤例测试数据,测试报告输出等测试框架⽬录结构编写⽤例⽅法1 testinfo:2 - id: test_login0013 title: 登录测试4 info: 打开抽屉⾸页5 testcase:6 - element_info: login-link-a7 find_type: ID8 operate_type: click9 info: 打开登录对话框10 - element_info: mobile11 find_type: ID12 operate_type: send_keys13 info: 输⼊⼿机号14 - element_info: mbpwd15 find_type: ID16 operate_type: send_keys17 info: 输⼊密码18 - element_info: //input[@class='keeplogin']19 find_type: XPATH20 operate_type: click21 info: 单击取消⾃动登录单选框22 - element_info: //span[text()='登录']23 find_type: XPATH24 operate_type: click25 info: 单击登录按钮26 - element_info: userProNick27 find_type: ID28 operate_type: perform29 info: ⿏标悬停账户菜单30 - element_info: //a[@class='logout']31 find_type: XPATH32 operate_type: click33 info: 选择退出34 check:35 - element_info: //div[@class='box-mobilelogin']/div[1]/span36 find_type: XPATH37 info: 检查输⼊⼿机号或密码,登录异常提⽰38 - element_info: userProNick39 find_type: ID40 info: 成功登录41 - element_info: reg-link-a42 find_type: ID43 info: 检查退出登录是否成功login.yamllogin.yaml例如,我们要新增登录功能测试⽤例:⾸先,只需在testyaml⽬录下新增⼀个页⾯对象yaml⽂件,参考login.yaml格式编写即可。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档