从代码里提取的测试需求

       服务器端的测试,软件需求基本等于产品说明书,只有大概,没有详尽。再需求不充分的情况下,我们可以从哪些方面来挖掘测试需求呢?

现已知需求:服务器支持对客户端的版本升级,存在两种升级规则:

第一:最低版本升级:按照客户端的类型,如果当前版本小于最低版本要求则需要进行升级

第二:指定版本升级:根据某个客户端类型+版本信息,强制或者提示升级到指定版本

      如果同时满足2种升级规则,优先匹配第二种。配置文件如下:

一般测试人员都能分析到以下两点如下:

  1. 两种规则同时满足时,怎么选择?
  2. 第一种规则:当前版本《 最低版本,则提示需要进行升级。那当前版本》最低版本的时候呢?

          第二种规则:当前版本《 最低版本,则需要强制升级,那当前版本》最低版本的时候呢?

 假设当前客户端类型只有一种,设只有PC客户端,一般都能写出以下的测试用例:

 

  那这样的设计,算全面了么,再深入一层分析,又缺少了什么呢?

1、  产品和两个规则的关系如何?1对1,1对多?每个产品都可能存在多个指定版本升级的规则?

2、  总共运营上存在14个产品,每类产品都需要覆盖测试?

3、  客户端与服务器是怎么进行交互的,客户端传递什么数据到服务器,服务器返回什么给客户端?升级的整个流程是什么样的,清楚么?

4、  之前考虑的第二点,太粗糙,》之外的,除了《,还有 = 。

                                                                                                                             

客户端和服务器端的接口核心函数代码如下:

//GetProductItem为服务器端与客户端之间的接口函数,客户端传szProductID,szVersion给服务器端,然后服务器就此作出判断,返回正确的数据到item类中,供客户端调用。

bool CConfig::GetProductItem(const CHAR *szProductID, const CHAR *szVersion, ProductItem &item)

{

// 先根据ProductID确定产品的ProductDetail

    ProductDetail *pProduct = FindProduct(szProductID);

    //如果客户端传递的szProductID为空,则用默认的

    if (!pProduct)

    {

   //m_strDefaultProduct存储从配置文件中读取的DefaultProduct的ID

      pProduct = FindProduct(m_strDefaultProduct.c_str());

   //如果默认的为空,则直接返回false

        if (!pProduct)

        {

            return false;

        }

 }

 

//根据szVersion在确定的ProductID内得到grayupdate配置的版本

//find()函数返回一个迭代器指向键值为key的元素,如果没找到就返回指向map尾部的迭代器

    auto iter = pProduct->mapVersionInfo.find(szVersion);

    //如果没有找到,就用默认版本信息(强制升级块)

    if (iter == pProduct->mapVersionInfo.end())

    {

        iter = pProduct->mapVersionInfo.find(DEFAULT_VERSION);

        if (iter == pProduct->mapVersionInfo.end())

        {

            return false;

        }

    }

 

// 在服务器端将strMinVersion,strNewVersion,lsDownloadUrl存在item,返回给客户端,由客户端控制怎么强制升级还是提示升级。

    item.strProductID = pProduct->strProductID;

    item.strWebServicesURL = m_strWebServicesURL;

    item.strMinVersion = iter->second.strMinVersion;

    item.strNewVersion = iter->second.strNewVersion;

    item.lsDownloadUrl = iter->second.lsDownloadUrl;

 

    return true;

}

FindProduct的实现过程如下:

服务器在等待客户端发送客户端相关数据过来前,服务器启动时,就加载配置文件,读取对应服务器下的配置文件<CONFIG>里的数据到szConfig中,然后调用LoadConfig的方法。

//LoadConfig方法作用:将配置文件里的数据,默认配置的产品ID读取到szProductID,产品的其他所有信息读取到pProductDetail中。

BOOL CConfig::LoadConfig(const CHAR *szConfig)

