测试自动化凫弥

自动化测试,也叫软件测试自动化。要学习软件测试自动化,首先就需要清楚什么是软件测试。

因为当局者迷,旁观者清的道理,软件开发是个复杂而周期性的过程,期间很容易产生或遗留下错误,而对于开发人员自己所编写与开发的应用程序(软件),往往有很多问题是他们自己发现不了,所以如果直接把存在不足的、有错误、有漏洞的应用程序直接运营上线提供给用户使用,那么很可能会给企业带来商业风险或影响企业受益,所以就需要软件测试人员进行软件测试了。

而软件测试(SoftwareTesting)就是为了尽快尽早地发现软件的各种软件缺陷而展开的贯穿整个软件生命周期、对软件(包括阶段性产品)进行验证和确认的活动过程。这个过程是在规定的条件下对程序进行测试操作并对其是否能满足设计要求进行评估,以达到发现、纠正程序错误,衡量和提升软件质量的目的。通俗点说,软件测试就是通过各种各样的手段或工具来尽可能的找到软件的不足和错误。

软件测试只能查找出软件中的错误或不足,但不能证明程序中没有错误,而且软件测试不能完全消灭软件的错误,只能尽早尽量多的发现软件中的错误与不足。

软件测试从不同的角度有着不同的分类方式。

在实际开发中,往往我们都是根据实际情况采用多种不同的测试手段、测试方式来对软件测试测试的。

软件缺陷,通常又被叫做bug或者defect,即为软件或程序中存在的某种破坏正常运行能力的问题、错误,其存在的最终表现为用户所需要的功能没有完全实现,不能满足或不能全部满足用户的需求。

bug出现的原因一般有如下几种情况,也就是说符合以下情况的问题都属于bug:

在整个bug处理的流程上,一般会把bug划分成多个不同状态。

缺陷报告,也叫bug报告,是软件测试人员重要的产出物之一,也是主要工作之一。一份高质量的缺陷报告可以帮助开发人员快速定位问题,修复Bug;也便于测试人员对缺陷进行统计、分析和跟踪管理,是测试人员和开发人员重要的沟通工具。开发中针对需求,测试bug,最怕的就是口口相传。

参考模板:

缺陷报告就是软件测试的结果产出物,而如何验证和测试缺陷?那就要继续往下学习更多内容了。

著名的敏捷开发布道师MikeCohn(迈克·科恩)在他的着作《SucceedingwithAgile》(中文名:《Scrum敏捷软件开发》)一书中提出了测试金字塔的概念。

根据MikeCohn的测试金字塔,测试的组合应该至少由以下三层组成(自下往上分别是):

意思是,应该把测试不同粒度的测试分布到整个软件不同层次中,而随着层次越高,编写的测试内容应该越少,也就是写许多小而快的低层次单元测试,适当写一些更粗粒度的中层次接口测试或集成测试,写很少的高层次UI测试、系统测试或验收测试。

所以,根据测试金字塔理论,接下来我们按部就班对测试自动化的内容进行学习。

禅道项目管理软件(简称:禅道)集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体,是一款功能完备的项目管理软件,完美地覆盖了项目管理的核心流程。

禅道的主要管理思想基于国际流行的敏捷项目管理方式—Scrum。Scrum是一种注重实效的敏捷项目管理方式,它规定了核心的管理框架,但具体的细节还需要团队自行扩充。禅道在遵循其管理方式基础上,又融入了国内研发现状的很多需求,比如bug管理,测试用例管理,发布管理,文档管理等。因此禅道不仅仅是一款scrum敏捷项目管理工具,更是一款完备的项目管理软件。基于scrum,又不局限于scrum。

禅道最大的特色是创造性的将产品、项目、测试这三者的概念明确分开,互相配合,又互相制约。通过需求、任务、bug来进行交相互动,最终通过项目拿到合格的产品。

目前,禅道和JIRA用的人较多。我们这里以禅道为例。

禅道项目管理软件是做什么的?

为什么用禅道这个名字?

禅和道这两个字含义极其丰富,有宗教方面的含义,也有文化层面的含义。禅道项目管理软件取其文化含义,期望通过这两个字来传达我们对管理的理解和思考。这个名字是受《编程之道》和《编程之禅》这两本书的启发。英文里面的禅为Zen,道为Tao,所以我们软件的英文名字为zentao。

我们可以在Windows,Mac,linux平台去搭建禅道。

如果是Windows平台,安装目录一定是磁盘的根目录

Windows平台的默认账号密码:

账号:admin密码:123456docker部署禅道[root@C/]#mkdir-p/docker_data/zento_data2.拉取镜像

[root@C~]#dockerpullidoop/zentao:12.0.1dockerrun-d-p6003:80--restart=always-eADMINER_USER="root"-eADMINER_PASSWD="password"-eBIND_ADDRESS="false"-v/docker_data/zentao_data:/opt/zbox/--add-hostsmtp.exmail.qq.com:163.177.90.125--namezentao-serveridoop/zentao:12.0.1账号:admin密码:123456禅道使用流程创建角色角色:

为了方便,角色密码以都为root!1234。

组织--添加用户/批量添加用户

填写:

创建计划的好处有:

需求变更

要在变更流程之后,指定有谁评审,这里指定项目主管评审。

当需求变更通过后,该需求的状态变成激活状态。

项目立项一般都是开个立项会:

完事之后,一般由项目经理在禅道中建立项目。

PS:项目组成员在线下已经分配好了,但还需要在项目创建后,手动的关联,所以,称这个过程为创建项目和创建团队。

编写项目信息:

当项目创建后,需要设置项目团队(开发组/测试组),进行项目与产品及产品计划进行关联。注意,关联操作会自动的关联在产品计划中已激活的需求。也可以手动的关联需求。

开发在任务列表中,能看到指派给自己的任务都有哪些,并且任务的时长。

开发在开发该任务时,要每天填写工时,能及时查看任务进度。

当该任务已经完成后,即剩余工时为0时,可以选择结束该任务,那此时的任务就处于已完成的状态。

当所有的任务都完成后,并且开发自测通过后,就可以进行提测,在提测前,要进行构建版本的过程。

编写版本信息。

在版本信息的描述中,要注意:

版本构建成功后,如下图

该版本实现了哪些需求

默认的,开发人员无权做给版本关联需求的操作,该权限只有研发主管、项目经理有权限。

如何给开发赋予该权限:

注意,该操作适用于为所有的角色赋予指定权限。

勾(多)选需求,然后点击关联需求按钮。

关联需求成功后,在版本详情中,能看到关联的需求:

此时的项目,在当前产品计划中,开发阶段基本完成,可以向测试提测。

编写提测单:

编写测试用例。

创建成功:

测试视图---测试单---点击关联用例

勾选用例并点击保存。

关联成功:

注意,只有用例的状态是正常的,才能被关联。

一般的,我们写的测试用例都是需要评审的,但是默认的,禅道并没有开启用例评审权限。

需要评审的用例的状态是待评审状态。

注意,测试人员也能评审自己的用例(也可以使用admin账号取消测试人员的评审测试用例的权限),但一般选择测试主管来评审。

首先明确,用例执行是一个实际的操作过程,只是在禅道中记录这一过程,并且进行bug管理。

测试视图--用例列表----选择执行用例

编辑bug信息:

开发人员访问测试---bug,点击指派给我的,bug详情中,点击确认按钮。

当开发修复bug后,我们测试人员需要进行回归测试。

如果回归测试成功,选择关闭bug

如果回归测试失败,重新激活该bug,开发继续修复,我们在进行回归测试,直到回归测试成功,然后关闭该bug。

创建环境:

编辑当前环境的变量:

如何在请求中应用上环境中的变量?

使用{{变量名}}的方式使用环境中的变量值。

全局变量:作用于全局,postman中的任何地方

集合变量:变量只作用于集合中的接口

自定义环境变量:自己定义的环境,在该环境中创建的变量,只要你使用该环境,就能使用其中变量值。

如何创建全局变量

使用{{变量名}}来使用。

只作用于当前的集合中。

创建

作用于所有地方,使用{{$内置的变量名}}

常用的:

python中的断言,assert,断定结果是怎样的,否则就断言失败。

postman中,可用的模板?

//状态码断言pm.test("判断响应状态码是否是200",function(){pm.response.to.have.status(200);});//判断json中的keyvalue是否符合预期,如果你的key是嵌套结构,就点下去pm.test("Yourtestname",function(){varjsonData=pm.response.json();pm.expect(jsonData.args.k2).to.eql("v2");});//判断文本类型的响应文本中,是否包含指定的字段pm.test("判断响应体是否包含指定的字段",function(){pm.expect(pm.response.text()).to.include("百度一下");});集合公共断言创建集合公共断言。

可以将集合中的一些公共的断言写到集合配置中,在集合中的接口在执行时,会自动的应用上集合配置中的断言。

postman不会帮我们处理token,只能我们自己来完成:

简单来说,webservice是通过xml进行交互的web请求,本质上也是HTTP请求。

WebService也叫XMLWebServiceWebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术。是通过SOAP在Web上提供的软件服务,使用WSDL文件进行说明,并通过UDDI进行注册。

如何调试webservice接口

如上图,在启动集合的时候,有如下参数配置:

数据驱动这里:一般轮训次数会自动的根据你的数据行数来定。如果轮训次数大于数据行数,那么在剩余的轮训中,提取的数据就是数据文件的最后一行。

这个意思是新版本的nodejs要求的Windows系统在win8以上,你可以安装一个稍微低一点的nodejs,如12.x版本

打开tomcat的启动文件,一闪即逝,意思是你的Java环境配置的有问题,解决办法:

所谓的单元测试(UnitTest)是根据特定的输入数据,针对程序代码中的最小实体单元的输入输出的正确性进行验证测试的过程。所谓的最小实体单元就是组织项目代码的最基本代码结构:函数,类,模块等。在Python中比较知名的单元测试模块:

phpphpunitjavajavaunit参考内容:

所谓的测试用例(TestCase),就是执行测试的依据和记录,把测试应用程序的操作步骤用文档的形式描述出来的一份文档。文档的格式可以是Excel、markdown、html、xmind网页。

一份合格的测试用例有利于测试人员理清测试思路,确保需要测试的功能周全没有遗漏,方便测试工作的开展和评估测试工作量,同时还可以便于测试人员记录测试数据和测试工作进度,为后续的回归测试提供样本参考,提升测试效率以及后续测试工作的交接。

那么一份合格的测试用例长什么样子或有什么内容呢?

参考文档:

在实际工作中,因为缺陷报告与测试用例作用相似,因此有时候会合并一起或只选择其中一种。

那么在工作中,我们一般都应该编写测试用例或者应该怎么设计测试用例来完成我们的测试工作呢?实际上在工作中,测试人员都是基于测试用例的7种基本设计方法来设计与编写测试用例的:

一般在工作中,我们比较常用的是等价类划分法与判定表法。

等价类划分法就是按照测试要求,把具有共同特征的测试数据划分为2类:有效等价类和无效等价类,把测试数据进行分类以后设计测试用例。

使用等价类划分法,可以让我们设计的测试工作更加科学有依据,避免出现穷举测试的情况,减少测试用例的数量。

例如,注册功能中用户名的测试用例,如果功能需求中,要求用户名必须长度为3-11个长度的字符。

判定表是分析和表达多逻辑条件下执行不同操作的情况的工具。而软件测试中的判定表法,就是把输入数据的各种可能情况进行组合罗列成一个判断表格,以判断表来设计测试用例。

判定表的表结构一般有如下2种:横向判断表与纵向判定表。

横向判断表:

纵向判定表:

例子,测试一个功能是否能修改文件。

Unittest具备完整的测试结构,支持自动化测试的执行,对测试用例进行组织,并且提供了丰富的断言方法,还提供生成测试报告。

importunittestprint(dir(unittest))上面的代码中,我们就引入了Unittest模块,同时可以通过打印发现Unittest框架中内置了大量的工具成员。这些工具成员中除了以下5个以外,其他的都不怎么常用。

前面讲到TestCase就是提供给我们编写测试用例的测试代码的,那么怎么编写一个测试用例?需要4个步骤即可。

在实际工作中,我们肯定是在项目中进行测试代码的编写或单独编写一个测试项目,但是我们现在刚开始学习,所以我们可以先编写一个例子代码,对其进行测试,以达到学习的目的。

unittest_01_测试用例的编写.py,代码:

