回归测试旨在确保软件更改不会在软件中引入新的问题或故障。 而且,它确保您不会重新引入以前修复的错误。 如果该软件对第三方组件和库有很多依赖关系(例如XML处理API或JPA这样的数据库抽象API),则引入新问题尤其常见。 在这些情况下,数据库架构中的细微更改可能会导致应用程序中的行为更改难以预测。 如果软件本质上很复杂,则对通用代码段进行的微小更改可能会导致无法预料的副作用。
需要持续支持特定中间件软件的先前版本或不同平台的方案会增加在维护或开发过程中引入问题的可能性。 在一个版本的数据库中间件中运行的修补程序或功能在另一个版本中可能会带来灾难性的后果。 另外,添加功能时,仅适用于较新版本的中间件的API可能会破坏使用较早版本的客户端。 当您支持不同的平台时,请彻底测试依赖于命令行界面或脚本的功能。 否则,在不同的操作系统(例如Windows®和Linux®)中可能会出现不同的行为。
回归测试针对整个软件,并考虑其与其他组件或应用程序的相互依赖性。 在开发过程中,重点关注正在开发的特定模块或功能。 您可以在实现模块或功能时逐步对其进行测试,有时还可以使用存根引用尚未实现的其他功能。 如果增量测试具有足够的结构和独立性,可以在特定环境(例如所需的中间件软件,计算机或配置)下重复进行,则可以在以后的回归测试中重复使用它们。 这种结构及其独立性减少了返工并提高了测试质量,因为对每段代码都进行了开发时所使用的相同检查。
在一组体系结构,操作系统和中间件版本上测试正在开发的功能时,请考虑自动增量测试。 例如,想象一下Linux,AIX®,Windows 7和Windows XP支持的命令行界面。 在开发过程中,在每个操作系统中执行测试可能会占用大量资源和时间。 在某些情况下,测试新功能所需的时间可以克服开发新功能所需的时间。 考虑到许多功能是由不同的开发人员在项目中同时开发的,因此这种情况变得更加困难。 更为复杂的是,通常只有有限数量的机器(即使是虚拟机器)才能进行测试。 通常,测试需要预先配置的环境,包括数据库服务器,应用程序服务器等。 专用于测试的机器越多,更新和配置每台机器所花费的时间就越多。 通过工具在一组环境或测试平台中运行的自动增量测试,您可以节省在每个环境上手动运行测试所需的时间,并可以更好地共享资源。
自动回归测试可以使用与增量测试相同的测试平台。 例如,通过将回归测试设置为每天运行一次,您不会消耗原本可能用于开发或增量测试的资源。 您可以将冗长的回归测试设置为以更长的时间间隔运行,例如在周末运行。
软件测试自动化框架(STAF)是一个开放源代码框架,其中包含一组内置服务,这些内置服务特别适合于构建自动化解决方案。 服务是可重用的组件,可提供STAF中的所有功能。 每个STAF服务都提供一组特定的功能,例如:
诸如电子邮件服务,FTP服务和计时器服务之类的其他服务不是内置的,但很容易插入到框架中。
STAX服务是在Java™环境或执行引擎中实现的特殊服务,它允许通过XML调用其他STAF服务。 它还带来了对以下方面的支持:
STAX定义的XML元素的工作方式类似于编程语言,其中包含该语言的所有基本元素:
元素脚本可用于嵌入Python脚本,从而允许更复杂的逻辑并访问预定义的Python模块。
Python代码由Jython运行。 Jython采用Python编程语言语法,并使其能够在Java平台上运行。 这允许与Java库和其他Java应用程序集成使用,从而提高了Java开发人员团队的工作效率。
STAX的一项有趣功能是它允许导入包含辅助功能的现有STAX文件。 此功能改善了自动化代码的组织和代码的重用。
STAF作为守护程序运行,侦听来自预配置端口的请求。 通过这些请求访问STAF服务,这些请求是必需命令的说明。 Stafcmd是STAX定义的元素,可用于表示请求。 如清单1所示,请求包含:
<stafcmd> <location>'lab01.mydomain.com'</location> <service>'FS'</service> <request>'CREATE DIRECTORY /tmp/CVT_TEMP' </request> </stafcmd>
清单1中的代码请求在机器lab01.mydomain.com上创建目录/ tmp / CVT_TEMP。 定义此命令的服务是“ FS”(文件系统服务)。 如果必须运行命令的位置不是“本地”,则请求命令的STAF实例会将请求发送到指定位置。 这种通信对呼叫者而言并不明显。 在本地计算机上创建目录的请求具有相同的语法。 唯一的区别是您将位置指定为“本地”。 然后,STAF知道该命令必须在本地运行,而不是在其他计算机上运行。
自动化执行测试所需的步骤取决于您测试的软件。 大多数自动化解决方案的主要步骤是:
您可以使用STAF / STAX执行所有这些步骤,如以下示例所示。
组织测试平台的一种方法是为每个环境创建一个属性文件,在该文件中放置对测试用例有意义的所有属性,例如:
每个属性文件代表一台特定计算机上的测试环境。 一台机器可以有多个环境。 例如,一个环境可能定义一个DB2数据库安装和一个WebSphere v8.5服务器。 同一台机器上的另一个环境包含带有WebSphere v7.0服务器的Oracle安装的属性。 每个属性文件代表一台特定计算机上的测试环境。
在准备阶段,开发人员必须遍历一系列环境,并启动一组命令以准备在定义了每种环境的远程计算机中执行测试。 清单2显示了环境的基本循环:
<script> env_list = ['LinuxDB2Websphere8','WindowsDB2Webshere85'] </script> <paralleliterate var="env_name" in="env_list"> <sequence> <message log="STAXMessageLog"> 'Preparing to launch tests on %s' % env_name </message> <tcstatus result="'info'"> 'Reading environment information from %s' % env_name </tcstatus> <script> file_path = "%s/CVT/config/%s.properties" % (temp_dir, env_name) </script> <call function="'read_properties'"> {'properties_file' : file_path} </call> <script> props_dict = STAXResult try: mach_name = props_dict.get('STAF_MACHINE') except: raise Exception('Property STAF_MACHINE not found in Env %s' % env_name) </script> … prepare remote environment for tests </sequence> </paralleliterate>
执行测试的准备工作涉及创建一个或多个目录,在其中放置了两个STAX脚本,以及必要的库或产品映像。 一种建议的结构是:
<TEMP_DIR>/CVT_TEMP/PRODUCT
→用于放置库和所需图像的目录。 <TEMP_DIR>/CVT_TEMP/CVT
→辅助STAX脚本和其他测试所需的资源。 要检索系统临时目录的位置,必须解析具有该值的STAF变量,如清单3所示 。
<stafcmd> <location>mach_name</location> <service>'VAR'</service> <request>'RESOLVE STRING {STAF/Env/TEMP}'</request> </stafcmd> <script> temp_dir = STAFResult product_dir = 'CVT_TEMP/PRODUCT/%s' % temp_dir </script>
该目录是使用文件系统服务(FS)创建的,如清单4所示 。
<stafcmd> <location>mach_name</location> <service>'FS'</service> <request>'CREATE DIRECTORY %s FULLPATH' % (product_dir)</request> </stafcmd>
准备远程环境时,请复制压缩的映像和必备组件,然后将它们提取到目标目录中。 要复制文件,请使用清单5中的COPY请求:
<stafcmd> <location>'LOCAL'</location> <service>'FS'</service> <request>'COPY FILE %s/%s TODIRECTORY %s TOMACHINE %s' % \ (local_directory, zip_file, remote_temp_dir, mach_name)</request> </stafcmd>
要解压缩图像,请使用清单6中的ZIP服务:
<stafcmd name="'Unzip %s on %s' % (zip_file, mach_name)"> <location>mach_name</location> <service>'ZIP'</service> <request>'UNZIP ZIPFILE %s/%s TODIRECTORY %s REPLACE' % \ (source_directory, zip_file, target_directory)</request> </stafcmd>
流程元素表示在指定计算机上运行的STAF流程。 它可用于启动脚本或可执行代码并等待其完成。 在其他选项中,您可以指定:
参见清单7 。
<script> ... cmd = 'C:/PROGRA~1/IBM/WebSphere85/profiles/Dmgr01/bin/startManager.bat' parms = '-username %s -password %s' % (user, passwd) </script> <process name="'cmd %s %s' % (cmd, parms)"> <location>mach_name</location> <command mode="'shell'">cmd</command> <parms>parms</parms> <workdir>work_dir</workdir> <envs>envs</envs> <console use="console" /> <stdout>stdoutFile</stdout> <stderr>stderrFile</stderr> <returnstdout /> <returnstderr /> </process>
流程元素提供了运行脚本或可执行代码的基本工具。 在测试执行过程中运行数十个不同的脚本时,建议创建一个辅助STAX函数来包装调用,记录运行的命令及其参数并检查退出代码。
process元素还可用于启动创建数据库的脚本。 清单8中的代码创建一个DB2数据库:
<script> script_name = 'db2Setup.bat' db_script_dir = 'C:/CVT_TEMP/PRODUCT/bin' cmd_str = 'db2cmd -w -i -c %s %s -d %s -u %s -p %s' % \ (script_name, migrate, db_name, db_user, db_pswd) </script> <process name="'cmd %s %s' % (cmd, parms)"> <location>mach_name</location> <command mode="mode">cmd</command> <workdir>db_script_dir</workdir> <console use="console" /> <returnstdout /> <returnstderr /> </process>
安装过程通常涉及以非交互方式调用脚本或可执行代码。 该过程类似于您调用设置数据库的脚本的方式,如清单8所示 。
尽管STAF / STAX对于设置测试环境很有用,但是当您测试同一场景的变体时,测试代码(STAX和python脚本)变得复杂或重复。 这种复杂性使维护变得困难,特别是如果不是所有的测试人员和开发人员都具有深厚的编程技能。 尽管STAF / STAX提供了坚实的基础框架,但是您可以重用以前用其他语言编写的测试,并合并报告工具,而不是要求测试人员扫描有时不直观的STAX日志。 对于Java语言,JUnit是最常用的测试框架。 JUnit与大多数开发软件集成在一起,并允许使用有趣的相关框架,从而提高了编写测试代码的效率。 例如,您可以使用DDTUnit将测试逻辑与测试数据分开。 ANT生成的JUnit报告对于组织报告和发现测试用例中的故障也很有用。
尽管您可以将JUnit作为简单的Java类直接启动,但是使用ANT调用它会更容易。 JUnit ANT任务封装对JUnit的调用,设置类路径,并以XML文件格式记录测试的执行。 然后,另一个名为junitreport的任务可以使用此XML文件来生成HTML格式的报告。
样本文件JUnitUtil.xml中定义的功能run_junit_ant可用于为一组测试用例或套件调用JUnit。 它创建一个包含类路径定义junit.tmp.classpath的临时ANT项目,该项目包含参数lib_dirs和libs中指定的所有JAR文件。 之后,它会参考类路径启动在示例文件JUnitRunner.xml中定义的目标junit.run。 (要获取JUnitRunner.xml和JUnitUtil.xml示例文件,请参见下载 。)目标启动任务junit,如清单9所示 :
<project name="cvt.junit.runner" default="junit.run" basedir="."> <import file="${junit.tmp.classpath.import}" /> <target name="junit.run" description="Runs the unit test cases."> <echo message="Generating JUnit output at ${output.dir}"/> <junit dir="${work.dir}" fork="yes" forkmode="once" printsummary="on" haltonfailure="no" haltonerror="no" showoutput="true" failureproperty="ut.failed"> <jvmarg value="-Djava.util.logging.config.file=${java.util.logging.config.file}"/> <sysproperty key="net.sourceforge.cobertura.datafile" file="{net.sourceforge.cobertura.datafile}" /> <classpath refid="junit.tmp.classpath" /> <test name="${cvt.test.class}" haltonfailure="no" outfile="TEST-${cvt.test.class}" todir="${output.dir}"> <formatter type="xml"/> </test> </junit> <fail if="ut.failed" message="Some of the tests failed. Check the JUnit report for details." /> </target> </project>
属性net.sourceforge.cobertura.datafile可用于生成覆盖率信息(有关更多信息,请参见Cobertura项目)。 您可以从函数run_junit_ant在参数jvm_args中提供此属性值。
同样,压缩文件的传输比单个文件的传输效率更高。 要压缩远程计算机中的目录,请使用ZIP请求。 在清单10中 ,压缩文件mach_name中压缩了ZIP文件'C:/CVT_TEMP/testcase_123_results.zip'中的目录'C:/ CVT_TEMP / CVT / logs'。
<script> zip_file = 'C:/CVT_TEMP/testcase_123_results.zip' results_dir = 'C:/CVT_TEMP/CVT/logs' </script> <stafcmd name="'Compressing results'"> <location>mach_name</location> <service>'ZIP'</service> <request>'ADD ZIPFILE %s DIRECTORY %s RECURSE RELATIVETO %s' % \ (zip_file, results_dir, results_dir)</request> </stafcmd>
压缩后,可以使用清单11中的 COPY FILE请求检索结果:
<script> local_results_dir = 'C:/CVT_TEMP/results' </script> <stafcmd> <location>mach_name</location> <service>'FS'</service> <request>'COPY FILE %s TODIRECTORY %s' % (zip_file, local_results_dir)</request> </stafcmd>
在跨不同网络的计算机上运行测试时,可能会出现防火墙问题。 一种更安全的方法是使用GET BINARY请求从调用中获取二进制形式的整个文件。 优点是不需要远程计算机解析和访问本地计算机。 缺点是,在传输之前,如果不将大文件分成较小的部分,可能无法检索它们。
删除目录的请求很简单。 指定要删除的目录以及该目录所在的机器,如清单12所示 :
<stafcmd name="'Delete remote directory'"> <location>mach_name</location> <service>'FS'</service> <request>'DELETE ENTRY %s RECURSE CONFIRM' % \ (file, ignore_param)</request> </stafcmd>
要删除数据库,停止服务器或执行其他操作,请使用清单12中说明的process元素。
为了生成JUnit报告,请采用与运行JUnit测试用例相同的方法:创建一个辅助ANT项目,以启动创建JUnit报告的任务,如清单13所示 :
<project name="cvt.junit.report" basedir="."> <target name="junit.report"> <echo message="Generating JUnit Report at ${junit.report.todir}"/> <echo message="Reading results from ${junit.report.dir}"/> <mkdir dir="${junit.report.todir}" /> <junitreport todir="${junit.report.todir}"> <fileset dir="${junit.report.dir}"> <include name="TEST-*.xml" /> </fileset> <report todir="${junit.report.todir}" /> </junitreport> <echo message="JUnit Report Generated"/> </target> </project>
要启动脚本,请通过process元素对其进行调用:
<script> from java.io import File f = File(STAXJobXMLFile) ant_script = File(f.getParentFile(),'utilities/JUnitReport.xml').getAbsolutePath() ant_script = ant_script.replace('\\','/') java_envs = '' java_envs = '%s -Djunit.report.todir=%s' % (java_envs, output_dir) java_envs = '%s -Djunit.report.dir=%s' % (java_envs, work_dir) parms = '%s -f %s junit.report' % (java_envs, ant_script) </script> <process name="'cmd %s %s' % (ant_cmd, parms)"> <location>mach_name</location> <command mode="'shell'">ant_cmd</command> <parms>parms</parms> <workdir>work_dir</workdir> <console use="console" /> <stdout>stdout</stdout> <stderr>stderr</stderr> <returnstdout /> <returnstderr /> </process>
运行所有对验证测试结果有用的报告后,将它们压缩为一个或多个文件。 如果将结果存储在Web服务器上,则访问结果可能会更容易,以便开发人员和测试人员可以立即访问它们。 请参见清单15中的示例。
<stafcmd> <location>'local'</location> <service>'FTP'</service> <request>'PUT HOST %s URLPATH %s FILE %s USER %s PASSWORD %s' % \ (CVT_FTP_SERVER, remotePath, localPath, ftp_user, ftp_passwd) </request> </stafcmd>
您可以使用EMAIL服务将有关增量或回归测试的通知发送给开发人员或测试人员。 staf.cfg(bin目录中的STAF配置文件)中的服务配置很简单。 它只需要一个电子邮件服务器和包含服务实现的JAR文件的路径。 您可以从STAF下载页面下载文件,如下所示:
SERVICE email LIBRARY JSTAF EXECUTE c:/staf/services/email/STAFEmail.jar \ PARMS "MAILSERVER na.relay.ibm.com"
清单16显示了发送电子邮件请求的结构:
<stafcmd name="'send_email'"> <location>'local'</location> <service>'EMAIL'</service> <request>email_cmd</request> </stafcmd>
其中email_cmd的格式(来自电子邮件服务用户指南)如清单17所示 :
SEND < TO <Address> | CC <Address> | BCC <Address> >... [FROM <[email protected]>] [CONTENTTYPE <contenttype>] < MESSAGE <Message> | FILE <File> [MACHINE Machine] > [SUBJECT <subject>] [NOHEADER] [TEXTATTACHMENT <file>]... [BINARYATTACHMENT <file>]... [ATTACHMENTMACHINE <machine>] [RESOLVEMESSAGE | NORESOLVEMESSAGE] [AUTHUSER <User> AUTHPASSWORD <Password>]
从开发人员的角度来看,持续集成包括将新代码和更改频繁集成到代码存储库中,并不断验证更改不会破坏现有代码。
验证通常由自动构建系统执行,该系统可以检测何时发生更改或在计划的时间运行构建。 该版本会验证可能的代码中断,并最好运行一组单元测试以验证基本功能是否得到维护。 构建可能经常发生或需要很长时间才能运行。 通常,您不希望在持续集成系统中包括组件测试,因为它无法运行每个构建。
连续运行组件测试的一种可能解决方案是单独的系统。 系统根据当前代码库运行自动化测试,或根据要求运行特定测试。 考虑通过STAX运行一个循环:
每天执行一次回归测试,包括所有测试。 只要必须测试代码更改(例如修订或新功能),就可以运行增量测试。 例如,要测试现有命令行界面的新参数,请运行特定于此命令行界面的增量测试。 运行增量测试可以提高团队的生产率,因为它们可以在等待夜间回归之前更快地识别故障。
要验证图像(包含要测试的软件或测试资源的捆绑软件)是否已更新,请检索文件修改时间,并将其与本地文件中存储的先前修改时间进行比较。 用于获取FTP服务器中文件修改时间的Python命令为:
ftp.cwd(ftp_url_path) ftpMDTM = ftp.sendcmd('MDTM %s' % file) #Example of result: '213 20101129060511'
如果文件自上次验证以来已被修改,则可以使用STAX FTP服务或Python FTP模块下载文件。 验证是否是运行回归的时间可以与将当前时间与计划表进行比较一样简单。 如果当前时间早于计划时间,请运行回归。
一个更复杂的功能是运行增量测试的能力。 增量测试是在一组选定的环境中运行列表或一组预定义的测试用例的请求。 一种可能的实现方式是定期验证新请求是否在与Web服务器共享的文件中。 您可以使用本地Web服务器提供HTML页面将请求包含在此文件中,其中包含以下信息:
在下面的示例中,代码显示在多行上以满足格式限制。 通常,它是一行连接代码。
t||testcase_nop||FRS-1.0.0||LinuxDB2Websphere85,ZLinuxDB2Websphere8||false||true| |4EF60DC3B825707D6BAE349047B4E664||[email protected]||ready||20121023220123||default
图1显示了用于请求增量测试的页面示例。
使用像Apache Tomcat这样的Web服务器作为接口并与运行连续集成的STAF / STAX脚本一起使用,可以扩展最终用户的选项数量,例如:
图2显示了主页的实现,其中包含指向系统中主要功能的链接。 Web服务器对于显示集成系统的状态也很有用,例如:
图3显示了一个页面,用户可以在其中访问按环境名称组织的先前执行的结果。 结果包含诸如测试用例日志,JUnit报告,覆盖率报告之类的信息,以及由测试生成的任何其他有用信息。 请注意报告中的六个环境。 所有测试用例在这些环境中每晚运行,并且白天可用于增量测试。 在可用环境中有Linux for System z,Windows和Linux(Red Hat)计算机。 通过为每个新环境创建属性文件,可以将新环境插入系统。
包含基本功能的连续集成系统可以按照以下顺序逐步构建:
使用STAF / STAX来构建测试用例和基础结构以进行持续集成的一个显着优势是,通过创建可集成到其中的新功能和脚本,可以根据需要灵活地扩展测试自动化系统。 当项目采用敏捷开发并具有使用STAF / STAX自动化所有测试并将其集成到持续集成系统中的能力时,您可以及时测试新功能或修复。 同样,应用户要求,在一组不同环境中并行执行增量测试可以缩短开发时间并提高软件质量。
翻译自: https://www.ibm.com/developerworks/opensource/library/os-test-stafstax/index.html