{

    if (NULL == szConfig)

        return FALSE;

 

    TiXmlElement element("");

element.Parse(szConfig, NULL, TIXML_ENCODING_UTF8);

 

// 取配置信息中DefaultProduct元素的数据存在szProductID中。

    const CHAR *szProductID = TiXmlGetValue(&element, "DefaultProduct");

    if (!szProductID || strcmp(szProductID, "") == 0)

    {

        return FALSE;

    }

    m_strDefaultProduct = szProductID;

 

// szWebServicesURL 变量暂时未被使用(以前的旧代码),可以忽略

  const CHAR *szWebServicesURL = TiXmlGetValue(&element, "WebServicesURL");

    if (szWebServicesURL)

    {

        m_strWebServicesURL = szWebServicesURL;

}

 

//读取配置文件中Product的第一个元素的信息,将里面的值返回pProductDetail类中

   TiXmlElement *pProductDetail=element.FirstChildElement("Product");

    if (!pProductDetail || !ReadProductDetail(pProductDetail))

    {

        return FALSE;

    }

    return TRUE;

}

 ReadProductDetail函数的作用就是将product下对应的部分数据,读取到pProductDetail的成员变量strProductID和mapVersionInfo(版本集合内).

     看完代码,得知的大致流程如下:首先服务一启动,就会将每个Product下的pProductDetail保存起来,然后客户端发送szProductID,szVersion给服务器端,服务器端首先是在m_lsProduct(list)下查找出自己对应的pProductDetail信息,如果没有找到,则使用默认版本,然后根据szVersion在确定的ProductID内得到grayupdate配置的版本,如果没有找到,就用默认版本信息,将得到的数据都保存在item类,返回给客户端。

那思考之前的疑惑,解答如下:

  1. 存在一个产品,有多个指定版本升级的情况,测试用例需要增加。
  2. 运营线是有14个,但是根据程序内部实现方法(容器循环控制找产品ID),是没必要配置14个的,测试4个,4个产品都能依次正常通过测试,就能保证14个没问题。
  3. 交互过程,接口输入输出已表明。
  4. 等于的时候是什么情况,得与开发沟通。

 修正测试点如下:

 

转载于:https://www.cnblogs.com/loleina/p/5091114.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/375215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PUSH/POP

栈操作指令PUSH 寄存器/段寄存器/内存单元POP 寄存器/段寄存器/内存单元PUSH AX1)SPSP-2 ,SS:SP指向新的内存单元2)将AX送入SS:SP指向的内存单元POP AX1)将SS:SP指向的内存单元处的数据送入AX中2)SPSP2

Android Ant 和 Gradle 打包流程和效率对照

一、Ant 打包&#xff1a;&#xff08;下载ant、配置环境变量就不说了&#xff09; 1、进入命令行模式&#xff0c;并切换到项目文件夹。运行例如以下命令为ADT创建的项目加入ant build支持&#xff1a; android update project -p . -t "android-17" 2、build脚本默…

读软件工程这本书的感悟(第一次作业)

在还没上这门课之前&#xff0c;我认为软件工程是让我们学会编写软件&#xff0c;但是在看到这本书后&#xff0c;我才知道我们学的不是如何的开发软件&#xff0c;而是在学习开发和维护软件&#xff0c;以及如何把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术…

请大家编译连接并执行一下

由于是笔记&#xff0c;也许记得有点糟糕&#xff0c;也许班门弄斧没有独到见解 &#xff0c;见谅见谅

KVC和KVO

OC中的一个比较有特色的知识点&#xff1a;KVC和KVO一、KVC操作OC中的KVC操作就和Java中使用反射机制去访问类的private权限的变量&#xff0c;很暴力的&#xff0c;这样做就会破坏类的封装性&#xff0c;本来类中的的private权限就是不希望外界去访问的&#xff0c;但是我们这…

8086加法指令ADD

加法指令ADD(ADDition) ADD OPRD1,OPRD2 ;OPRD1<--OPRD1OPRD2 ;完成OPRD1与OPRD2相加 ,结果保存在OPRD1中CODE SEGMENT MOV AX,1 MOV BX,2 ADD AX,BX ;AX<--AXBX ,结果AX3CODE ENDS参与运算的操作数类型必须保持一致,同为字节或字可组合以下几种形式&…

Fragment基础讲解

//新建一个碎片public class LeftFragment extends Fragment { Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 加载一个碎片界面 View view inflater.inflate(R.layout.leftfragment, container, false)…

[bzoj1012](JSOI2008)最大数maxnumber(Fenwick Tree)

Description 现在请求你维护一个数列&#xff0c;要求提供以下两种操作&#xff1a; 1、 查询操作。语法&#xff1a;Q L 功能&#xff1a;查询当前数列中末尾L个数中的最大的数&#xff0c;并输出这个数的值。限制&#xff1a;L不超过当前数列的长度。 2、 插入操作。语法&…

