敏捷开发和测试中重现缺陷和验证缺陷的解决方案(3)

简介:

简介:在作为系列的最后一篇覆盖的部分是缺陷生命周期的最后一个环节,缺陷的验证。本文主要描述了如何通过 Rational Team Concert(RTC)、Rational Quality Manager(RQM)及 IBM Workload Deployer(IWD)实现缺陷验证的自动化,而且笔者通过一个 RTC web 插件来展现自动化页面。

  背景

  系列前两篇中我们描述了如何用 IBM 产品帮助开发人员快速重现缺陷问题,下面本文主要描述一下我们是如何使用 IBM 产品加速缺陷验证过程的。

  在缺陷验证的过程中,测试人员需要完成一下几个任务:

  ● 定位可验证的缺陷 (Verifiable Defect)

    ▲ 可验证的缺陷是指缺陷对应的产品代码变动已经被开发人员提交并包含在产品最新版本中。

    ▲ 定位的范围一般包括

      → 测试人员自己提交的缺陷(Created by)

      → 由其他人员提交的,需要测试人员关注的缺陷(Subscribed by)

    ▲ 测试人员一般需要针对每个关注的缺陷查看是否相应的代码变更已经包括在最新产品版本中。

  ● 快速部署缺陷验证的测试环境

    ▲ 环境准备一直是比较耗时的部分,不过这里我们可以借助在第一篇中我们创建的重现缺陷用的 IWD 中的虚拟系统模式 (Virtual System Pattern)。

  ● 调用对应的测试用例执行

    ▲ 测试人员需要找到对应的测试用例,在最新产品版本中重现执行。

  ● 更新缺陷状态和信息

    ▲ 根据最新的测试执行结果,可以判断缺陷是否还存在,从而更新缺陷状态和信息记录。

  本文主要解决的问题

  ● 如何快速定位可验证的缺陷

  ● 把缺陷验证环节自动化,自动化内容包括:

    ▲ 准备测试环境

    ▲ 执行测试用例

    ▲ 更新缺陷状态和信息

  ● 更好的用户体验

    ▲ 现在每个团队都会在不同程度上通过自动化工具来解决上述问题。由于上述工作涉及存储不同信息的软件系统,测试人员就需要登陆不同的系统采取相应的操作,例如:

      → 缺陷管理系统:开发和测试人员在这里可以更改缺陷的内容和状态。

      → 产品 build 管理系统:每个产品在正式发布前,内部的研发解决都会采用某个软件或系统对产品代码进行管理并且对内部发布产品非正式版本 (Build) 用于开发和测试。产品 Build 管理系统会记录每个 Build 所包含的代码变动,也会同时记录这一代码变动是由哪个缺陷引起的。

      → IT 环境管理系统:这一系统通常会为开发测试人员提供可用的环境。在某些团队中会通过不同的软件来调用 IT 环境管理系统来实现不同程度的自动化环境部署。

      → 测试管理系统:存储测试用例,测试结果和测试计划等内容。

    ▲ 所以开发和测试人员在完成缺陷验证工作的过程中,需要登录各种不同的软件系统,而没有统一入口的使用方式会带来不好的用户体验。

  实现框架

图 1. 实现框架



框架中有四个主要的部分:

  1、搜索:这个部分负责跟缺陷管理系统和产品 Build 管理系统交互获得跟用户有关的可验证缺陷信息、对应的产品 Build 信息和测试用例的信息。

  2、部署环境:负责接收搜索部分提供的结果,准备测试环境。框架中给出了两个部署环境的方案,第一个是创建一个新的测试环境;第二个是查找跟这个用户有关的已经存在的测试环境,并把产品的最新 Build 部署到这个环境中。这里第二个方案也是为了能够更好地重用测试资源,以免造成浪费。

  3、测试执行:根据搜索部分提供测试用例,调用对应的自动化测试用例脚本进行验证。

  4、状态更新:根据测试执行的结果自动更新缺陷的状态和内容。

  框架中提到的不同软件系统,每个团队可以针对自己的实例完成实现。

  实现部分 1:搜索可验证的缺陷

  在 RTC 中我们的实现是开始于 RTC 中的一个缺陷查询 (Query),用户可以自己定义一个缺陷查询包括那些状态时 Resolved 的缺陷。

