通过测试工具模拟人为操控浏览器,使软件按照测试人员的预定计划自动执行测试的一种方式,可以完成许多手工测试无法完成或者不易实现的繁琐工作。
正确使用自动化测试,可以更全面的对软件进行测试,从而提高软件质量进而缩短迭代周期。
日常测试活动中,都会根据功能模块进行拆分,所以在设计器中我们可以通过创建流程包的方式来拆分需要测试的功能模块,如下图中操作创建一个电脑流程包并且取名为对应的功能模块名称,如果有多个功能模块就创建多个对应的流程包,实在RPA设计器有易用的图形可视化界面,方便管理较多的功能模块。

实在RPA设计器提供了流程块的功能,可以根据需要测试的功能模块,进入对应的流程包中,创建流程块并且将流程块命名为测试用例的名称,需要创建多个测试用例时可以从左侧的流程模块中将流程块拖入到画布中并且连上线,一个流程块就是一条测试用例;流程块即测试用例的执行顺序是按照连线从“开始”流程块开始执行,直到连线的最后一个流程块运行结束

元素定位就是通过元素的信息或者元素的层级结构来进行定位,传统的自动化流程编写一个点击元素的场景,需要调用代码方法然后通过id、name,css,xpath等方法来定位到元素,再调用点击的方法实现。
实在RPA设计器中元素定位只需要拖入 “点击界面元素”的组件,然后点击元素拾取的按钮,拾取目标元素,保存后运行组件即可实现一个点击功能,使用方法相当的简洁,让使用者可以极快的入门,操作如下:

PageObject是编写UI测试时的一种设计模式,软件教父马丁·福勒提出的设计理念。
将页面上的元素定位操作流程写到一个方法上,对于调用的人来说,一个PageObject代表了一个页面,或者页面上的一个区域,比如搜索框,侧边栏,页面流程等也可以是一个独立的方法。
这样做的好处是封装了页面流程的操作方法 ,使用时只需调用这个方法即可,就算前端页面变动后也可以直接找到这个方法修改元素定位,代码看起来更简洁修改起来也很方便。
1)创建没有输入参数和返回的自建组件(这里的组件应用就好比po中提到的方法):首先进入设计器中我的组件页面点击新增按钮创建组件,然后在自建组件区域拖入页面操作相关的组件即可,详情操作见视频
创建没有输入参数和返回的自建组件
2)创建带有输入参数和返回参数的自建组件:如下视频中操作打开百度页面搜索二十大,然后在跳转的页面获取一个元素文本,我们可以把这个操作中的搜索的内容用输入的形参,把搜索结果页面获取的元素文本放到设定好的输出参数中,这样我们在用例流程中调用这个组件时就可以自己输入参数,并且获取到元素返回值,视频如下:
创建带有输入参数和返回参数的自建组件
3)创建的自建组件返回参数:设计器的自建组功能设定返回参数只有一个,所以如果流程中需要返回多个参数值时可以把参数放到一个列表中然后返回出来,用例流程中调用这个自建组件的时候,以列表取值的方式取出返回值列表中的参数用来断言或进行其他操作

4)如何在流程中使用自建组件:
创建好的自建组件首先需要发布,可以选择发布到本地,然后进入测试用例流程中左侧栏点击“组件扩展中心” - “自建组件” - “我的组件” 安装自己发布好的组件,安装成功后就可以在左侧栏的“扩展组件” 中选中自定义的组件然后拖入画布中使用,详情操作见图

什么是参数化?参数化就是把测试所需要的参数写在数据集里,让程序自动去取值,每个参数对应一个测试用例;测试用例之所以要进行参数化处理,是因为可以提供不同的数据值以提高执行脚本的能力,从而更加真实的模拟生产环境的数据,并且这样写脚本看起来也更简洁,方便管理测试参数;实在设计器提供储存数据和读取数据的组件有很多种,这里我们选择了表格的方式管理参数结合自建组件实现测试用例的执行可参数化:
1)首先创建一个封装测试用例的自建组件,组件主要实现功能是接收input参数传递的值判断值是不是等于a,如果不等为False反之为True,结果都赋值给output变量作为自建组件的返回,如图: 
2)假设此自建组件的运行内容就是我们需要执行的测试用例流程,测试流程中可以把要测试的参数放到表格中,使用打开表格和读取表格数据的组件来读取测试参数,将读取到的测试参数列表赋值给变量test_param,再利用for循环遍历列表test_param中的元素作为参数传入封装测试流程的组件中。这样,就可以把多个参数依次传入测试流程中运行了从而实现参数化测试,接着使用组件创建一个列表result_list,并且把自定义的测试组件返回值添加到result_list中(如果列表值顺序不对可以插入代码调整),就会得到一个测试结果的实际值列表可以用来和期望值对比做断言处理,具体实现如下图处理。