javaScript转换日期合格式

javascript如何将时间日期转换为Date对象:有时候需要讲一个字符串型的时间日期转换为Date时间对象&#xff0c;下面就通过一个简单的实例提供一种解决方案&#xff0c;当然也是一种思路&#xff0c;可以进行一定的变通&#xff0c;以达到举一反三的效果。例如这里有一个时间日期…

8086减法指令SUB

减法指令SUB(SUBtraction) SUB OPRD1,OPRD2 ; OPRD1<-- OPRD1-OPRD2 都影响FLAG标志寄存器,同样的包含两种含义(有符号减法和无符号减法)

奇怪吸引子---Dadras

奇怪吸引子是混沌学的重要组成理论&#xff0c;用于演化过程的终极状态&#xff0c;具有如下特征&#xff1a;终极性、稳定性、吸引性。吸引子是一个数学概念&#xff0c;描写运动的收敛类型。它是指这样的一个集合&#xff0c;当时间趋于无穷大时&#xff0c;在任何一个有界集…

8086 INC, DEC

INC OPRD ;OPRD<--OPRD1 ;自加1指令code segmentmov ax,0inc ax ;ax<--ax1 ,ax1inc ax ;ax<--ax1 ,ax2code endsDEC OPRD ;OPRD<--OPRD-1 ;自减1指令code segmentmov ax,5dec ax ;ax<--ax-1 ,ax4 code ends

iPhone UITableViewCell如何滚动到视图顶端。

如何让UITableViewCell滚动到视图顶端。 - (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated;- (void)scrollToNearestSelectedRowAtScrollPosition:(UITableViewScrollPosition)s…

app 一些常用的

发短信 &#xff1a;sms:10086 打电话&#xff1a;tel:10086 1、-webkit-tap-highlight-color:rgba(255,255,255,0)可以同时屏蔽ios和android下点击元素时出现的阴影。备注&#xff1a;transparent的属性值在android下无效。 2、-webkit-appearance:none可以同时屏蔽输入框怪异…

8086乘法指令MUL,IMUL

对于加减指令来说CPU对有符号加减和无符号加减一视同仁,根据我们需要把它作为有符号的结果还是无符号的结果,但是乘除法指令区分有符号乘除和无符号乘除指令 无符号数乘法指令MUL(MULtiply) MUL OPRD(OPRD可以用除立即数以外的任何寻址方式)OPRD是八位一个乘数默认在AL中 则&am…

hdu 4857 逃生 拓扑排序

逃生题目连接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid4857 Description 糟糕的事情发生啦&#xff0c;现在大家都忙着逃命。但是逃命的通道很窄&#xff0c;大家只能排成一行。 现在有n个人&#xff0c;从1标号到n。同时有一些奇怪的约束条件&#xff0c;每个…

指针数组,数组指针,指针函数,函数指针(转)

int *p[4]; //指针数组。 是个有4个元素的数组&#xff0c; 每个元素的是指向整型的指针。(数组的每个元素都是指针)int (*p)[4]; //数组指针。 它是一个指针&#xff0c;指向有4个整型元素的数组。 (一个指针指向有4个整型元素的数组)int *…

8086除法指令DIV,IDIV

无符号除法指令DIV(DIVision) DIV OPRD ;除数OPRD决定是8位除法还是16位除法;OPRD8位,则被除数默认在AX中,AX除以OPRD的商保存在AL中,余数保存在AH中;OPRD16位,则被除数默认在DX与AX中,结果的商保存在AX中,余数保存到DX中assume cs:code data segmentdb 2,4 data ends code se…

Hibernate 基础配置及常用功能(二)

本章主要是描述几种经典映射关系&#xff0c;顺带比较Hibernate4.x和Hibernate5.x之间的区别。 一、建立测试工程目录 有关实体类之间的相互映射关系&#xff0c;Hibernate官方文档其实描述的非常详细&#xff0c;这里只提供几种常见映射。&#xff08;推荐4.3.11版本的 hibern…

三言两语

人生中总是在选择。每当做一件事我们都应该问问我们的内心&#xff0c;或多或少我们都能理解一点人生的真谛。 最近时间很充裕&#xff0c;也就想了好多事情。首先我想明白的第一件事就是做任何事就要勇敢的去面对、去追求。喜欢一个女孩子大概有8年了吧&#xff01;这期间我们…