图 2. RTC 中的缺陷查询

  清单 1. 引用 RTC 中用户自定义的缺陷查询

  搜索条件包括三个方面,

  ● 产品– 由于 RTC 同一个项目中可能会涉及多个产品的缺陷记录,而一个用户又有可能会对多个产品的缺陷负责,所以产品作为第一个筛选条件。

  ● 产品版本– 由于 RTC 同一个项目中可能会涉及同一个产品的不同版本的开发以及缺陷记录,而一个用户又有可能会工作于不同的产品版本。

  ● 环境 -- 在 RTC 中可以为不同的项目缺陷记录定义不同的字段,这里可以定义环境的信息。(如图3)

图 3. RTC 缺陷中的环境字段

  根据用户自定义的缺陷查询和选定的三个筛选条件,我们可以完成第一次筛选,得到待验证的缺陷列表。下面就需要去版本控制系统中查找当前产品版本中包含哪些待验证的缺陷。

图 4. 筛选可验证的缺陷

  由于本文作者没有直接使用 RTC 作为版本控制软件,而是采用其他软件进行版本控制,所以这里没有具体介绍图 4 中代码的实现。










 实现部分 2:缺陷验证环境的部署

  由于我们在系列第二篇中曾经提到对 RTC 中存储的缺陷添加"IWD Pattern"字段,用于存储虚拟系统模式的名字,这里可以直接通过 RTC RESTAPI 获得虚拟系统模式名称,然后通过 IWD 的命令行工具 (Command Line Tool) 或者 RESTAPI 在对应的 IWD 服务器上创建缺陷验证环境。

  IWD 提供的命令行工具可以直接从 IWD 的登陆界面上下载:

图 5. IWD 登陆界面中命令行工具下载页面

 

图 6. IWD 命令行工具本地文件结构

  IWD 命令行工具是通过 python 脚本调用 IWD RESTAPI 实现具体功能的,工具中的 readme 文件具体描述了如何调用 python 脚本,或者读者也可以从参考资源中提供的链接学习如何调用。以下是两个 python 脚本,在部署缺陷环境前先查找缺陷中记录的虚拟系统模式是否包含在这个 IWD 服务器中,如果在则继续部署这个虚拟系统模式为一个虚拟机环境。

  清单 2. 查看 IWD 服务器上所有虚拟系统模式信息

#
# For each pattern returned, the name of the pattern is presented
#
import ConfigParser
import threading, time, csv, random

# get all the vsystems associated with a pattern
# this emulates the user clicking on the "Systems" selection in the tree view
def get_systems(pattern, fname, fhandle):
    nsystems = 0
    start = time.time()
    nSystems = len(pattern.virtualsystems)
    for cnt in range (nSystems):
        try:
            system = pattern.virtualsystems[cnt]
        except:
            break        
    finish = time.time()
    fname.writerow([time.strftime("%m/%d/%Y"), time.strftime("%H:%M:%S"),'system',
                     nSystems, (finish-start)])
    fhandle.flush()
    
# get all the patterns
# this emulates the user clicking on the "Patterns" selection in the tree view
def get_patterns(fname, fhandle):
    start = time.time()
    patterns = deployer.patterns
    finish = time.time()
    fname.writerow([time.strftime("%m/%d/%Y"), time.strftime("%H:%M:%S"),'pattern', 
                   len(patterns), (finish-start)])
    fhandle.flush()
    
    for pattern in patterns:
        if (len(pattern.virtualsystems) > 0):
            time.sleep(random.randint(1, 10))            
            get_systems(pattern, fname, fhandle)

######
config = ConfigParser.RawConfigParser()
config.read('listPatterns.cfg')

try:
    output = '%s_%s.csv' % (config.get('Main', 'outfile'),time.strftime("%Y%m%d@%H%M%S"))
    interval = config.getint('Main', 'interval')
    duration = config.getint('Main', 'duration')
except ConfigParser.Error:
    print "Error reading config file"
    sys.exit