setup主要是进行测试前初始化工作,比如在接口测试前做一些前置的参数赋值、数据库相关的操作,总之所有在测试用例运行前可执行的动作都可以放在setup中;
teardown是测试后的清除工作,比如参数还原或销毁,数据库的还原恢复等后置执行的动作;
一种是写自建组件的方式,写好自建组件然后在用例流程块中的代码最前面和最后面分别加上对应功能的自建组件,这样用例流程块执行时自建组件就可以起到setUp和tearDown的相似作用,但是这种方法的只能作用到当前的用例流程块;
第二种是在整个功能模块流程包中创建,用前后两个流程块来代替setup和teardown的操作,如果测试用例流程块中有参数依赖setup和teardown的流程块时,可以使用设置全局变量的方式将有依赖的参数赋值到全局变量中,这样就可以跨流程块引用;
针对第二种方式我们举个例子,主要实现功能为setup流程块执行创建测试参数,然后测试用例流程块需要引用这个参数并完成测试,最后teardown流程块清除数据的操作,设置方法如下:
首先创建三个流程块分别命名为“setup”,“testcase”,“teardown” 然后创建全局参数testCase1和testCase2来给各个流程块之间依赖参数赋值,运行时 “setup” 流程块先运行并且运行成功后赋值变量1给全局变量testCase1,运行 “测试用例” 流程块时引用参数testCase1判断通过后,给全局变量testCase2赋值 “测试通过” 的值,最后运行teardown流程块时获取全局变量testCase2并判断是否符合预期,如果符合预期就执行数据清除的操作,至此流程运行结束。
Step1:设置全局变量

Step2:setup流程块

Step3:测试用例流程块

Step4:teardown流程块

Step5:运行结果

流程块中的组件代码并不是总能够平稳运行,例如测试参数错误,元素定位异常,网络连接断开,数据库连接失败等其他因素,这种情况称为异常情况。
测试用例在运行过程中,如果用例流程块因为异常而停止运行的话,就会导致整个流程包中当前运行流程块的下级流程块也停止运行,最后影响其他的测试用例流程块导致无法执行完成。
异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常,让程序尽最大可能恢复正常并继续执行,且保持代码的清晰。
1)一种是在用例流程块或者自建组件中,针对组件运行异常可以使用设计器提供的 “异常捕获(try catch)” 组件 。这里展示一个实例,主要实现的功能是给一个点击元素的组件做异常处理,如果出现异常时就打印出错的提示。
首先,拖入“异常捕获” 的组件到编辑区域,然后将元素点击的组件放到“异常捕获” 组件中尝试运行的区域,最后把捕获到异常时需要输出的信息放到 “异常捕获” 组件的抛出错误区域,运行流程块时如果 “点击界面元素” 组件运行失败,异常捕获组件就会获取到组件运行失败的状态从而输出异常捕获组件“抛出错误” 区域中的内容。

但是上面的这个抛出错误的方法肯比较片面而且是自己定义输出的,可能不具备太大的实际参考价值,如果想要拿到具体的更详细的报错内容,这里我们需要用到一个“异常处理”自建组件包(此章节末端提供);
从设计器左侧菜单栏-扩展组件-本地导入中导入异常处理的组件包,组件包中有四个组件本次主要用到 “获取元素名称” 和 “抛出异常” 这两个;
首先在 “异常捕获”组件的如果发现执行错误区域中拖入 “插入代码” 组件并在组件中输入代码 import traceback,这个组件主要用来插入python代码;

再拖入“获取异常元素名称” 放在 “插入代码”组件的下方,输入元素库字典SHIZAI_ELEMENT_DICT,输入获取详细错误信息代码traceback.format_exc(limit=3),这个组件的功能是把traceback.format_exc(limit=3)返回的错误信息里面取出报错的元素名称然后赋值给ele_name。

最后拖入 “抛出异常” 组件,这个组件的功能是抛出异常信息,可以结合上面的两个组件使用,我们在组件参数 “异常元素” 中输入异常组件的元素变量ele_name,在另一个组件参数 “异常明细” 中输入抓取异常信息的python代码traceback.format_exc(limit=3)这样可以打印出全部的报错信息:

将三个组件结合在一起使用,这样就可以抓取到报错组件的具体信息,报错信息也可以收集起来。下图就是定位百度输入框元素失败后,抛出的错误信息:

——>>异常处理自建组件,可以通过导入本地包的方式导入自建组件

2)另外一种需要异常处理的情况,主要使用场景是流程包运行时,因为本文中管理测试功能模块和测试用例是按流程包、流程块来划分的,为了让功能模块中的测试用例独立运行,我们需要增加判断,设置一个全局变量 “流程块异常继续执行” 值为1,在流程块中添加流程走向判断,判断全局变量 “流程块异常继续执行” 的值是否为1,是的话流程块就可继续执行,就算有流程块运行错误了,也不会影响到其他的流程块,如下图:


运行测试用例时,判断用例是否执行成功,此时需要有一个期望结果来进行验证。如果case执行的过程中报错,或者我们判断结果不符合期望,就会认为用例执行失败,这个判断依据主要是根据断言来实现; 所以断言的方法就是通过比对期望值与实际值是否一致。 在设计器中我们可以把判断逻辑写好然后封装到自建组件中,这个组件就是用来断言的方法,然后再测试流程块中可以通过调用自建组件的方式引用这个断言,举例如下。
1)普通的对比断言方式,创建自建组件命名assert设置输入参数expect_param和actual_param,输出参数test_result,判断expect_param和actual_param是否一致,是的话返回True反之返回False,使用的时候只需要传入期望值和实际值给断言组件就可得到测试结果
Step1:组件内容

Step2:流程块中调用组件

2)、在对比断言自建组件中加入 “数据服务” 组件和 “异常处理”组件 的方式并且收集测试结果,“异常处理” 组件前文已经介绍过了,这里主要叙述下 “数据服务”组件的使用;“数据服务” 组件是设计器提供的组件,主要实现的功能是往当前登录设计器的账号所拥有的数据表中上传数据,但是账号下的数据表是由哪里来的?
这里要介绍下我们的另一个产品“松塔数据平台”。松塔数据平台,是实在智能打造的一款为政企提供数据全链路闭环应用的数据智能化产品。可一站式完成数据集成、数据存储、数据开发、数据应用,真正实现“采、存、管、用”一体化, 帮助企业实现数据价值释放,驱动业务增长和成本优化。我们这里用到了松塔的 “存” 功能,首先把当前登录的rpa账号在松塔开通授权,然后在松塔菜单 “数据采集” 中创建一个RPA采集表test_report,添加一些测试报告中需要用到的字段,case_name(测试用例名称),test_result(测试用例执行结果)case_failure_reason(用例失败原因),success_num(用例执行成功时输入1主要用来测试报告中做统计),failure_num(用例执行失败时输入1主要用来测试报告中做统计),如下图;
Step1:创建任务表

Step2:定义字段收集自己测试报告中所需要的信息

数据表创建成功后就可以在设计器的“数据服务”组件中查到test_report表,如图

那么如何在断言组件中使用数据服务组件保存测试数据,这里需要分两种场景:
第一种,测试用例执行流程无异常时使用的,首先创建自建组件,设置自建组件属性变量 case_name(对应test_report表中的case_name),test_expect(接收测试期望值),test_actual(接收测试实际值),通过设计器的 “设置变量” 组件,
创建变量 “测试用例执行结果成功” 赋值 “True”;
创建变量 “用例执行成功往success_num写1” 赋值 “1” ;
创建变量 “测试用例执行结果失败” 赋值 “False”;
创建变量 “用例执行成功往failure_num写1” 赋值 “1”;
创建好变量后在组件中判断expect_param和actual_param是否一致,是的话就通过 “数据服务” 组件往数据表test_report中传 “测试用例执行结果成功” 、case_name、 “用例执行成功往success_num写1”这三个变量值

expect_param和actual_param不一致的话就通过 “数据服务” 组件往数据表test_report中传 “测试用例执行结果失败” 、case_name、 “用例执行成功往failure_num写1” 这三个变量值

断言的自建组件的判断展示如下
第二种,测试用例执行流程有异常时使用的,首先创建异常时断言自建组件,设置自建组件属性变 量case_name(对应test_report表中的case_name),test_expect(接收测试期望值),test_actual(接收测试实际值),failure_reason(流程执行失败抓取的错误信息数据),通过设计器的 “设置变量” 组件:
创建变量 “测试用例执行结果失败” 赋值 “False”;
创建变量 “用例执行成功往failure_num写1” 赋值 “1”;
通过数据服务组件向数据表test_report中传入“测试用例执行结果失败” 、case_name、 “用例执行成功往failure_num写1” “failure_reason”这四个变量值如下:

断言的自建组件内容展示如下:

3)实际流程中调用示例,本次示例实现的功能是打开百度搜索输入内容 “二十大” 后获取页面的文本内容做实际值,然后和期望期值通过assert断言组件进行断言处理并保存测试结果数据,代码如下:

第一个断言成功的测试场景,如果期望值和实际相同时通过断言组件断言并保存测试结果 数据如下,

第二个断言失败的测试场景,如果期望值和实际相同时通过断言组件断言并保存测试结果数 据如下,

第三个断言失败的测试场景,如果测试流程块出现异常报错比如元素定位失败,通过断言组 件断言并保存测试结果数据如下,详细的流程报错信息保存信在case_failure_reason字段中

为了结合实际测试场景测试用例运行方法有很多方式大致分为单个用例运行和指定用例批量运行,单个运行时主要可以用来测试单个场景以及调试用例时使用,指定用例批量运行使用场景主要用来做功能模块的回归验证比如修改了某个功能模块的bug然后需要回归下整个功能模块这时就可以派上用场了;
在实在RPA设计器中运行单个测试用例时,按照本文的用例划分一个流程块即一个测试用例所以想要运行流程那个用例时只需要进入流程块点击运行按钮。
批量运行用例时我们可以直接找到对应功能模块的流程包运行,这样就可以实现批量运行的效果,只需简单的操作即可实现想要的功能;
Step1:按单个用例运行流程块

Step2:按功能模块批量运行流程包

很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("