importunittest#被测试的代码单元defadd(x,y):returnx+yclassFuncTest(unittest.TestCase):"""测试用例"""deftest_01(self):print(add(10,20))deftest_02(self):print(add("hello","world"))#deftest_03(self):#print(add("hello",20))#因为pycharm本身内置了执行unittest的功能,所以不适用以下代码也能执行,但是终端下或者使用其他的代码编辑器时,则需要加上。if__name__=='__main__':unittest.main()测试套件-TestSuite前面我们将到测试套件,主要用于把多个测试用例类打包集成到一个测试集中一起执行。工作中,一个项目往往需要编写非常多的测试用例,而那么多的测试用例也不可能只编写在一个文件中,此时就需要使用测试套件了。2个步骤:

unittest_02_测试套件的基本使用.py,代码:

importunittestimportunittest_01_测试用例的编写asunittest_01suite=unittest.TestSuite()##1.添加测试用例方法#suite.addTest(unittest_01.FuncTest("test_01"))#suite.addTest(unittest_01.FuncTest("test_02"))##2.批量添加测试用例方法#test_data=(unittest_01.FuncTest("test_01"),unittest_01.FuncTest("test_02"))#suite.addTests(test_data)##3.添加测试用例类#suite.addTest(unittest.makeSuite(unittest_01.FuncTest))#4.批量添加测试用例类test_data=(unittest.makeSuite(unittest_01.FuncTest),unittest.makeSuite(unittest_01.FuncTest))suite.addTests(test_data)TestSuite的作用仅仅是把多个测试用例打包集成到一块,但是并没有提供批量执行测试用例的方法,所以我们需要使用TextTestRunner了。

前面说过,TextTestRunner是用于执行测试用例、测试套件和输出测试结果的。2个步骤:

unittest_03_测试运行器基本使用.py,代码:

importunittestimportunittest_01_测试用例的编写asunittest_01suite=unittest.TestSuite()##添加测试用例方法#suite.addTest(unittest_01.FuncTest("test_01"))#suite.addTest(unittest_01.FuncTest("test_02"))##批量添加测试用例方法#test_data=(unittest_01.FuncTest("test_01"),unittest_01.FuncTest("test_02"))#suite.addTests(test_data)##添加测试用例类#suite.addTest(unittest.makeSuite(unittest_01.FuncTest))#批量添加测试用例类test_data=(unittest.makeSuite(unittest_01.FuncTest),unittest.makeSuite(unittest_01.FuncTest))suite.addTests(test_data)if__name__=='__main__':runner=unittest.TextTestRunner()runner.run(suite)测试加载器-TestLoader前面说过,用于加载测试用例TestCase,并生成测试套件TestSuite,实现自动从代码中加载大量测试用例到测试套件中。2个步骤:

发现其他目录中的脚本用例:

importunittestsuite=unittest.TestLoader().loadTestsFromModule(ff_case)suite=unittest.TestLoader().loadTestsFromName(name="ff_case.TestCase.test_case_01",module=ff_case.TestCase)suite=unittest.TestLoader().loadTestsFromNames(names=["ff_case.TestCase.test_case_01","ff_case.TestCase.test_case_02",],module=ff_case.TestCase)unittest_04_测试加载器基本使用.py,代码:

importunittestloader=unittest.TestLoader()#在当前目录下,搜索以unittest开头作为文件名的所有python文件,并把文件中的测试用例类打包集成到测试套件中suite=loader.discover("./",pattern="unittest*.py")if__name__=='__main__':runner=unittest.TextTestRunner()runner.run(suite)测试脚手架-TestFixture前面提到,测试脚手架会在执行一些测试代码之前与之后,让我们编写一些初始化和销毁的代码,主要分三个级别:

在测试用例类中提供了2个固定名字的实例方法(setUp与tearDown),用于完成方法执行前与执行后的操作。

unittest_05_测试脚手架_方法级别的脚手架.py,代码:

importunittest#被测试的代码单元defadd(x,y):returnx+yclassAddTest(unittest.TestCase):"""测试用例"""defsetUp(self):print("每个方法执行前都会执行一遍setUp实例方法,用于完成通用的前置操作或初始化工作")deftearDown(self):print("每个方法执行后都会执行一遍tearDown实例方法,用于完成通用的后置操作或销毁工作")deftest_01(self):print(add(10,20))deftest_03(self):print(add("hello",20))#因为pycharm本身内置了执行unittest的功能,所以不适用以下代码也能执行,但是终端下或者使用其他的代码编辑器时,则需要加上。if__name__=='__main__':unittest.main()类级别的脚手架setUpClass与tearDownClass在测试用例类中提供了2个固定名字的类方法(setUpClass与tearDownClass),用于完成类执行前与执行后的操作。

unittest_06_测试脚手架_类级别的脚手架.py,代码:

importunittest#被测试的代码单元defadd(x,y):returnx+yclassAddTest(unittest.TestCase):"""测试用例"""@classmethoddefsetUpClass(cls):print("当前类执行前都会执行一遍setUpClass类方法,用于完成通用的前置操作或初始化工作")@classmethoddeftearDownClass(cls):print("当前类执行后都会执行一遍tearDownClass类方法,用于完成通用的后置操作或销毁工作")deftest_01(self):print(add(10,20))deftest_03(self):print(add("hello",20))#因为pycharm本身内置了执行unittest的功能,所以不适用以下代码也能执行,但是终端下或者使用其他的代码编辑器时,则需要加上。if__name__=='__main__':unittest.main()模块级别的脚手架setUpModule与tearDownModule在测试用例类中提供了2个固定名字的函数(setUpModule与tearDownModule),用于完成类执行前与执行后的操作。

unittest_07_测试脚手架_模块级别的脚手架.py,代码:

使用HTMLTestRunner模块可以直接生成HTML格式的报告。HTMLTestRunner是一个不再维护的第三方的模块,通过pip工具安装不了,只能下载后手动导入。

因为HTMLTestRunner是python2模块的,所以在python3.x以后需要做些修改才可以使用,修改后版本代码如下:

importunittestfromHTMLTestRunnerimportHTMLTestRunnerimportunittest_01_测试用例的编写asunittest_01suite=unittest.TestSuite()test_data=(unittest.makeSuite(unittest_01.FuncTest),unittest.makeSuite(unittest_01.FuncTest))suite.addTests(test_data)if__name__=='__main__':#生成html报告withopen("test_report.html","wb")asfile:runner=HTMLTestRunner(stream=file,title="单元测试的HTML格式报告",description="python单元测试报告",tester="墨落")runner.run(suite)断言断言(assertion)是一种在程序中的判断测试用例执行结果是否符合预期结果的方式,所以断言也被称之为“期望”。当程序执行到断言的位置时,对应的断言应该为真。若断言不为真时,程序会中止执行,并给出错误信息。

unittest中常用的断言方法(加粗为重要方法):

unittest_09_断言.py,代码:

importunittestdefadd(x,y):returnx+yclassAddTest(unittest.TestCase):deftest_01(self):res=add(1,2)#断言结果是否与预期内容相同#self.assertEqual(res,3,msg="断言失败!一般会错误的结果与原因")#self.assertEqual(res,2,msg="断言失败!一般会错误的结果与原因")self.assertIn(res,[1,2],msg="断言失败!一般会错误的结果与原因")if__name__=='__main__':unittest.main()用例执行成功用.表示,执行失败是F表示。unittest.main()会自动的找到当前模块的unittest.TestCase的子类,然后找该子类内部以test开头的用例名,完事去一一的执行它们。

@unittest.skip(reason)#跳过用例的描述@unittest.skipif(condition,reason)#跳过的条件,跳过的原因unittest_10_跳过.py,代码:

importunittestclassMyCase(unittest.TestCase):deftest_case_01(self):self.assertTrue(1)@unittest.skip(reason='无条件跳过')deftest_case_02(self):self.assertTrue("")@unittest.skipIf(condition=3<2,reason='有条件跳过')deftest_case_03(self):self.assertTrue(0)if__name__=='__main__':unittest.main(verbosity=2)在输出的窗口中,跳过的用例用s表示;断言成功.表示;断言失败F表示。

当需要使用多组不同的测试数据测试同一个方法时,可以使用unittest参数化来解决。常用的参数化方法有ddt、parameterized

pipinstallparameterizedunittest_11_参数化.py,代码:

importunittestfromparameterizedimportparameterizeddefadd(x,y):returnx+yversion=(2,7,0)classAddTest(unittest.TestCase):defsetUp(self):print("setUP执行....")@parameterized.expand([(10,20),("a","B"),(50,20)])deftest_00(self,x,y):res=add(x,y)self.assertIn(res,[1,30,"aB",70],msg="断言失败!一般会错误的结果与原因")#deftest_01(self):#res=add(1,2)#self.assertIn(res,[1,3],msg="断言失败!一般会错误的结果与原因")##deftest_02(self):#res=add("a","B")#self.assertEqual(res,"aB",msg="断言失败!一般会错误的结果与原因")##deftest_03(self):#print(add("a",20))if__name__=='__main__':unittest.main()数据驱动测试Data-DrivenTests(DDT)即数据驱动测试,可以实现多个数据对同一个方法进行测试,达到数据和测试代码分离,目的是为了减少测试用例的数量。

基本安装

pipinstallddt直接传递单个数据

unittest_12_参数化_基于ddt直接传递数据.py,代码:

importunittestfromddtimportddt,datadefadd(a,b):returna+b@ddtclassAddTest(unittest.TestCase):##单次传递一个数据到测试用例方法中#@data(100)#@data([1,2,3,4])#@data({"a":1,"b":2})#@data((1,2,3))##多次传递一个数据到测试用例方法中#@data(*["a","b","c"])#字符串#@data(*[{"a":1},{"a":2},{"a":3}])#字典#@data(*[[1,1,1],[1,1,2],[1,1,3]])@data([1,1,1],[1,1,2],[1,1,3])deftest_01(self,a):print(a)if__name__=='__main__':unittest.main()unittest_13_参数化-基于ddt解包传递多个数据.py,使用unpack装饰器解包数据

Pytest是基于Python语言的单元测试框架,也是一个命令行的工具,比unittest测试框架更灵活。具有以下特点:

安装

pipinstallpytest#测试是否安装成功pytest--version快速入门基本格式pytest_01_基本格式.py,代码:

defadd(x,y):returnx+yclassTestAddFunc(object):#测试用例类名必须用Test开头,若执行收集不到用例则将文件名改为test_开头试试deftest_01(self):#方法名与函数名必须要用test_开头print(add(10,20))deftest_02(self):print(add("a","B"))deftest_03(self):print(add("a",20))测试运行pytest提供了三种方式给测试人员执行测试用例:

类级别:setup_class与teardown_class,注意:这是实例方法,不是类方法

模块级别:setup_module与teardown_module

pytest_02_测试脚手架.py,代码:

defadd(x,y):returnx+ydefsetup_module():print("模块执行初始化操作")defteardown_module():print("模块执行初始化putest")classTestAddFunc(object):#测试用例类名必须用Test开头defsetup(self):print('setup执行初始化操作')defteardown(self):print('teardown执销毁操作')defsetup_class(self):#注意:此处方法类型是实例方法。print('类级别:setup_class执行初始化操作')defteardown_class(self):#注意:此处方法类型是实例方法。print('类级别:teardown_class执行初始化操作')deftest_01(self):#方法名与函数名必须要用test_开头print(add(10,20))deftest_02(self):print(add("a","B"))deftest_03(self):print(add(20,20))基于配置文件运行pytest在pytest提供的终端运行测试用例的方式的基础上,pytest还支持使用配置文件来简化运行参数。

可以通过pytest--help查看pytest配置文件的名:pytest.ini、tox.ini、setup.cfg。

配置文件一般保存在项目根目录下。

pytest.ini,配置文件格式:

;命名空间,表示以下选项属于pytest配置[pytest];运行参数addopts=-s-v;匹配搜索的测试文件的目录路径testpaths=./;匹配搜索的测试文件名格式python_files=test_*.py;匹配搜索的测试类格式python_classes=Test*;匹配搜索的测试方法名格式python_functions=test_*;markersmarkers="测试标记-一般就是本轮测试的项目名或者模块"上面的注释,必须清除否则报错。有了配置文件以后,使用pytest命令即可运行测试用例。

pytest断言Pytest的断言比unittest提供的断言更加简单易用,仅仅只需要使用assert关键字,后续跟上python原生的表达式即可。

assert"m"in"moluo"assert"m"notin"moluo"assert1==2assert1!=1assert1>2assertnotTrueasserttype(1)isintasserttype(1)notisintpytest_03_断言.py,代码:

defadd(x,y):returnx+yclassTestAddFunc(object):#测试用例类名必须用Test开头deftest_01(self):#方法名与函数名必须要用test_开头res=add(10,20)assertres==30deftest_02(self):res=add("a","B")asserttype(res)isintdeftest_03(self):res=add(20,20)assertres!=20跳过根据特定的条件,不执行标识的测试函数。

@pytest.mark.skipif(判断条件,reason="跳过原因")pytest_04_跳过.py,代码:

importpytestdefadd(x,y):returnx+yversion=(2,7,12)classTestAddFunc(object):#测试用例类名必须用Test开头deftest_01(self):#方法名与函数名必须要用test_开头res=add(10,20)assertres==30@pytest.mark.skipif(version<=(2,7,12),reason="高于2.7以下,不测试test_02")deftest_02(self):res=add("a","B")asserttype(res)isintdeftest_03(self):res=add(20,20)assertres!=20参数化pytest也支持参数化操作,而且不需要安装任何第三方模块即可使用,也不再需要ddt。

importpytestdefadd(x,y):returnx+yclassTestAddFunc(object):#测试用例类名必须用Test开头@pytest.mark.parametrize("x,y",[(10,20),{"x":10,"y":20},("a","b"),("a",20)])deftest_01(self,x,y):#方法名与函数名必须要用test_开头res=add(x,y)assertres==30进阶使用fixture-脚手架在Unittest中我们经常需要针对不同的测试用例使用脚手架完成一些测试的前置与后置操作,但是很多测试用例的前置与后置操作基本一样,所以pytest提供的fixture脚手架相比Unittest提供的脚手架进行了显著改进:

pytest的fixture有个scope参数可以控制fixture的作用范围(从大到小):session>module>class>function。

代码:

importpytest@pytest.fixture(scope="class",autouse=True)deffixture_open_browser():print("打开浏览器")#相当于setupyield"xiaoming","123456"#生成器函数中的暂停关键字,作用是当代码运行到yield时,把yield右边的数据作为返回值提供给调用处,把代码执行权交出去。print("关闭浏览器")#相当于teardownclassTestUser(object):#object是一个基类,python中所有的类都是默认继承于object的。deftest_01(self,fixture_open_browser):print(f"fixture_open_browser={fixture_open_browser}")print("注册流程,测试用户是否能注册成功")deftest_02(self,fixture_open_browser):print(f"fixture_open_browser={fixture_open_browser}")print("登陆流程,测试用户是否能登陆成功")单独存放fixture代码我们还可以基于fixture脚手架把代码提前写好,放在在一个pytest能自动识别的conftest.py文件中,这样可以有效避免出现重复的fixture代码。注意:conftest.py的文件名必须固定,而且里面只存放fixture代码,并保证该文件与被测试代码文件在同一目录即可。

conftest.py,代码:

importpytest@pytest.fixture(scope="class",autouse=True)deffixture_open_browser():print("打开浏览器")#相当于setupyield"xiaoming","123456"#生成器函数中的暂停关键字,作用是当代码运行到yield时,把yield右边的数据作为返回值提供给调用处,把代码执行权交出去。print("关闭浏览器")#相当于teardown5-单独存放fixture代码.py,代码:

classTestUser(object):deftest_01(self,fixture_open_browser):print(f"fixture_open_browser={fixture_open_browser}")print("注册流程,测试用户是否能注册成功")deftest_02(self,fixture_open_browser):print(f"fixture_open_browser={fixture_open_browser}")print("登陆流程,测试用户是否能登陆成功")第三方常用组件控制测试用例执行顺序unittest执行测试用例的默认顺序是根据测试用例方法名的ASCII码排序[0-9A-Za-z]而定的,值越小,越靠前执行。

pytest执行测试用例的默认顺序是根据测试方法的源代码上下顺序来排序的。

而如果在完成接口测试或集成测试时,我们要控制测试用例的执行顺序,可以通过pytest的第三方模块pytest-ordering来实现。

pipinstallpytest-ordering使用

classTestAdd(object):@pytest.mark.run(order=n)#n表示执行顺序,可以是正负整数。deftest_测试方法名(self):pass#执行顺序为优先执行正数排序的方法,接着到没有排序的方法,最后是负数排序的方法。#如果多个方法都是正数,则先执行排序值小的,同理如果多个方法都是负数,也是一样先执行排序值小的。pytest-ordering.py组件的使用,代码:

"""前置步骤,安装插件:pipinstallpytest-ordering"""importpytestclassTestAdd(object):@pytest.mark.run(order=-1)deftest_01(self):print(f"test_01执行了,order=-1")@pytest.mark.run(order=-10)deftest_02(self):print(f"test_02执行了,order=-10")@pytest.mark.run(order=10)deftest_03(self):print(f"test_03执行了,order=10")@pytest.mark.run(order=3)deftest_04(self):print(f"test_04执行了,order=3")deftest_05(self):print(f"test_05执行了,没有指定排序值")deftest_06(self):print(f"test_06执行了,没有指定排序值")"""多个方法排序值为正整数的情况:以小为先test_04test_03没有排序值的情况下,源代码中先写的先执行,后写的后执行:先写为先test_05test_06多个方法排序值为负整数的情况:以小为先test_02test_01"""pytest-ordering用于解决测试开发中,UI测试、系统测试、接口测试等多个测试用例有先后流程的场景。

例如,系统测试的购物车流程:

注意:pytest-ordering组件如果和参数化fixtrue脚手架一起使用会导致参数解析错误,所以不能一起使用。因此pytest-ordering使用时,如果需要对测试用例实现参数化,则可以使用pytest.mark.parametrize,注意:不能使用ddt。

针对网络场景或服务端性能不稳定的情况下,进行测试时经常遇到用例运行失败的情况,特别在性能测试方面,此时我们可以让失败用例重试指定次数,以达到测试的更准确的结果。

importrandomdefadd(x,y):returnx+yclassTestAdd(object):deftest_01(self):res=add(10,20)assertresis30deftest_02(self):ret=random.randint(1,3)assertret%2==0配置文件pytest.ini,代码:

[pytest]addopts=--reruns3--reruns-delay2-s-vtestpaths=./python_files=test_*.pypython_classes=Test*python_functions=test_*局部失败用例重试局部失败用例重试.py,代码:

importrandomimportpytestdefadd(x,y):returnx+yclassTestAdd(object):deftest_01(self):res=add(10,20)assertresis30#只设置当前测试用例方法失败重试@pytest.mark.flaky(reruns=3,reruns_delay=2)deftest_02(self):ret=random.randint(1,3)assertret%2==0注意:

pipinstallpytest-xdist使用

pytest-xdist安装以后,pytest会新增一个参数-n,可以让我们指定本次运行测试所开启的进程数量。

参数设置如下:

pytest-s-v-n4#使用4个进程运行,也可以改成autopytest-s-v-nauto#自动检测系统的CPU核数,并根据CPU核算创建对应数量的进程数量pytest.ini,代码:

[pytest]addopts=-s-v-nautotestpaths=./python_files=test_*.pypython_classes=Test*python_functions=test_*代码:

defadd(x,y):returnx+yclassTestAdd(object):deftest_01(self):res=add(10,20)assertresis30deftest_02(self):res=add("10","20")assertres=="1020"deftest_03(self):res=add("10","20")assertres=="1020"deftest_04(self):res=add("10","20")assertres=="1020"deftest_05(self):res=add("10","20")assertres=="1020"deftest_06(self):res=add("10","20")assertres=="1020"自身生成HTML格式测试报告[了解下即可]安装

pipinstallpytest-html使用

安装插件到本地以后,在pytest运行参数中会新增选项:--html=report.html生成HTML格式测试报告.py,代码

importrandomimportpytestdefadd(x,y):returnx+yclassTestAdd(object):deftest_01(self):res=add(10,20)assertresis30#只设置当前测试用例方法失败重试@pytest.mark.flaky(reruns=3,reruns_delay=2)deftest_02(self):ret=random.randint(1,3)assertret%2==0pytest.ini,代码:

[pytest]addopts=-s-v--html=report.htmltestpaths=./python_files=test_*.pypython_classes=Test*python_functions=test_*AllureAllure是一款轻量级的开源自动化测试报告生成框架,Java语言开发出来的。它支持绝大部分测试框架,比如pytest、unittest等。比起上面那些丑陋的测试报告生成,Allure是最漂亮的,而且还可以配合pytest与Jenkins实现CI持续集成。pytest+Allure+git+pycharm+Jenkins+gitlab/gitee/github=CI持续集成

allure插件安装:解压压缩包到一个没有中文的目录中,然后将其中的bin目录添加到环境变量(PATH)中

测试,终端输入:

Allure的运行起来需要依赖于java环境,此处下载安装jdk1.8环境(Java8)。

此处我们演示windows下的java环境安装。

鼠标右键点选下载到本地的java的jdk安装包,选择以"管理员身份运行",窗口如下,勾选窗口左下角的"更改目标文件夹",点击"安装",进入下一步。

默认情况下,java的jdk会选择在C盘的"ProgramFiles"目录下安装,如果不想要在此目录安装,则可以点击更改,如果无所谓,则点击"下一步"即可。建议修改“ProgramFiles”之前的路径,后半段保持原样。

jre与jdk同样保存在一个父目录下即可。

OK,接下来,喝杯茶,等待一会即可。

效果如下,则没有问题。

注意:javasdk环境是依赖于JAVA_HOME的,依次打开控制面板系统与安全系统高级系统设置环境变量系统变量新建。变量名中输入JAVA_HOME,变量值中填写刚才获取到的路径C:\tool\Java\jdk1.8.0_201(注意,此处根据自己的实际路径填写,别瞎复制)。

保存了JAVA_HOME环境变量,点击下方的Path环境变量,里面把javasdk安装目录下bin目录加入到环境变量中。

cmd终端输入java-version,出现如下内容表示安装完成。

接下来,只需要安装allure集成到pytest的pytest-allure集成模块即可。

pipinstallallure-pytest基本使用生成allure测试结果,结果以json文件格式保存在--alluredir选项指定的目录下。

pytest.ini,代码:

[pytest]addopts=-s-v--alluredir=./allure_resultstestpaths=./python_files=test_*.pypython_classes=Test*python_functions=test_*基于json报告结果使用浏览器展示allure测试结果报告

allureserve./allure_results生成HTML格式文档的测试报告

HTML格式文档的测试报告也是要基于上面的json文件格式的测试结果才能生成的。

#必须先生成json格式的测试报告,才能生成HTML格式的测试报告alluregenerate./allure_results-o./reports--clean基于json格式的报告生成HTML报告,代码:

pythonmain.py补充:关于在python中可以执行命令行命令方法一:

settings.py

如何删除一个非空目录

用shuitil

接口自动化的框架开发:

实现思路:

我们要构建一个自动化测试框架,就要以项目的概念来对项目中所有的代码文件进行划分目录和文件结构,不同的代码功能不一样,所以我们需要设计一个合理的目录结构,以方便与测试开发团队的其他人员进行测试功能的开发与测试,也方便将来的项目代码维护。

根目录/├─config.py#项目代码配置文件├─pytest.ini#pytest模块配置文件├─main.py#主程序,执行入口├─api/#封装被测试项目的api接口存放目录[用于mock测试、冒烟测试]├─data/#测试数据/测试用例的存放目录├─allure_results/#测试报告结果生成目录├─allure_reports/#HTML测试报告生成目录├─tests/#测试用例脚本存放目录├─libs/#第三方工具类的存放目录[开源模块,不是当前项目封装的模块]└─utils/#自定义工具类的存放目录[当前项目自己封装的模块]配置文件,config.py,代码:

importpathlib#路径操作模块,替代os.path模块,os.path采用字符串来操作路径,pathlib采用面向对象来操作路径#项目目录的主目录路径[字符串路徑]BASE_DIR_STR=pathlib.Path(__file__).parent.resolve().as_posix()#基本操作系统转换路径的分隔符as_posix#項目目录的主目录路径[路径对象]BASE_DIR=pathlib.Path(BASE_DIR_STR)#项目名WEB_NAME="路飞自动化接口测试框架"#测试自动化项目的运行端口与IP地址HOST="127.0.0.1"PORT=8088#print(pathlib.Path(__file__))#D:\data\1045699\Desktop\luffy_code\testting\luffytest\config.py#print(BASE_DIR_STR,type(BASE_DIR_STR))#D:/data/1045699/Desktop/luffy_code/testting/luffytest#print(BASE_DIR,type(BASE_DIR))#D:\data\1045699\Desktop\luffy_code\testting\luffytest入口文件,main.py,代码:

[pytest]addopts=-s-v--alluredir=./resultstestpaths=./python_files=test_*.pypython_classes=Test*python_functions=test_*OK,完成了上面操作以后,我们就可以写一个测试用例来测试下现在我们的基本框架是否能正常运行了。

tests/users/test_login.py,代码:

注意:公司内部的代码不要私自自己往gitee(码云),github去推。

需要提前在当前开发机子上安装git代码版本管理工具。

我们是学习,所以我这创建项目库名luffytest。项目库名建议是英文的。

选择git-flow自定义分支模型。

所谓的分支,其实就是一个项目的代码的不同流程版本。

git-flow分支命名规范:

补充说明:

接下来,我们可以使用ssh连接远程的git仓库,需要先在本地电脑下生成ssh秘钥对。

复制终端下出现的公钥信息,复制到码云上面。

切换项目的仓库地址,设置线上仓库

gitconfig--globaluser.name"mooluo"gitconfig--globaluser.email"649641514@qq.com"#在项目根目录下初始化git仓库cdluffytest/#具体的路径根据自己的设置而定gitinit#gitremoteremoveorigin#删除仓库地址,origin可以理解是一个变量,因为当前时一个新仓库,所以不需要执行这段。gitremoteaddorigingit@gitee.com:mooluo_admin/luffytest.git#新仓库地址,等同于origin=git..../luffycity.git分支管理,git提交代码版本并同步到远程服务器。

gitbranch#查看分支#刚执行gitinit初始化时,会没有分支,因此我们需要进行第一次的代码提交。gitadd.gitcommit-m"feature:项目初始化"#经过上面的命令操作,本地的git就会自动生成一个master分支#gitbranch<分支名称>#新建分支#gitbranchtest#例如:创建一个test分支#gitcheckout<分支名称>#切换分支#gitcheckouttest#例如:切换到test分支,检出分支代码#gitbranch-d<分支名称>#删除分支#gitbranch-dtest#gitpush<远程仓库别名>--delete<分支名称>#删除远程服务器分支#gitpushorigin--deletetest#例如:删除远程仓库origin中的test#推送代码记录到远程服务器的代码仓库gitpushoriginmaster#推送的过程中,如果本地有该分支,但是线上没有这个分支,则git会自动在远程中创建该分支,默认的空仓库是一个分支都没有的。使用.gitignore可以在git上传或下载代码时,把一些不必要记录的垃圾文件/目录过滤掉。

注意:必须保证.git目录和.gitignore在同一级目录下,才能生效。

.gitignore文件内容:

gitadd.gitcommit-m"feature:新建.gitignore忽略文件"#推送代码记录到远程服务器的代码仓库gitpushoriginmastergitcommit提交版本的描述信息,编写前缀规范:

最终,成功提交了代码版本到gitee平台。

针对的项目开发,将来肯定需要把测试框架这个项目保存公司的服务器的,所以如果项目在公司服务器报错了,我们有可能不在场,或者其他同时去运作,那么我们针对当前这个项目在这个运行期间,有没有出现异常,那就需要记录整个项目的运行信息。

config.py,新增如下日志配置代码,代码:

importpathlib#路径操作模块,替代os.path模块,os.path采用字符串来操作路径,pathlib采用面向对象来操作路径#项目目录的主目录路径[字符串路徑]BASE_DIR_STR=pathlib.Path(__file__).parent.resolve().as_posix()#基本操作系统转换路径的分隔符as_posix#項目目录的主目录路径[路径对象]BASE_DIR=pathlib.Path(BASE_DIR_STR)#项目名WEB_NAME="路飞自动化接口测试框架-master"#测试自动化项目的运行端口与IP地址HOST="127.0.0.1"PORT=8088"""日志配置"""LOGGING={"name":"luffytest",#日志处理器的名称,一般使用当前项目名作为名称"filename":(BASE_DIR/"logs/luffytest.log").as_posix(),#日志文件存储路径,注意,一定要在项目根目录下手动创建logs目录"charset":"utf-8",#日志内容的编码格式"backup_count":31,#日志文件的备份数量"when":"d",#日志文件的创建间隔事件,m表示每分钟创建1个,h表示每小时创建1个,d表示每天创建1个,m0~m6表示每周星期日~星期六创建1个,midnight表示每日凌晨}在项目根目录下创建logs目录,并编写日志工具类,utils/logger.py,代码:

其中我们作为测试开发,比较常用的就是requests模块了。

Requests是一个Python编写,基于urllib的开源HTTP网络请求工具第三方库。它python内置的urllib模块使用更加简单便,可以节约我们量的作,完全满HTTP测试需求。

pipinstallrequestsrequests.request(method,url,**kwargs)类能够构造一个请求,支持不同的请求方式。

流式请求,指的不是请求是流,而是请求返回的数据流,返回一点取一点,而普通的请求是返回完毕你再取内容。

发送无参数的GET请求

demo/demo_requests.py,代码:

utils/requestor.py,代码:

pipinstallflaskpipinstallpymysqlpipinstallflask_sqlalchemy项目初始化api/__init__.py,代码:

importconfigfromflaskimportFlaskfromflask_sqlalchemyimportSQLAlchemy#SQLAlchemy初始化db=SQLAlchemy()app=Flask(__name__)definit_app():#加载配置app.config.from_object(config)#加载mysql数据库配置db.init_app(app)#db创建数据表withapp.app_context():db.create_all()returnappconfig.py,添加配置信息,代码:

createdatabasepytest;项目根目录下,单独创建run.py文件,启动mockserver,代码:

importconfigfromapiimportinit_app#注意,务必把模型models的内容以及views中的服务端接口引入当前文件,否则flask不识别。fromapiimportmodelsfromapiimportviewsapp=init_app()if__name__=='__main__':app.run(host=config.API_HOST,port=config.API_PORT)提交代码版本,代码:

gitadd.gitcommit-m"feature:基于flask实现mockserver"#推送代码记录到远程服务器的代码仓库gitpushoriginmaster编写测试用例测试mockservertests/users/test_login.py,代码:

gitadd.gitcommit-m"test:编写测试用例测试mockserver"#推送代码记录到远程服务器的代码仓库gitpushoriginmaster基于数据驱动生成用例代码在实际测试开发中,我们一般使用参数化来自动生成测试用例,前面介绍过常用的有ddt与parametrize。那么在pytest中,因为本身提供了parametrize参数化,所以我们往往会在unittest中采用ddt来实现参数化,而在pytest中采用内置的parametrize即可。

而参数化所需要的测试用例,一般我们也是可以采用json,yaml或Excel文件来存储,如果用例数量太多,还可以改成数据库保存。