fhandle = open(output, 'w')
fname = csv.writer(fhandle, delimiter=',')
fname.writerow(['date', 'time', 'type', 'number','duration'])
fhandle.flush()

print 'Running ...'
print 'Output File: %s\tDuration: %d\tInterval: %d' % (output, duration, interval)

end_time = time.time()+(60*duration)
while (end_time > time.time()):
    start = time.time()
    time.sleep(random.randint(1, 10))
    get_patterns(fname, fhandle)
    
    # only sleep the remainder of the interval
    time.sleep((time.time()+interval) - start)
    
print 'Completed on %s at %s' % (time.strftime("%m/%d/%Y"), time.strftime("%H:%M:%S"))
fhandle.close()


 清单 3. 部署制定的虚拟系统模式

import time, threading, Queue, csv
   
# deploy the images for performance throughput
class waitfor(threading.Thread):
    def __init__(self, system, log_q):
        self.system = system
        self.log_q = log_q
        threading.Thread.__init__(self)
            
    def run(self):
        start = time.clock()
        self.system.waitFor()
        finish = time.clock()           
        self.log_q.put_nowait([time.strftime("%m/%d/%Y"), time.strftime("%H:%M:%S"),
                              self.system.name,self.system.currentstatus,(finish-start)])
    
def run_test(instances, fname):
    log_q = Queue.Queue()
    threads = []
    for instance in range (int(instances)):
        virtualsystem = None
        sysName = '%s-%s-%s-%d' % (pfx, time.strftime("%Y%m%d"),time.strftime("%H%M5%S"),
                                   instance+1)
        print 'deploying virtual system: %s' % sysName
        
        createParms['name'] = sysName
        virtualsystem = deployer.virtualsystems << createParms
        sys = waitfor(virtualsystem, log_q)
        sys.start()
        threads.append(sys)
    
    #wait until all are done
    for thd in threads:
        thd.join()
    
    # write out the results
    fname = csv.writer(open(fname, 'w'))
    fname.writerow(['date', 'time', 'system_name','status','duration'])
    for xx in range(log_q.qsize()):
        data = log_q.get()
        fname.writerow(data)

#################################################################
# select pattern to deploy
instances = raw_input('number of instances to create: ')
pfx = raw_input('prefix for created systems: ')
output = raw_input('results file (** will be overwritten **): ')
createParms = {}

# default parameters
createParms['*.script-4.CHEF_NODE'] = 'devops_default'
createParms['*.script-4.DEPS_FILE_URL'] = '/tmp/devops_install/media/Deps-devops_services'
createParms['*.script-4.CHEF_NODE_ATTR'] = 
    '\"devops_server\"\:
    {\"app_source\"\:\"file:///tmp/devops_install/media/devops_services_app.zip\"}, 
    \"ram\"\:{\"server_url\"\:
    \"http://devops.rtp.raleigh.ibm.com/downloads/RAM-Server-7.5.1.1-Linux64.zip\",
    \"persist_url\"
    \:\"http://devops.rtp.raleigh.ibm.com/downloads/RAM-Data-7.5.1.1.tar.gz\",
    /\"database_url\"\:
    \"http://devops.rtp.raleigh.ibm.com/downloads/RAM-Database-7.5.1.1.tar.gz\"},
    \"db2\"\:{
    \"host_server_url\"\:\"http://devops.rtp.raleigh.ibm.com/downloads\"},
    \"jruby\"\:{\"download_url\"\:\"http://devops.rtp.raleigh.ibm.com/downloads/\"}'
createParms['cloud'] = deployer.clouds[0]

# select the performance pattern to deploy
pattern = None
while not pattern:
    i = 1
    for p in deployer.patterns:
        print '%d. %s' % (i, p.name)
        i = i + 1
    x = raw_input('select the test pattern to deploy: ')
    try:
        pattern = deployer.patterns[int(x) - 1]
    except:
        # try again
        pass
createParms['pattern'] = pattern

#start deploying
started = time.strftime("%m/%d/%Y at %H:%M:%S")
run_test(instances, output)    
completed = time.strftime("%m/%d/%Y at %H:%M:%S")

print '#############   test summary  #######################'
print 'Started on: %s\tCompleted on: %s' % (started, completed)
print 'Images deployed: %s' % instances

  实现部分 3:测试执行

  测试执行的时候我们需要调用 RQM 的命令行执行工具 (Command Line Execution Tool),这个工具是跟着 RQM 同时发布在 Jazz.net 上的,具体下载请看参考资源中提供的链接。

  RQM 命令行执行工具是我们可以方便的执行测试,通过 RQM RESTAPI 启动测试执行记录 (Test Execution Record) 的运行。在运行测试执行时需要提供以下信息:

  ● RQM url – https://hostname:9443/qm

  ● 用户名和密码 -- 使用这个用户名允许运行相应的测试执行记录

  ● 项目– 测试用例所在的 RQM 中的测试项目

  ● 测试执行记录的 id

  ● 测试执行记录关联的脚本的 id

  ● 执行适配器 (Adapter) 的 id

    ▲ 执行适配器是 RQM 提供的用以连接并操作具体测试脚本的功能,常用的适配器包括 Rational Functional Tester、Rational Performance Tester、Rational Build Forge 以及其他更多第三方厂商和开源工具的适配器。用户也可以自己编写适配器。

  ● 执行时需要的参数

  通过命令行调用后执行结果是会输出到命令行的,也可以直接输出到文件,用于后续操作。


实现部分 4:自动化中注意事项

  要把整个流程自动化需要用到流程工具,可以用开源的 ant 或者使用 IBM Rational Build Forge。

  这里主要介绍几个重点:

  1、测试用例相关信息获得

  a)缺陷可以通过 RTC 与 RQM 之间的 OSLC 关联关系连接 RQM 中的测试执行结果 (Test Execution Result),测试执行结果是测试执行记录 (Test Execution Record) 的执行结果。

  b)然后我们可以从缺陷中获得测试执行结果的 url,经过分析我们可以获得 RQM 项目名称,测试执行结果 id 等信息,用于调用 RQM 命令行执行工具。

  2、缺陷验证环境信息的传递

  a)缺陷验证环境是我们通过部署虚拟系统模式生成的新的虚拟机,所以 ip、hostname、用户名和密码都是新的。而在验证系列第二篇中提到的 WAS 卖花网站中遇到的缺陷,我们需要传送新的 url 地址给 RFT 脚本。

  b)在调用 RQM 命令行执行工具的时候就需要传输参数

  清单 4. RQM 命令行调用附参数

c:\IBM\java60\bin\java -jar RQMExecutionTool.jar -tcerId=1 -projectName=QM1 
                       -publicURI=https://paul801beta:9443/qm -user=paul 
                       -password=passw0rd -exitOnComplete=true 
                       -variables=host:clmsvr-sjy.cn.ibm.com

    c)RFT 中接受参数的脚本如下

  清单 5. RFT 脚本