YAML(递归缩写:YAMLAin'taMarkupLanguage,译作:YAML不是一种标记语言)是一种可读性高,用来表达数据序列化的数据格式,使用场景与xml、json类似,2001年首次发布,在最初开发YAML语言时YAML的意思其实是:"YetAnotherMarkupLanguage"(仍是一种标记语言)。后面之所以改了名称,原因是为了强调YAML语言以数据为中心,而不是以标记语言为重点。

1.大小写敏感2.使用缩进表示嵌套层级关系,且缩进不允许使用tab,只允许使用空格缩进(缩进的空格数不重要,只要相同层级的元素左对齐即可)3.'#'表示注释4.'~'表示空(None,null),也可以使用null表示None,但是尽量不要在属性中出现null或者~5.yaml文件中,属性唯一不能重复,否则报错6.文件扩展名为yml或yaml,如:data.yaml或者data.ymltest.yaml,代码:

username:'xiaoming'age:16数据类型类型名称对应python的数据类型描述纯量(scalars)整型、浮点型、布尔型、字符串、None单个的、不可再分的值数组(Array)列表、元祖一组按次序排列的值,又称为序列(sequence)/列表(list)对象(object)字典键值对的集合,又称为映射(mapping)/哈希(hashes)/字典(dictionary)纯量纯量是最基本的,不可再分的值。类似python中的字符串、布尔值、整型、浮点型、None等

pipinstallpyyaml基本使用

importyaml"""读取yaml文件的数据"""#withopen("./data.yaml","r",encoding="utf-8")asf:#content=f.read()#data=yaml.load(content,Loader=yaml.FullLoader)#print(data)#print(data["name"])"""把数据写入yaml文件"""fromdatetimeimportdatetimewithopen("./data2.yaml","w",encoding="utf-8")asf:#yaml.dump(data,f,Dumper=yaml.SafeDumper)#没有多字节内容的情况下data={"name":"xiaoming","age":17,"datetime":datetime.now(),"point":1.245464E10,"goods_list":[{"name":"xiaoming","age":17,"sex":True},{"name":"xiaoming","age":17,"sex":True},{"name":"xiaoming","age":17,"sex":True},{"name":"xiaoming","age":17,"sex":True},],"author_list":["小明","小白","小红"],"user_info":{"username":"小明","password":"123456"}}yaml.dump(data,f,Dumper=yaml.SafeDumper,allow_unicode=True)#有多字节内容的情况下,中文就是多字节内容封装yaml工具类,utils/yamler.py,代码:

importyamlfromloggerimportLogHandleclassYaml(object):"""yaml操作工具类"""__instance=Nonedef__new__(cls,*args,**kwargs):ifnotcls.__instance:print("创建Yaml的单例")cls.__instance=super(Yaml,cls).__new__(cls,*args,**kwargs)returncls.__instancedef__init__(self):self.logger=LogHandle().get_logger()defread(self,path):"""读取yaml文件"""withopen(path,encoding="utf-8")asf:result=f.read()ifresult:result=yaml.load(result,Loader=yaml.FullLoader)returnresultdefwrite(self,path,data):"""写入yaml文件"""try:withopen(path,"w",encoding="utf-8")asf:yaml.dump(data,f,Dumper=yaml.SafeDumper,allow_unicode=True)returnTrueexceptExceptionase:self.logger(f"写入数据到yaml文件失败:{e}")returnFalseif__name__=='__main__':ya=Yaml()data=ya.read("../demo/yaml_demo/data.yaml")print(data,type(data))提交代码版本,代码:

gitadd.gitcommit-m"feature:封装yaml工具类"#推送代码记录到远程服务器的代码仓库gitpushoriginmaster基于yaml数据驱动生成测试用例data/user_login.yaml,代码:

fromloggerimportLogHandlelogger=LogHandle().get_logger()defassertor(assert_list,response):"""断言函数"""iftype(assert_list)isnotlist:assert_list=[assert_list]forexprinassert_list:logger.info(f"开始断言:assert{expr}")ifexpr:exec(f"assert{expr}",{"code":response.status_code,"json":response.json(),"text":response.text,"content":response.content,"headers":response.headers,})logger.info(f"断言通过:assert{expr}")if__name__=='__main__':#Response就是模拟requestsHTTP请求工具的返回结果对象classResponse(object):status_code=400text="对不起,登陆失败!"content="对不起,登陆失败!"headers=[]@classmethoddefjson(cls):return{"id":1},assert_list=["code==400","'失败'intext",]assertor(assert_list,Response())tests/users/test_login.py,代码:

gitadd.gitcommit-m"feature:基于yaml数据驱动生成测试用例"#推送代码记录到远程服务器的代码仓库gitpushoriginmasterExcel在测试开发中,如果测试用例数量太多,使用yaml也存在很大的维护成本,此时可以考虑使用Excel或者数据库保存更多的测试用例,python中操作Exeel文件的模块有很多,常用的有:xlrd+xlwt,pyexcel+openpyxl等等。

安装模块

pipinstallxlrdpipinstallxlwt封装Excel工具类utils/excel.py,代码:

gitadd.gitcommit-m"feature:封装Excel工具类"#推送代码记录到远程服务器的代码仓库gitpushoriginmaster基于excel文件实现数据驱动生成测试用例tests/users/user_login.py,代码:

gitadd.gitcommit-m"feature:基于excel数据驱动生成测试用例"#推送代码记录到远程服务器的代码仓库gitpushoriginmaster认证测试基于jwt实现登陆正确,并在pytest中基于conftest脚手架使用生成器保持登陆状态

在用户注册/登陆以后,往往项目会返回登陆状态(jwt,session,cookie)提供给客户端,所以上面我们所实现的mockserver实际上是有问题的。因此接下来我们继续来模拟存在jwt认证鉴权的服务端,并在测试框架中基于conftest.py来实现认证测试的这个流程。

安装jwt

pipinstallflask-jwt-extendedconfig.py,代码:

#秘钥,不管是使用session还是jwt认证,都需要对认证的信息鉴权加密SECRET_KEY="ac361a52518d99f4525c1cfe5ba635572190aa6ac52bc8f27ae1b07529feafd0"api/__init__.py,代码:

importconfigfromflaskimportFlaskfromflask_sqlalchemyimportSQLAlchemyfromflask_jwt_extendedimportJWTManager#SQLAlchemy初始化db=SQLAlchemy()app=Flask(__name__)jwt=JWTManager()definit_app():"""服务端初始化"""#加载配置app.config.from_object(config)#加载mysql数据库配置db.init_app(app)#jwt初始化jwt.init_app(app)#自动创建数据表withapp.app_context():db.create_all()returnappapi/views.py,代码:

importpytestimportconfigfromutils.requestorimportRequestfromutils.yamlerimportYamlyaml=Yaml()@pytest.fixture(scope="class",autouse=False)defjwt_token():request=Request()request.logger.info("获取token")data=yaml.read(config.BASE_DIR/"data/test_user.yaml")response=request(data.get("method"),data.get("url"),json=data.get("json"))token=response.json().get("data",{}).get("token")yieldtoken#生成器函数中的暂停关键字,作用是当代码运行到yield时,把yield右边的数据作为返回值提供给调用处,把代码执行权交出去。request.logger.info("移除token")data/test_user.yaml,填写一个保存正确用户信息的用例,方便在conftest中发送正确的账户信息获取token,代码:

importallureimportpytestimportconfigfromutils.requestorimportRequestfromutils.yamlerimportYamlfromutils.assertorimportassertoryaml=Yaml()@allure.epic(config.WEB_NAME)@allure.feature("用户模块")@allure.story("用户中心")classTestUser(object):@pytest.mark.usefixtures("jwt_token")@pytest.mark.parametrize("kwargs",yaml.read(config.BASE_DIR/"data/user_info.yaml"))deftest_user(self,jwt_token,kwargs):allure.dynamic.title(kwargs.get('name'))request=Request()request.logger.info(f"开始请求测试接口:{kwargs.get('name')}")data=kwargs.get('request')data['headers']["Authorization"]=data['headers']["Authorization"].format(token=jwt_token)response=request(data.get("method"),data.get("url"),headers=data.get("headers"))assertor(kwargs.get("assert"),response)data/user_info.yaml,代码:

思路:

问题:如何获取域名?

Jenkins篇:

持续交付是一种软件开发实践。通过持续交付,系统可以自动构建和测试代码更改,并为将其发布到生产环境做好准备。持续交付可以在构建阶段后将所有代码变更都部署到测试环境和/或生产环境中,从而实现对持续集成的扩展。当持续交付得以正确实施时,开发人员将始终能够获得一个已通过标准化测试流程的部署就绪型构建工件。

参考:

前提:有java环境

支持各种的平台:

最低推荐配置:

为小团队推荐的硬件配置:

软件配置:

本次安装环境:阿里云服务器(centos7.4)+docker19.03.8

常用的镜像有两个:

管理jenkins--->mangesplugins--->可选插件,搜索要安装的插件,可选择,安装并且重启jenkins

由于下载地址是插件官网,可能会导致下载失败,然后安装失败.....

如果安装失败,就采用第二种方式。

方式2:

然后手动将下载到本地的hpi插件,上传到jenkins。

管理jenkins--->mangesplugins--->高级选项,下拉选择上传插件。点击本地文件上传

完事之后,重启jenkins,插件生效。

管理jenkins--->mangesplugins--->已安装,搜索要卸载的插件,并且勾选然后点击卸载。

修改/var/jenkins_home/hudson.model.UpdateCenter.xml文件,换国内源:

管理jenkins--->全局安全配置,勾选允许用户注册,完事点击保存。

管理jenkins--->管理用户

点击新建用户

创建成功后的用户列表:

这里只能删除普通的用户。

管理jenkins--->管理用户,点击红色按钮进行删除。

确认删除:

由于jenkins要和别的软件或者平台打交道,那么就要拿着先关凭据去做认证。

jenkins主页--->凭据--->全局凭据

此时进入到了全局的凭据列表,列出了所有的凭据。

如何添加凭据呢?

点击左侧的添加凭据按钮。

创建成功,会在凭据列表展示出来,可以点击右侧按钮编辑该凭据。

在凭据列表中,点击指定凭据后的小三角或者右侧的更新按钮,来修改凭据。

凭据列表,选择指定凭据后的小三角,选择删除选项。

确认删除。

在上述的配置GitHub账号密码的凭据中,有的时候会遇到如下问题:

如何解决:

可以使用ssh形式来解决:

github对SSH密钥做了升级,原来的SHA-1,rsa等一些已经不支持了,由于我使用的是rsa,可能和大部分用户一样,所以今天在push代码时候遇到了这个问题,记录以下。

在本机使用git来生成公钥私钥:

在本机(windows)的用户,你的用户下面有个.ssh目录,生成了公钥私钥两个文件。

添加成功。

在jenkins中,凭据管理下的凭据列表,添加一个凭据。

添加成功后的凭据列表:

如在job中:

不同的镜像依赖的基础镜像不同,导致容器内容的包管理工具也不同,如何查看以来的基础镜像:

[root@rdocker_data]#dockerexec-it-urootmyjenkinsbashbash-4.4#cat/etc/issueWelcometoAlpineLinux3.9Kernel\ronan\m(\l)常见的基础镜像的包管理工具有:

常用的apk的操作:

安装python3.6

bash-4.4#apkupdate-ybash-4.4#apkaddgccbash-4.4#apkaddbuild-basebash-4.4#apkaddzlib-devapksearchpython3apkaddpython3=3.6.9-r2bash-4.4#python3-VPython3.6.9bash-4.4#pip3-Vpip18.1from/usr/lib/python3.6/site-packages/pip(python3.6)pip3install--upgradepip参考:

在系统配置选项,下拉选择邮件通知选项:

如何配置?

后续的构建中,在构建后的操作中,就会自动发邮件。

常用的操作:

配置构建环境中的参数,后续再构建中,能直接是用的参数。

#Exampleofjobdefinition:#.----------------minute(0-59)#|.-------------hour(0-23)#||.----------dayofmonth(1-31)#|||.-------month(1-12)ORjan,feb,mar,apr...#||||.----dayofweek(0-6)(Sunday=0or7)ORsun,mon,tue,wed,thu,fri,sat#|||||#*****user-namecommandtobeexecuted分时日月周示例:

点击添加构建步骤:

常用的有:

allurecommandline会自动从$ALLURE_HOME目录读取json数据,生成allure报告。

注意,json数据目录在项目根目录下的allure-results目录;生成的报告在项目根目录下的allure-report目录中。我们可以通过在项目目录下看到。

就差左下角的保存按钮了。

我已经将制作好的镜像上传到了dockerhub上,咱们直接拉取即可:

dockerpullwangzhangkai/jenkins:1.0然后启动:

dockerrun\-uroot\--namemyjenkins\--restart=always\-d\-p6010:8080\-p50000:50000\--envJAVA_OPTS="-Xmx1024m"\-eJAVA_OPTS=-Duser.timezone=Asia/Shanghai\-v/etc/localtime:/etc/localtime\-v/tmp/jenkins_home:/var/jenkins_home\-v/var/run/docker.sock:/var/run/docker.sock\wangzhangkai/jenkins:1.0参考上述命令启动即可。

一般在提交的时候,遇到该问题。

解决,管理jenkins---->全局安全配置,下拉选择扩展请求保护,勾选启用代理兼容,下拉保存。

dockerrun\-uroot\--namemyjenkins\--restart=always\-d\-p6010:8080\-p50000:50000\--envJAVA_OPTS="-Xmx512m"\-eJAVA_OPTS=-Duser.timezone=Asia/Shanghai\-v/etc/localtime:/etc/localtime\-v/docker_data/jenkins_home:/var/jenkins_home\-v/var/run/docker.sock:/var/run/docker.sock\wangzhangkai/jenkins:1.0java.io.IOException:Failedtoload:LockableResourcesplugin(lockable-resources1069.v726298f53f8c)...解决办法:更新最新版本即可

管理所有的接口:

实现:

项目列表:

用例列表:

用例执行日志:

数据可视化:

遇到数据库问题,pycharm中无法连接或者无法识别mysql数据库。可能的原因:

adminLTE:

我们copy的是static/AdminLTE-master/starter.index修改静态文件的引用方式

it表

法1

pipinstallHTMLTestRunner-Python3pipinstallHTMLTestRunner-Python3==0.8.0但经过测试,发现源码有点问题,如果你在使用中遇到报错:

TypeError:abytes-likeobjectisrequired,not'str'就去源码的691行,修改:

#修改前self.stream.write(output)#修改后self.stream.write(output.encode('utf8'))其实源码中也提到了这点!

获取所有的选中状态的复选框:

$("#chk1").find('input:checkbox').each(function(){//遍历所有复选框if($(this).prop('checked')==true){console.log($(this).val());//打印当前选中的复选框的值}});functiongetCheckBoxVal(){//jquery获取所有选中的复选框的值varchk_value=[];$("#chk1").find('input[name="test"]:checked').each(function(){//遍历,将所有选中的值放到数组中chk_value.push($(this).val());});alert(chk_value.length==0'你还没有选择任何内容!':chk_value);}或者:

$("#sure").click(function(){vararr=newArray();$.each($(".p1"),function(index,item){//console.log(index,item)if($(item).get(0).checked){arr.push($(item).val())}});if(arr.length==0){//说明用户未选中用例,需要给提示//console.log(2222222,"未选中",arr);$("#errorMsg").html("请勾选至少一个用例!");}else{//编写后续的操作}});ajax如何处理跨域问题?有以下几种办法:

//序列化字典->字符串JSON.stringify(['A','B'])//反序列化字符串->字典JSON.parse()后端序列化与反序列化#序列化字典->字符串json.dumps(['A','B'])#反序列化字符串->字典json.loads()io在内存中创建一个文件句柄

fromioimportBytesIOfromioimportStringIOf=open('a.html','wb')#BytesIOf1=open('a.html','w',encoding='utf-8')#StringIO可视化前端从后端获取必要的数据,进行渲染展示

pyecharts的使用

使用:

前端

utils/EchartsHand.py

@csrf_exemptdefecharts_show(request):"""可视化"""ifrequest.is_ajax():data_dict={}data_dict.update(EchartsHandler().pie())data_dict.update(EchartsHandler().line_race())returnJsonResponse({'status':True,'data_dict':data_dict})returnrender(request,'echarts_show.html')定时任务常见用于定时任务的:

APScheduler

#!/usr/bin/envpythonimportosimportsysimportthreadingfromutils.CrontabHandimportrunif__name__=="__main__":os.environ.setdefault("DJANGO_SETTINGS_MODULE","auto_port.settings")try:fromdjango.core.managementimportexecute_from_command_lineexceptImportError:#Theaboveimportmayfailforsomeotherreason.Ensurethatthe#issueisreallythatDjangoismissingtoavoidmaskingother#exceptionsonPython2.try:importdjangoexceptImportError:raiseImportError("Couldn'timportDjango.Areyousureit'sinstalledand""availableonyourPYTHONPATHenvironmentvariableDidyou""forgettoactivateavirtualenvironment")raise#起一个线程执行定时任务#threading.Thread(target=run).start()execute_from_command_line(sys.argv)utils/CrontabHand.py

settings.py配置:

有两种常用的文件上传方式:

ajax上传

upload.html

把预览完成

使用echarts展示三个图:

每天凌晨1点30分50秒,检查it表,it_end_time是当前日期的接口项目,提取出来,获取该项目下所有的用例,批量执行一次,并生成log日志。

扩展:使用django发邮件,附件是批量执行的报告

建议:

多线程执行该任务

定时任务:-需求是:每天的凌晨1:30:20去检查it表,查看it_end_time是当天的,就把其关联的所有的用例执行一遍。-问题:如何实现?思路是随着django环境的运行,启动一个线程,调用一个job来实现需求。

UI测试(UserInterfaceTest,译作:用户界面测试),UI测试侧重产品的UI交互是否正确,模拟后端进行测试也可以,放在单元测试里去做也可以。

常用的web自动化测试工具有:selenium,Playwright、QTP、Cypress、Rapise、TestProject、Ranorex、Katalon、Subject7、Serenity等等

以下内容可参考:

提供了脚本录制功能和导出脚本。

火狐浏览器安装

火狐的插件管理中搜索seleniumide.

将该插件添加到浏览器。

添加成功如下:

在Google应用商店

添加该扩展程序。

解决:无法访问谷歌应用商店的问题:

Selenium是由杰森·哈金斯(JasonHuggins)于2004年在思特沃克(ThoughtWorks)开发的一款专门为Web应用而开发的自动化测试工具(最早是作为火狐浏览器的一个插件存在,内核基于javascript实现),适合进行功能测试、验收测试,同时支持所有基于web的管理任务自动化。简单来说,就是用程序模拟人操作浏览器网页,可以实现UI自动化测试。

Selenium基于webdriver协议可以控制浏览器模仿用户操作完成UI自动化测试,同时它也是一个生态系统,其主要功能包括:测试与浏览器的兼容性,测试应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能,创建回归测试检验软件功能和用户需求。Selenium包含了SeleniumIDE、SeleniumRC(Selenium2.0以后已经webdriver替代了)、SeleniumGrid。

Selenium发展到今天已经经历4个版本:Selenium1.0,Selenium2.0,Selenium3.0,Selenium4.0

特点:

注意:UI自动测试依赖于浏览器环境,所以浏览器务必不要设置为自动更新!!!下载的浏览器webdriver驱动一定要对应当前测试的浏览器版本。

selenium配置Chrome的驱动,该驱动需要和Chrome的版本保持一致(大版本)

安装webdriver驱动

python中安装selenium

解决方案:

fromselenium.webdriver.common.action_chainsimportActionChains基本使用

测试页面:

Title

测试双击与鼠标选放

importtimefromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.chrome.serviceimportServicefromselenium.webdriver.common.action_chainsimportActionChainsservice=Service("chromedriver.exe")driver=webdriver.Chrome(service=service)#打开一个网址driver.get("C:/Users/Administrator/Desktop/code/11-测试页面.html")element=driver.find_element(By.CLASS_NAME,'box')ActionChains(driver).move_to_element(element).perform()time.sleep(1)ActionChains(driver).double_click().perform()time.sleep(3)driver.quit()拖拽元素

fromselenium.webdriver.common.keysimportKeys方法名描述send_keys(Keys.ENTER)回车键Entersend_keys(Keys.BACK_SPACE)删除键BackSpacesend_keys(Keys.SPACE)空格键(Space)send_keys(Keys.TAB)制表键(Tab)send_keys(Keys.ESCAPE)复位键Escsend_keys(Keys.CONTROL,'a')全选Ctrl+Asend_keys(Keys.CONTROL,'c')复制Ctrl+Csend_keys(Keys.CONTROL,'x')剪切Ctrl+Xsend_keys(Keys.CONTROL,'v')粘贴Ctrl+Vsend_keys(Keys.F1)键盘F1…………send_keys(Keys.F12)键盘F12基本使用页面:

Titlehello!EveryBody!代码:

importtimefromseleniumimportwebdriverfromselenium.webdriver.common.byimportByfromselenium.webdriver.chrome.serviceimportServicefromselenium.webdriver.common.keysimportKeysservice=Service("chromedriver.exe")driver=webdriver.Chrome(service=service)driver.get("C:/Users/Administrator/Desktop/code/12-测试页面.html")time.sleep(3)element=driver.find_element(By.TAG_NAME,"textarea")element.send_keys(Keys.CONTROL,'a')element.send_keys(Keys.BACK_SPACE)time.sleep(3)element.send_keys("2012年9月25日,辽宁舰正式交付中国海军;2019年12月17日,山东舰入列,中国海军进入双航母时代;2022年6月17日,福建舰来了,我们有三艘航母了。")time.sleep(5)driver.quit()回车键等操作

主要是通过driver.save_screenshot来完成。

通过先获取HTML文档中的元素对象,再通过元素对象调用screenshot来进行截取。

基本使用:

WebDriverWait(driver=driver,timeout=10,poll_frequency=0.5,ignored_exceptions=None)WebDriverWait类提供了两个方法来完成等待条件的检测实现:

上面代码用到的method指定为expected_conditions模块并调用其presence_of_element_located方法判断指定元素是否存在。

expected_conditions模块提供了各种判断:

显式等待的另一种写法,首先实例化一个显式等待对象,这样可以在各个地方灵活的调用:

在等待机制的选择上,我们可以在三种等待机制中灵活选择:

在测试客户端时,往往存在有些功能流程需要点击打开并操作多个窗口页面的情况。此时就需要使用selenium在多个窗口中相互切换操作了。selenium中提供了三个方法给测试开发人员完成窗口切换操作。

常用的无头浏览器有:

如无特殊情况,推荐使用谷歌和火狐无头

上传文件非常的简单,也就是在send_keys中添加上文件路径即可。

随便输入一些描述信息。

fromseleniumimportwebdriverfromselenium.webdriverimportChromeOptionsfromselenium.webdriver.chrome.serviceimportServicefromselenium.webdriver.common.byimportByoption=ChromeOptions()option.add_experimental_option('excludeSwitches',['enable-automation'])#规避网站监测option.add_experimental_option('useAutomationExtension',False)#去掉开发者警告#开启浏览器的无头模式option.add_argument('--headless')option.add_argument('--disable-gpu')#允许在无GPU的环境下运行,可选option.add_argument('--window-size=1920x1080')#建议设置service=Service("chromedriver.exe")driver=webdriver.Chrome(service=service,options=option)driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",{'source':'Object.defineProperty(navigator,"webdriver",{get:()=>undefind})'})#规避网站监测注意:把chromedriver.exe保存到站点根目录下。

单元测试代码,users/test_login.py,代码:

gitadd.gitcommit-m"feature:selenium集成到pytest实现UI测试自动化"#推送代码记录到远程服务器的代码仓库gitpushoriginmasterAPP自动化测试APP移动端测试是指对移动端应用进行的测试,测试应用功能是否满足特定的需求。移动端测试一般分3类:APP功能测试、APP自动化测试、APP安全测试。其中常用的APP自动化测试工具有:Robtium、macaca、Appium、UiAutomator、Monkey、MonkeyRunner、Instrumentation、Athrun等等。

appium继承了selenium的webdriver,也就是selenium2.0,所以appium在调试中实际上也调用了selenium的某些功能。

appium起到了一个电脑连接移动端的桥梁,然后我们可以在电脑上调用selenium工具来调试移动端应用。

在这里client其实就是发起command的设备,一般来说就是我们编写代码执行的机器,执行appium测试代码的机器。狭义点理解,可以把client理解成是代码,当然这些代码可以是java/ruby/python/js的,只要它实现了webdriver标准协议就可以。

这样的设计思想带来了一些好处:

目前,java环境普遍来说使用的都是java8,所以我们直接下载安装1.8版本的sdk即可(jdk是Java语言的软件开发工具包,是整个java开发的核心,它包含了JAVA的运行环境,JAVA工具和JAVA基础的类库)。

鼠标右键安装(注意,不要把它安装到有中文的路径下,所以最好默认路径即可),一路点击确定下一步即可完成安装。

把下载下来的sdk压缩包解压到一个没有中文路径的目录下。例如:我的是C:/tool/

解压完成以后,进入sdk目录下,点击SDKManager.exe(sdk开发工具管理器,提供了类似pip的功能)。

按下面图中所示,勾选安卓开发最基本的7个模块到本地。

安装完成以后,AndroidSDKTools会在安装成功以后,从上面隐藏掉,不用在意。

接下来,需要把以下三个路径加入到环境变量中,让系统能识别androidsdk(注意根据自己实际的解压路径填写,不要瞎复制)。

cmd终端下输入命令adb,出现如下效果则安装正确。

需要注意的问题

解决办法:下载我的百度网盘中有AndroidSDK目录下jar包,将下载好的jar包放在platform-tools目录下

appium既支持使用真机测试,也支持模拟器测试。不过我们测试过程中实际上也并非一定要使用真机,因为我们测试的并非是移动端的操作系统而是app本身,所以很多时候测试开发过程中使用模拟器会更加方便,最关键的是模拟器可以轻松切换不同版本。这里推荐使用夜神模拟器(它不仅有windows版本,也有ios版本,而像其他的雷神模拟器,则仅支持windows版本,没有ios版本)。

提示:如果windows下同时安装了安卓模拟器和docker-desktop的同学,如果无法顺利启动模拟器,可能需要执行以下命令,切换模拟器与docker-desktop的虚拟化服务。

#使用模拟器bcdedit/sethypervisorlaunchtypeoff#使用docker-desktopbcdedit/sethypervisorlaunchtypeauto模拟器默认在安装以后会在bin目录下提供一个adb.exe安卓调试桥接工具(夜神模拟器叫nox_adb.exe),但是这个工具的版本有可能与我们安装的androidsdk的abd.exe版本不一样,这样会导致无法使用appium调试模拟器中的移动端应用,所以需要把androidsdk的abd.exe复制并改名替换掉模拟器bin目录下的adb.exe。真机测试则没有这个问题。

找到androidsdk安装目录下platform-tools目录下的adb.exe。

找到夜神安装目录的bin目录下的nox_adb.exe,并备份,然后替换成上面的。

同时打开模拟器中的配置,修改为手机版面,并开启开发者模式,并勾选开启USB调试功能。

点击7下召唤神龙~。。。。说错了,重来,点击7点是打开当前设备的开发者选项。

返回上一步,就可以看到多了一个开发者选项了,接下来,开启USB调试选项。

因为版本更新的原因,实际上appium是存在着2个分支版本的,分别是appiumServer与appiumDesktop。其中,appiumServer的安装比较复杂需要先安装node.js,所以目前来说官方已经不再更新与维护appiumServer分支了,而是推荐测试开发者安装appiumDesktop版本。所以此处,我们直接通过以下链接到github下根据自己当前使用的操作系统安装appiumDesktop即可。

下载到本地以后双击exe文件,一路默认安装即可。

完成上面操作以后,打开终端输入adbdevices,看到如下效果,则表示安装环境全部完成。

adbdevices的结果是当前连接到PC端的所有的移动端设备列表。左侧参数是设备ID,右侧参数是设备的连接状态。

如果使用模拟器则显示效果如下:127.0.0.1:5555device#表示雷电模拟器127.0.0.1:62001device#表示夜神模拟器

如果使用真机则显示效果如下:UJN0221722001562device

注意:鸿蒙手机实际上虽然不是安卓系统,但是鸿蒙手机为了兼容安卓,实际上也提供了adb调试,但是很遗憾的是,我们不能直接使用USB调试,只能改用wifi调试才可以测试鸿蒙系统下的app。

以下是开发中比较常用的adb命令:

安装:

#通过自动打包工具aapt,查看下载回来的apk的包名,并把源apk文件名改成包名。aaptdbadgingC:\Users\Administrator\Desktop\test\jd.apk#通过adb指定设备,进行安装adb-s127.0.0.1:62001installC:\Users\Administrator\Desktop\test\com.jingdong.app.mall.apk#卸载apk包adb-s127.0.0.1:62001uninstallcom.jingdong.app.mall安装appium-inspectorAppiumInspector是appiumServerUI内置的一个元素定位工具,在早期版本中是内置的,新版本已经分离了,所以可以通过以下链接进行安装。

Python想要操作appium,就要有专门的的连接工具模块-appium-python-client。直接安装即可。

pipinstallappium-python-clientOK。经过上面的步骤以后,appium的安装步骤就全部完成了。

在前面的Appium基本介绍时,我们提到过AppiumServer实际上就是一个HTTP服务器,它对外暴露了一系列的restfulAPI接口给开发者进行远程调用。

所以我们上面编写的python代码打开设置应用这个过程,本质上就是通过jsonwp(jsonwireprotocol,WebDriver开发者编写的一种通信协议)协议来实现对远程APP的操作的。

postman操作

初始化参数(Capability)可以编写在WebDriver测试代码中或者存放在AppiumServerGUI中(Inspector会话)。

常用的元素定位UI工具,有:uiautomatorviewer、AppiumDesktopInspector、Webditor等工具。

uiautomatorviewer

uiautomatorviewer是AndroidSDK自带的元素UI定位工具,在我们安装好AndroidSDK以后,默认就用有的。

双击打开效果如下:

点击以后,效果如下:

注意:uiautomatorviewer会与后面的工具产生冲突,所以使用uiautomatorviewer就不能使用下面2种工具了。

元素的bounds属性表示当前元素在APPActivatity中的距离左上角的坐标。

AppiumDesktopInspector

AppiumDesktopInspector是AppiumDesktop官方开发的工具,在早期版本中默认集成进来的,在最新版本中,需要我们手动安装,当然上面我们Appium环境安装完成以后就已经安装过这个AppiumDesktopInspector工具了。AppiumDesktopInspectord的使用必须保证在AppiumServer启动状态才可以使用。

AppiumDesktopInspector是基于jsonwp协议进行截屏审查元素的。所以需要创建会话才能获取当前APP的截屏。

所以直接打开效果如下:

Webditor

Webditor是python第三方模块UIautomator2(UIautomator2是Android内置的开源的自动化测试java框架,仅支持Android平台的原生应用测试,后来发展了python-uiautomator2,封装了谷歌自带的uiautomator测试框架,提供便利的python接口)提供的元素定位UI工具,是比上面2种元素定位UI工具更加强大的辅助工具,不仅支持Android,也支持IOS(不过需要单独安装tidevice)。不过要使用Webditor,需要先在当前python环境中安装python-uiautomator2模块。

#安装python-uiautomator2模块pipinstalluiautomator2pipinstallweditor使用工具,不过模拟器中得有adx软件

python-muiautomator2initpython-mweditor效果如下:

结合上面三种工具,我们可以发现在Android中对元素进行定位,一般可以依靠元素的以下属性进行定位。

appium的webdriver提供了11种元素定位方法,在selenium的基础上扩展了三个。

对元素的操作有:

作为测试人员就需要极可能早地避免针对上述情况的出现,因此我们的测试工具就需要把UI自动化用例维护成本降到最低,尽可能全面地覆盖回归业务。此时我们就需要自动遍历测试技术了。

使用自动遍历测试技术,可以让我们的测试工作使用更少的代码去覆盖更多的回归测试业务。常见的自动遍历工具,除了Android官方提供的Money,appcrawler以外,还有百度的smartmonkey、腾讯的newmonkey、字节的zhangzhaomaxim、seveniruby的appcrawler。其中大部分第三方开发的工具都是基于官方的monkey进行二次开发所衍生出来的,而eveniruby的appcrawler则是基于Appium所开发的工具。这两类的工具的使用对比存在以下优缺点:

基于Monkey实现的自动遍历测试工具:不可控,性能好,速度快,不具备跨平台能力。

基于Appium实现的自动遍历测试工具:可控可定制,性能差,速度慢,具备跨平台能力。

Monkey就是一个在模拟器或设备上运行的程序,可以自动生成随机用户事件,模拟用户的随机操作。Monkey是AndroidSDK自动工具,所以我们不需要单独安装直接可以使用。在Money使用过程中支持以下操作:

是国人seveniruby(思寒)基于appium开发的开源的多平台自动遍历工具,支持Android和IOS,支持真机和模拟器,灵活性高,可以通过yaml配置文件定制自动遍历规则的工具,还提供截图以及HTML测试报告。

appcrawler的使用提供了2种模式,终端参数模式与配置文件模式。终端参数模式比配置文件模式优先级高。

注意:appcrawler是基于Appium开发出来的,所以使用的时候,务必保证AppiumServer是启动状态。

java-jarappcrawler-2.7.4-hogwarts.jar--capability"appPackage=com.jingdong.app.mall,appActivity=.main.MainActivity"配置文件模式生成配置文件

java-jarappcrawler-2.7.4-hogwarts.jar--demo注意:在window下生成的配置文件,默认编写格式是GBK编码,而appcrawler的运行需要基于utf-8模式,所以务必在执行之前进行编码转换。

基于配置文件模型来启动appcrawler

Grid的基本使用架构分:Hub(一个集线器服务端)与Node(1个或多个分布式子节点)

因为SeleniumGrid是基于Selenium项目的,所以安装使用时必须保证当前运行环境中已经提前安装了selenium,同时还要保证webddriver要么已经配置到当前系统环境的环境变量中,要么就与接下来下载的SeleniumGrid的jar包在同一个目录。

SeleniumGrid提供了2种模式使用:单点模式与分布式。

其中单点模式,SeleniumGrid提供的一种让hub(集线器服务端)与node(分布式节点)在同一个服务器下测试使用的最简单配置模式。而分布式,则是允许hub节点与node节点不在同一个服务器下测试使用的配置方式。

分布式的前提是,必须hub服务端所在的操作系统与node分布式节点所在操作系统属于同一个网络,也就是相互之间可以访问。

启动Hub节点

java-jarselenium-server-4.3.0.jarhub#启动bub节点,默认端口:4444java-jarselenium-server-4.3.0.jarhub--port4455#--port指定端口启动Node节点

基于配置文件启动node节点

java-jarselenium-server-4.3.0.jarnode--configconfig.toml[node]port=5566hub=192.168.233.1:4444OpenSTFOpenSTF(SmartphoneTestFarm)是一个web端移动设备管理平台,可以让测试开发人员从浏览器端进行远程调试、管理移动端设备。

openstf支持原生安装,也支持docker安装。

macos安装如下:

brewinstallrethinkdbgraphicsmagickzeromqprotobufyasmpkg-config这里我们基于vmware安装的ubuntu操作系统下使用docker安装。

ubuntu20.04镜像下载地址:

vmware运行了网盘下载的ubuntu20.04镜像以后,在ubuntu终端下,直接运行如下命令:aliasdocker=podman拉取镜像

dockerpullopenstf/stf:latest#dockerpullsorccu/adb:latestdockerpullrethinkdb:latest启动镜像

冷启动通常会发生在以下两种情况:

在冷启动的最开始,系统需要负责做三件事:

一旦系统完成创建app进程后,app进程将要接着负责完成下面的工作:

一旦app进程完完成了第一次绘制工作,系统进程就会用mainactivity替换前面显示的预览窗口,这个时候,用户就可以正式开始与app进行交互了。

例如测试今日头条App的启动性能,使用步骤:

下载压缩包回到本地目录下(不要出现中文目录!!),解压并把内部的bin目录设置为环境变量。

使用步骤:

补充:

adb提供的录屏工具,除了录制app启动过程以外,实际在测试过程中也可以用于记录bug现场或者场景测试过程的。

目前在市面上的App无非三种:原生App(IOS、Android),混合App(H5+安卓外壳程序、H5+IOS外壳程序)、H5。

混合App中能运行使用H5网页,全依靠webview视口。

chrome浏览器自带的webview调试工具:chrome://inspect/。注意:连接的模拟器或真机必须是打开开发者选项并开启USB调试,同时chrome浏览器尽量采用高版本(>=89),

手机连接成功以后,直接打开chrome浏览器直接访问chrome://inspect/调试工具界面,然后在手机中打开一个网页或打开混合APP,点击inspect进入webview调试界面(这个界面需要FQ。)

点击打开network选项,即可查看webview中页面元素加载的性能参数。

借用W3C协议提供的性能参数来完成自动化H5性能测试。因为W3C标准是浏览器标准,市面上所有的浏览器都支持W3C标准,它规定使用者可以通过api查询性能信息。

window.performance.timing借用appium/selenium提供execute_script方法都可以执行js代码实现自动化获取性能指标,如下代码:

systrace在我们安装了AndroidSDK开发环境以后,默认内置在platform-tools/systrace子目录下,所以不需要单独安装systrace,但是要使用systrace工具则必须清楚systrace仅支持python2,不支持python3。

所以需要在本地开发机子上安装python2.7解释器,并保证python2.7的安装根目录以及scripts子目录被设置为系统环境变量即可。

例如,我们可以使用money来录制参数

可以通过GPU绘制柱状图来查看App系统资源加载性能,通过手机的开发者选项->监控->GPU呈现模式分析->在屏幕上显示为条形图。

adbshelldumpsysprocstats--hours2打印信息格式说明:

清理耗电量数据

adb-sUJN0221722001562shelldumpsysbatterystats--resetadb-sUJN0221722001562shelldumpsysbatterystats--enablefull-wake-history运行测试用例或手动操作测试功能,并收集耗电量数据

adb-sUJN0221722001562bugreportbugreport.zip#Androd得到报告以后上传到battery-historian的耗电量分析工具上即可。

因为battery-historian项目是基于go语言开发的,务必在本地安装好go(>=1.8.1),AndroidSDK与Python2.7等开发环境。

同时battery-historian并不支持手机模拟器的耗电量数据,所以我们也必须在真机环境下才能进行耗电量测试。

上传报告:*

耗电量报告效果如下:

弱网测试主要是为了测试移动端App在网络较差的极端情况下(如电梯、地下室等封闭环境)的表现。一般我们会认为如果网络速度低于3G网络就是弱网环境了。

在开发测试过程中,我们可以使用charles、fiddler、NEWT、Atc网络代理软件或浏览器开发者工具F12来模拟弱网环境。

弱网条件测试点:

点击Add...

Charles是在PC端常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析。除了在做移动开发中调试端口外,Charles也可以用于分析第三方应用的通讯协议。配合Charles的SSL功能,Charles还可以分析Https协议。Charles通过将自己设置成系统的网络访问代理服务器,使得所有的网络访问请求都通过它来完成,从而实现了网络封包的截取和分析。

开启弱网

弱网配置

安装charles证书

保证开启了charles的网络代理

打开本地网络代理设置。

打开手机网络代理->设置->WLAN->在可用WLAN中找到当前手机已经连接到电脑中的WLAN,长按连接的WLAN,并选择修改网络->在高级选项中设置代理选项为手动,然后填写charles所在电脑的IP地址为代理服务器主机名,端口为8888即可。如果是真机的弱网测试,务必要保证手机与chalers所在的电脑在同一个网络。

填写当前电脑IP地址,一般是本机以太网地址。

手机首次通过配置连接到charles代理服务端时会出现以下弹出框,直接点击Allow即可。

模拟器下会反复出现以下警告,直接不断点击继续即可。

有了弱网环境以后,就可以使用自动遍历测试工具,如Monkey,allcrawler进行弱网测试并记录测试的过程了。

健壮性测试用于测试App系统在出现故障时,是否能够自动恢复或者忽视故障继续运行。

我们可以设置App在无网络或使用上面的charles工具模拟弱网环境,然后结合之前学习过的money或appcrawler等自动遍历工具来测试App在当前极端环境下是否会因为某些功能,或某些数据、或某些模块出现异常而导致App出现崩溃或停滞现象。

例如,使用monkey在弱网下间隔5秒执行一个事件,运行50个事件测试App的健壮性。

HttpRunner目前最新的版本是v4版本,其中HttpRunnerv4相比于之前的v1/v2/v3/hrp版本进行叠加封装,同时采用了Golang/Python两种编程语言,底层会有两套相对独立的执行引擎,目标是兼具Golang的高性能和pytest的丰富生态。

hrp就是HttpRunner+(HttpRunnerPlus)。

下载完成以后解压放到本地目录下,并给该目录配置hrp服务的环境变量,我的电脑——属性——高级系统设置——环境变量,在PATH下新增系统变量。

hrp-v查看帮助

hrp-h快速上手创建项目

hrpstartprojecthr_demo目录结构

├─har/测试用例脚本转换工具(把har录制脚本转换成测试用例)├─reports/报告存放目录├─testcases/用例存放目录,1个文件就是一个测试用例,支持2种形态的测试用例脚本:文本形态(JSON、YAML)与代码形态(pytest和gotest)1个测试用例下基本涵盖两个:config【当前测试用例的全局配置】与teststeps【测试用例的测试步骤】├─.env本地项目的环境配置参数,不会被git提交到代码仓库├─.gitignoregit代码管理的忽视内容文件├─debugtalk.py插件函数存储文件如果扩展名是py,则表示当前HttpRunner项目采用pytest来驱动,如果扩展名是go,则表示当前HttpRunner项目采用gotest来驱动,└─proj.json项目描述配置文件,用于生成html测试报告运行测试用例

在reports目录下可以查看测试报告:

运行性能测试[PyTest格式的底层引擎基于pytest执行引擎,不支持性能测试]

hrpboomtestcases/www.luffycity.yml--spawn-count100--spawn-rate10输入性能参数:

各项参数说明:

基于django结合pytest、jenkins实现CICD持续集成、实现测试平台项目。

THE END
1.连笔英文签名设计在线生成有意思的谐音梗文案生成器! 火星文转换器 简繁体字、火星文一键转换! 流光字表情包 炫彩文字表情包! 免费连笔英文签名设计在线生成,艺术字网出品,采用英文签名字体帮助您设计个性英文签名。 连笔英文艺术字转换器:该英文签名设计款式由首至末,一气贯之,无丝毫倦意,一笔英文字体之下添加一段结尾曲线, 顿觉厚实开朗http://www.yishuzi.com/_yishuzi/b/15.htm
2.英文签名设计英文艺术签名设计免费版在线生成Your name潇洒英文签帅气英文签时尚大气英文签连笔英文签英文商务签英文花式签英文花体签英文书法签手写英文签一笔英文签英文艺术字体英文美术体连笔英文风格连笔装饰英文体简化英文签个性英文签英文浮夸签飘逸英文签60像素40像素50像素80像素100像素 点击图片可快速生成签名 http://www.uustv.com/yw.php
3.免费英文签名生成器生成字体分类发现字体免费英文签名生成器 标签: 生成 最后更新: 2025-01-02 共 5个字体 简介: 免费英文签名生成器 Sunflower Light语言:英文 下载 Semind语言:英文 下载 Avita-Regular语言:英文 下载 manula font total语言:英文 下载 Bonefish语言:英文 下载http://www.qiuziti.com/fontlist2?id=1042961
4.英文签名字体若需要为您的英文签名下载免费的字体,您可以浏览我们的英文手写体字体合集。 如果您不希望下载大量字体,您可以使用下方的字体转换器将输入的文本转换为图片。只需右键单击已生成的图片即可保存该图片,也可以点击「图片链接」按钮获取代码分享图片。 选择一个字体 https://fontmeme.com/zh/signature-fonts/
5.连笔英文艺术签名设计英文字体在线生成器SignGenerator急切网连笔英文艺术签名设计 英文字体在线生成器 Sign Generator 免费的英文艺术签名、英文签名设计:英文字体在线生成器! 艺术字体在线生成器英文版本 精选个性英文签名字体、英文艺术字体,包括一些手写英文、连笔英文、一笔英文,免费地为您在线生成转换!http://www.jiqie.com/a/m34.htm
6.英文字母生成器特殊英文字母符号在线生成英文字母生成器是可一键生成23种英文特殊字母,适用于个性英文昵称、网名、签名生成,支持一键复制。https://www.shubang.net/tools/english.html
7.签名字体转换器在线转换经典个性签名字体 名字设计签名字体 霸气签名字体 个人签名字体 英文签名字体签名字体艺术字知识 免费艺术签名在线生成器可以在线生成设计出个性艺术签名。 在线生成签名字体除了之前提到的意象签、合文签和花押签等艺术签名字体,还有下面一些: 竖式签名是将名字竖着签写、自上而下的签名。竖签法是我国最早的签名形式,也https://www.diyiziti.com/qianming
8.Ai艺术字体在线生成艺术字转换器字体转换器上一个艺术字体 下一个艺术字体 艺术字体在线生成控制台(增加倒影、投影、渐变等效果) 艺术字体 叶根卡通恶魔尾巴美呗嘿嘿体庞门正道细线体铁蒺藜体淘淘字体汉仪彩蝶体简汉仪海纹体华康金文字体腾祥相思简下雨了哦足球宝贝甲骨文字体哥特式字体海星田螺听不到啊圆圆字体我初恋了西良文字落落汤圆迷你双线秋生书法虾皮铭记https://www.yishuzi.cn/
9.免费签名设计在线生成免费签名设计一键生成器免费签名设计在线生成【免费签名设计一键生成器】 今天给大家分享一个可以帮助我们制作公务签、笔签、反笔签、形象签、仿英文签、防签、行草签、合体签、花体签、个性签各种设计风格的签名设计神器,就像下面这种,每个都特别的个性,书写方式呢有100多种,这只是一部分。https://www.shejilogo.com/article/design/1223.html
10.从近100篇文章中,挑选了这36个神仙工具,各个都堪称[外贸神器这是一个所见即所得的邮件签名设置工具。允许设置全名、工作职位、电话、网站、logo(允许logo居左、居中、居右)、设置社交网站 12、垃圾邮箱、无效邮箱自动给检查,清除工具 https://removebounce.com/ 手头有一大批邮箱,可能参杂了很多无效、垃圾邮箱。如何清理掉,保证邮件发放的成功率(不浪费钱)?靠人肉辨别是不靠https://www.cifnews.com/article/75093
11.艺术签名在线生成一笔签名设计在线艺术字体在线生成器艺术签名在线生成 一笔签名设计在线 艺术字体在线生成器_艺术字网 相似网站 包图网_专注原创商用设计图片下载,会员免费设计素材模板独家图库 包图网汇集了各种视觉冲击力强的原创广告图片设计、电商淘宝、企业办公模板、视频、配乐、音效、字体、插画动图、装饰装修等素材,由顶尖的设计师供稿,符合各个行业的商用需求,下载https://nav.dreamthere.cn/site/index/85013
12.设计师签名免费签名设计生成器在线签名生成转换设计师签名网是中国领先的艺术签名制作平台,免费签名生成转换器支持硬笔签、时尚签、立体签、行楷签等效果,集成草体签、瘦金签、板书签、童体签等功能智能实现在线签名设计,可生成png,svg,pdf格式,请牢记设计师签名 www.ssjjss.comhttp://www.ssjjss.com/
13.英文电子签名生成器Word模板下载编号ldorrpzg本模板为英文电子签名生成器,格式为word,其他风格,可用于校园教育演讲展示,文字图片可以直接替换,使用简单方便。https://www.tukuppt.com/muban/ldorrpzg.html
14.艺术签名在线生成器最高支持四个字的中文名字设计,如果是英文名请进入英文签名设计专用页面,这里只能输入中文,英文显示乱码。 艺术签名在线生成软件经过多年的迭代,现在是7.0版本,更新了多处细节,如调整签名字与字的间距,优化生成签名的风格等大幅提升用户体验。http://www.kachayv.cn/
15.免费在线签名生成器,rpa,机器人,自动化第一字体网签名字体转换器在线转换-签名字体在线生成器第一字体网提供永久免费的签名字体转换器在线转换、签名字体在线生成器,可选择不同的字号、行高、字体色和背景色,生成名家书法字体和个性艺术字体图片。还有艺术签名字体、英文个 英文个性签名字体温馨提示 1、 英文个性签名字体转换器在线转换生成成功后,请点击上面的https://www.wdlinux.cn/html/email/20241211/23843.html
16.CAD签名在线生成器3d溜溜设计问答平台为广大设计师们提供各种CAD签名在线生成器问题解答,3d溜溜素材问答平台汇聚全球各地的设计师、名师名司、设计爱好者等设计灵感和经验,迅速为您解决CAD签名在线生成器的困惑。https://www.3d66.com/answers_relation/relation_3314006_26.html
17.签名免费设计一笔签名在线一键生成安卓Android证书jks文件通过安卓证书制作工具一键制作android证书,在线生成jks证书文件,自定义别名及密码等信息,自动获取md5签名sha1&sha256签名 免费使用 1 2 免费制作安卓证书 Q:什么是安卓证书工具?解释 A:安卓证书工具是一门推出的android证书云端制作工具,可一键在线生成安卓JKS证书文件,jks证书文件请妥善保存哦。 http://zaixian.yimenapp.com/anzhuo-zhengshu-199.html
18.openssl之SSL签名相关介绍openssl证书签名详解2.4)生成SSL证书 如果想使用 SSL 证书来确保服务的安全,但不需要 CA 签名的证书,一个有效的(和免费的)解决方案是签署你自己的证书,即:自签证书(self-signed certificate)。自签证书是用自己的私钥签署的证书。自签证书和 CA 签名证书一样可以用来加密数据,但是你的用户会显示一个警告,说这个证书不被他们的计算机https://blog.csdn.net/liuxiao723846/article/details/127623841
19.BURP商店插件官方目录及功能介绍(翻译)Blazer实施了一种新的测试方法,该方法已在2012年美国黑帽大会上推出。这种自动化的灰箱测试技术使安全研究人员能够提高针对复杂应用程序的覆盖范围和进行模糊测试的效率。 功能包括: 通过Java反射和“最佳匹配”启发式方法从方法签名自动生成Java对象 具有自定义数据池和攻击向量的模糊测试功能 https://www.t00ls.com/articles-58902.html
20.UnionPay中国银联在线支付开发文档商户根据在线支付系统提供的接口规则,通过程序生成得到签名结果及报文信息传给在线支付的数据集合。 (2)发送请求数据 把构造完成的数据集合,通过页面表单提交(POST)的方式传递给在线支付系统。 (3)在线支付系统对请求数据进行处理 在线支付系统得到这些集合后,会先进行安全校验等验证,一系列验证通过后便会处理这次发送过https://m.360docs.net/doc/892582580066f5335b812171.html
21.生成签名软件有哪些APP推荐生成签名软件有哪些下载豌豆荚生成签名软件有哪些榜单为您提供最新生成签名软件有哪些大全,这里不仅有生成签名软件有哪些安卓版本APP、历史版本应用下载资源,还有类似生成签名软件有哪些的应用推荐,欢迎大家前来豌豆荚下载。https://www.wandoujia.com/bangdan/399442/
22.九大名字设计网站签名设计网站排名艺术签名设计网哪个好用3、中华签名网www.qianming.cn 杭州贤书阁文化创意有限公司旗下的名字设计网站,主要为广大用户提供在线付费和免费签名设计自动生成服务,该签名设计系统是由书法家叶根友先生亲自研发设计。免费签名可选风格有个性签、少女签、卡通签、行草签、刀锋体等。收费签名最低2元,支持公务签、尚乐体、立体字、英文。定制化签http://www.zhuoyunkang.com/news/show-34658.html
23.吾爱签名xv1.0免费版最需网爱签名是一款绿色免费的签名设计软件,只要你输入你的姓名,软件立即生成你的手工签名,完全区别于电脑字库生成的签名,让你3秒钟轻松获得漂亮的签名。 功能特色 输入姓名自动生成手工效果签名。可以一次性生成4款签名,包括公文签、公文签反签、英文签1、英文签2。 https://www.zuixu.com/down/589063.html
24.协同办公系统常见问题解答(精选11篇)答:请检查是否按要求装载控件(控件会自动弹出,如没有弹出,请更换浏览器重试);电脑所安装的office是否为完全版(可卸载本机office后到协同办公论坛内下载office2003安装包安装)?是否同时安装有wps(请卸载wps)? 4、盖章时出现“没有找到可用于签名的证书” https://www.360wenmi.com/f/file64wfndgf.html
25.UIAutomation安装教程ui安装包└── Sign 签名脚本 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 1.安装包界面必要的UI修改 不管采用哪种方式打包,必要的UI修改都是要做的,比如图标以及个别界面上的提示信息;我们的UI模板已经尽可能做到简洁与美观,相信您只需要替换部分图标后,完全可以直接作为您产品的安装包界面。 https://blog.51cto.com/u_16213618/11643435
26.网站名称logo设计(电子签名在线生成)网站名称logo设计(电子签名在线生成) 大家好!今天让创意岭的小编来大家介绍下关于网站名称logo设计的问题,以下是小编对此问题的归纳整理,让我们一起来看看吧。 创意岭作为行业内优秀的企业,服务客户遍布全球各地,相关业务请拨打电话:175-8598-2043,或添加微信:1454722008https://www.de1919.com/article/18924.html
27.在AGC平台生成新的profile签名文件(.p7b),更新到HarmonyOS工程如何在App启动时让各种权限弹窗的申请自动弹出 module.json5文件中的requestPermissions配置如何填写 如果有多个UIAbility,如何判断应用进入后台 发布签名发生变更后,用户是否需要先卸载原来的应用才能安装签名变更的应用 在AGC平台生成新的profile签名文件(.p7b),更新到HarmonyOS工程重新打包安装时提示:”code:9568322 https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs-V5/faqs-ability-96-V5
28.商务网站建设方案(精选12篇)一般企业型网站应包括:公司简介、企业动态、产品介绍、客户服务、联系方式、在线留言等基本内容。更多内容如:常见问题、营销网络、招贤纳士、在线论坛、英文版5、无需后台操作,真正的同步静态页面生成,拥有高效的浏览机制和响应速度。 企业资料库系统 切实考虑多行业企业的实际需求,能够随需应变。 https://www.ruiwen.com/jianshefangan/5430104.html
29.个性网名设计制作107个(个性网名自动生成器)19、云朵朵在线自动取艺名。定制网名输入自己名字:定制网名输自己名字的情侣网名(带对方名字)。定制网名输入自己名字:如何用自己的姓名制作微信昵称姓名微信昵称一键生成cp名。 20、溫暖如初 二、个性网名设计制作 1、烟花沼泽 2、一个高冷的智障 3、吃货姑娘可爱 http://www.awcms.net/shuoshuo/459868.html