import com.rational.test.ft.script.IParameter;
import com.rational.test.ft.script.IVariablesManager;
public class SampleScript extends SampleScriptHelper
{
    /**
     * Script Name   : <b>SampleScript</b>
     * Generated     : <b>Dec 10, 2012 1:44:05 PM</b>
     * Description   : Functional Test Script
     * Original Host : WinNT Version 5.1  Build 2600 (S)
     *
     * @since  2012/12/10
     * @author Administrator
     */
    public void testMain(Object[] args)
    {
        //接收参数的定义
        IVariablesManager manager = getVariablesManager();
        IParameter host = manager.getInputParameter("host");
        
        
        startApp("http://" + host.getValue() + ":9081/PlantsByWebSphere/");
        
        // HTML Browser
        // Document: Plants by WebSphere: 
        // http://clmsvr-sjy.cn.ibm.com:9081/PlantsByWebSphere/
        // Document: http://clmsvr-sjy.cn.ibm.com:9081/PlantsByWebSphere/promo.html
        image_bonsaiTree().click();
        // Document: 
        // http://clmsvr-sjy.cn.ibm.com:9081/PlantsByWebSphere/servlet/ShoppingServlet?
        //      action=productdetail&itemID=T0003
        browser_htmlBrowser(document_plantsByWebSphere(),DEFAULT_FLAGS).inputChars("abc");
        button_addToCart().click();
    }
}

  这里提示一下 RQM 命令行执行工具也提供了 ant 任务调用,方便把执行测试这部分集成到自动化的流程中。

  实现部分 5:Jazz 插件的开发

  Jazz 插件的开发与 Eclipse 插件开发模式是一致的,Jazz 平台定义了丰富而功能强大的扩展点,用户可以利用这些扩展点,定义和实现各种定制功能。

  首先要搭建扩展开发环境,Jazz.net 网站提供了详细的下载 SDK 链接,以及参考文档。

  RTC Server 端服务的扩展,有关 Jazz Component 开发详细资料请查看参考资源中提供的链接。Jazz Component 开发扩展扩展点"com.ibm.team.repository.common.components",定义服务类接口,类型是 Raw_HTTP。

  清单 6

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?>
<plugin>
   <!--
      This extension defines our component to Jazz. Note that the
      common plugin is included on both the client and server, so
      the component is known both places.
   -->
   <extension
         point="com.ibm.team.repository.common.components">
      <component
            id="com.ibm.rational.svt.workitem.extensions"
            name="Workitem Validation Workflow">
         <service
               kind="RAW_HTTP"
               name="Workitem Validation WorkFlow Rest Service" 
               uri="com.ibm.rational.svt.workitem.extensions.common.
                    IWorkitemValidationWorkflowRestService"
               version="1">
         </service>
      </component>
   </extension>
</plugin>







最新内容请见作者的GitHub页:http://qaseven.github.io/

目录
相关文章
|
8天前
|
敏捷开发 机器学习/深度学习 人工智能
探索自动化测试在敏捷开发中的关键作用
【4月更文挑战第30天】 随着软件开发实践的不断进化,敏捷方法论已成为推动快速迭代和响应市场变化的重要工具。在此过程中,自动化测试作为确保软件质量和提升开发效率的关键环节,其重要性愈发凸显。本文将深入探讨自动化测试在敏捷开发环境中的作用,分析其如何助力持续集成和持续交付(CI/CD),并讨论实现高效自动化测试的策略与挑战。通过实际案例分析,揭示自动化测试对缩短反馈周期、降低人力成本以及维护软件稳定性的贡献。
|
6天前
|
算法 异构计算
基于直方图的图像曝光量分析FPGA实现,包含tb测试文件和MATLAB辅助验证
该内容包括了算法的运行效果展示、软件版本信息、理论概述和核心程序代码。在正常图像中,`checkb`位于`f192b`和`f250b`之间,而多度曝光图像中`checkb`超出此范围,判断为曝光过度。使用的软件为Vivado 2019.2和MATLAB 2022a。理论依据未详细给出,但提及主要方法。提供的Verilog代码段用于处理图像数据,包括读取文件、时钟控制及图像histogram计算等,其中模块`im_hist`似乎是关键部分。
|
7天前
|
敏捷开发 测试技术 持续交付
探索自动化测试在敏捷开发中的应用移动应用的未来:跨平台开发与操作系统的融合
【4月更文挑战第30天】随着软件开发周期的不断缩短,传统的软件测试方法逐渐显得力不从心。本文将深入探讨自动化测试在敏捷开发环境中的关键作用,分析其如何提高测试效率、减少人力资源成本,并确保软件产品的质量与稳定性。通过案例分析,我们还将讨论实施自动化测试的最佳实践和面临的挑战,为追求高效敏捷开发的组织提供参考。
|
8天前
|
敏捷开发 开发框架 测试技术
探索自动化测试在敏捷开发中的关键作用
【4月更文挑战第30天】 在快速迭代的软件开发过程中,自动化测试已成为确保产品质量和加快交付速度的核心实践。本文将深入探讨自动化测试在敏捷开发环境中的重要性,分析其如何帮助团队实现持续集成和持续部署,并保持高效率的同时降低错误率。我们将通过实际案例来揭示自动化测试策略的最佳实践,并提出一系列优化建议,以促进测试流程的改进和效率提升。
|
8天前
|
敏捷开发 测试技术 持续交付
探索自动化测试在敏捷开发中的关键作用
【4月更文挑战第30天】 随着软件开发实践的不断演进,敏捷开发已成为推动快速迭代和交付的主流模式。本文深入探讨了自动化测试在敏捷环境中的重要性,分析了如何通过自动化测试提高软件质量、缩短反馈周期,并促进持续集成的实践。我们将从自动化测试的基本概念入手,讨论其与敏捷方法论的契合点,并通过案例分析展示自动化测试如何有效支持敏捷团队应对快速变化的需求和技术挑战。
|
8天前
|
算法 TensorFlow 算法框架/工具
基于直方图的图像阈值计算和分割算法FPGA实现,包含tb测试文件和MATLAB辅助验证
这是一个关于图像处理的算法实现摘要,主要包括四部分:展示了四张算法运行的效果图;提到了使用的软件版本为VIVADO 2019.2和matlab 2022a;介绍了算法理论,即基于直方图的图像阈值分割,通过灰度直方图分布选取阈值来区分图像区域;并提供了部分Verilog代码,该代码读取图像数据,进行处理,并输出结果到&quot;result.txt&quot;以供MATLAB显示图像分割效果。
|
9天前
|
敏捷开发 机器学习/深度学习 Java
Java中的异常处理机制深入理解与实践:持续集成在软件测试中的应用探索自动化测试在敏捷开发中的关键作用
【4月更文挑战第29天】在Java编程中,异常处理是一个重要的概念。它允许开发者在程序执行过程中遇到错误或异常情况时,能够捕获并处理这些异常,从而保证程序的稳定运行。本文将详细介绍Java中的异常处理机制,包括异常的分类、异常的处理方式以及自定义异常等内容。 【4月更文挑战第29天】 随着敏捷开发和DevOps文化的兴起,持续集成(CI)已成为现代软件开发周期中不可或缺的一环。本文将探讨持续集成在软件测试领域内的关键作用、实施策略以及面临的挑战。通过对自动化构建、测试用例管理、及时反馈等核心要素的详细分析,揭示持续集成如何提高软件质量和加速交付过程。 【4月更文挑战第29天】 在当今快速发
|
13天前
|
敏捷开发 运维 jenkins
探索自动化测试在敏捷开发中的应用与挑战
【4月更文挑战第25天】 在当今软件开发的快速迭代周期中,敏捷方法论已成为推动项目高效进行的关键。本文聚焦于自动化测试技术在敏捷开发环境下的应用实践,分析了其在提升软件交付速度和质量方面发挥的核心作用。通过深入探讨自动化测试框架的选择、测试用例设计、持续集成的实施等关键技术点,揭示了在多变的需求面前如何维持测试覆盖率和准确性。同时,本文也识别了实施过程中可能遇到的挑战,如资源分配、工具选型以及团队协作等,并提出了相应的解决策略。
|
14天前
|
算法 计算机视觉 异构计算
基于FPGA的图像累积直方图verilog实现,包含tb测试文件和MATLAB辅助验证
该内容展示了FPGA实现图像累积直方图的算法。使用Vivado2019.2和matlab2022a,通过FPGA的并行处理能力优化图像处理。算法基于像素值累加分布,计算图像中像素值小于等于特定值的像素个数。核心代码为`test_image`模块,读取二进制图像文件并传递给`im_hist`单元,生成直方图和累积直方图。
|
23天前
|
算法 计算机视觉 异构计算
基于直方图相似性的图像分类算法FPGA实现,包括tb测试文件和MATLAB辅助验证
该内容包含了一段关于图像处理算法的摘要,主要包括: 1. 展示了MATLAB和FPGA的测试结果图像,显示了图像读取完成的标志和相似性指标,其中图1与图2有较强相似性,图1与图3相似性较弱。 2. 算法使用的是vivado 2019.2和matlab 2022A版本。 3. 算法原理涉及图像直方图统计和直方图相似性度量,通过计算直方图的差异来衡量图像相似度,FPGA实现包括图像采集、直方图计算、比较和分类决策步骤。 4. 提供了一个部分核心Verilog程序,用于读取图像数据并在FPGA上进行直方图相似性计算。

热门文章

最新文章