发布新日志

  • Linux静态库和动态库

    2011-10-20 11:18:20

    库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。  

     

    静态库和动态库的区别

    1. 静态函数库 

        这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。 

    2. 动态函数库 

        这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。 

    linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。 

     

    静态库的使用

    静态库的操作工具:gccar 命令。  

    编写及使用静态库  

    (1)设计库源码 pr1.c 和 pr2.c  

    [root@billstone make_lib]# cat pr1.c  

    void print1()  

    {  

                    printf("This is the first lib src!\n");  

    }  

    [root@billstone make_lib]# cat pr2.c  

    void print2()  

    {  

                    printf("This is the second src lib!\n");  

    }  

    (2)  编译.c 文件  

    [bill@billstone make_lib]$ cc -O -c pr1.c pr2.c  

    [bill@billstone make_lib]$ ls -l pr*.o  

    -rw-rw-r--        1 bill          bill                    804    4 月  15 11:11 pr1.o  

    -rw-rw-r--        1 bill          bill                    804    4 月  15 11:11 pr2.o  

    (3)  链接静态库  

        为了在编译程序中正确找到库文件,静态库必须按照 lib[name].a 的规则命名,如下例中[name]=pr.  

    [bill@billstone make_lib]$ ar -rsv libpr.a pr1.o pr2.o  

    a - pr1.o  

    a - pr2.o  

    [bill@billstone make_lib]$ ls -l *.a  

    -rw-rw-r--        1 bill          bill                  1822    4 月  15 11:12 libpr.a  

    [bill@billstone make_lib]$ ar -t libpr.a  

    pr1.o  

    pr2.o  

    (4)  调用库函数代码 main.c  

    [bill@billstone make_lib]$ cat main.c  

    int main()  

    {  

                    print1();  

                    print2();  

                    return 0;  

    }  

    (5)  编译链接选项  

        -L -l 参数放在后面.其中,-L 加载库文件路径,-l 指明库文件名字.  

    [bill@billstone make_lib]$ gcc -o main main.c -L./ -lpr  

    [bill@billstone make_lib]$ ls -l main*  

    -rwxrwxr-x        1 bill          bill                11805    4 月  15 11:17 main  

    -rw-rw-r--        1 bill          bill                      50    4 月  15 11:15 main.c  

    (6)执行目标程序  

    [bill@billstone make_lib]$ ./main  

    This is the first lib src!  

    This is the second src lib!  

    [bill@billstone make_lib]$  

     

    动态库的使用

    编写动态库  

    (1)设计库代码  

    [bill@billstone make_lib]$ cat pr1.c  

    int p = 2;  

    void print(){  

                    printf("This is the first dll src!\n");  

    }  

    [bill@billstone make_lib]$    

    (2)生成动态库  

    [bill@billstone make_lib]$ gcc -O -fpic -shared -o dl.so pr1.c  

    [bill@billstone make_lib]$ ls -l *.so  

    -rwxrwxr-x        1 bill          bill                  6592    4 月  15 15:19 dl.so  

    [bill@billstone make_lib]$  

    动态库的隐式调用  

      在编译调用库函数代码时指明动态库的位置及名字,  看下面实例  

    [bill@billstone make_lib]$ cat main.c  

    int main()  

    {  

                    print();  

                    return 0;  

    }  

    [bill@billstone make_lib]$ gcc -o tdl main.c ./dl.so  

    [bill@billstone make_lib]$ ./tdl  

    This is the first dll src!  

    [bill@billstone make_lib]$  

    当动态库的位置活名字发生改变时,  程序将无法正常运行;  而动态库取代静态库的好处之一则是通过更新动态库而随时升级库的内容.  

    动态库的显式调用  

      显式调用动态库需要四个函数的支持,  函数 dlopen 打开动态库,  函数 dlsym 获取动态库中对象基址,  函数 dlerror 获取显式动态库操作中的错误信息,  函数 doclose 关闭动态库

    [bill@billstone make_lib]$ cat main.c  

    #include <dlfcn.h>  

    int main()  

    {  

                    void *pHandle;  

                    void (*pFunc)();                                                    //  指向函数的指针  

                    int *p;  

                    pHandle = dlopen("./d1.so", RTLD_NOW);                  //  打开动态库  

                    if(!pHandle){  

                                    printf("Can't find d1.so \n");  

                                    exit(1);  

                    }  

                    pFunc = (void (*)())dlsym(pHandle, "print");                //  获取库函数 print 的地址  

                    if(pFunc)  

                                    pFunc();  

                    else  

                                    printf("Can't find function print\n");  

                    p = (int *)dlsym(pHandle, "p");                                      //  获取库变量 的地址  

                    if(p)  

                                    printf("p = %d\n", *p);  

                    else  

                                    printf("Can't find int p\n");  

                    dlclose(pHandle);                                                                //  关闭动态库  

                    return 0;  

    }  

    [bill@billstone make_lib]$ gcc -o tds main.c –ld1 –L. 

    此时还不能立即./tds,因为在动态函数库使用时,会查找/usr/lib/lib目录下的动态函数库,而此时我们生成的库不在里边。 这个时候有好几种方法可以让他成功运行: 最直接最简单的方法就是把libstr_out.so拉到/usr/lib/lib中去。 还有一种方法 export LD_LIBRARY_PATH=$(pwd) 另外还可以在/etc/ld.so.conf文件里加入我们生成的库的目录,然后/sbin/ldconfig。 /etc/ld.so.conf是非常重要的一个目录,里面存放的是链接器和加载器搜索共享库时要检查的目录,默认是从/usr/lib /lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig 。另外还有个文件需要了解/etc/ld.so.cache,里面保存了常用的动态函数库,且会先把他们加载到内存中,因为内存的访问速度远远大于硬盘的访问速度,这样可以提高软件加载动态函数库的速度了。

     

    库依赖的查看

    使用ldd命令来查看执行文件依赖于哪些库。

    该命令用于判断某个可执行的 binary 档案含有什么动态函式库。

    [root@test root]# ldd [-vdr] [filename]

    参数说明:

    --version  打印ldd的版本号

    -v --verbose  打印所有信息,例如包括符号的版本信息

  • hex格式介绍及转bin格式的源程序2(转帖)

    2011-02-11 17:21:45

    上接:hex格式介绍及转bin格式的源程序1(转帖)

     

    int _tmain(int argc, _TCHAR* argv[])

    {

         char fileName[100];

         char data[2];

         BYTE *outBuf;

         FILE *myFile;

         int len;

         int i;

         BYTE adressHigh;

         BYTE adressLow;

         BYTE dataLen;

         BYTE dataType;

         BYTE byteData;

         int totalLen;

         totalLen = 0;

         len = 0;

         adressHigh = 0;

         adressLow = 0;

         dataLen = 0;

         dataType = 0;

         printf("请输入HEX格式文件名:");

         scanf_s("%s",fileName);

         printf("\n");

         if (fopen_s(&myFile,fileName,"r") != 0)

         {

             printf("打开文件%s失败!",fileName);

         }

         //将文件长度计算出来用于申请存储数据的缓冲区

         while (!feof(myFile))

         {

             ++len;

             fgetc(myFile);

         }

         rewind(myFile);

         //因为是每两个字符表示一个字节,所以最大的数据个数要少于文件字符个数的一半

         outBuf = (BYTE*)malloc(len/2);

         memset(outBuf,0xff,len/2);

         while (!feof(myFile))

         {

             //:号表示一行的开始

             if (fgetc(myFile) == ':')

             {

                  //一行的头两个字符表示该行包含的数据长度

                  data[0] = fgetc(myFile);

                  data[1] = fgetc(myFile);

                  CharToByte(data,&dataLen);

                  //一行的第、个字符表示数据存储起始地址的高位

                  data[0] = fgetc(myFile);

                  data[1] = fgetc(myFile);

                  CharToByte(data,&adressHigh);

                  //一行的第、个字符表示数据存储起始地址的低位

                  data[0] = fgetc(myFile);

                  data[1] = fgetc(myFile);

                  CharToByte(data,&adressLow);

                  //一行的第、个字符表示数据类型

                  data[0] = fgetc(myFile);

                  data[1] = fgetc(myFile);

                  CharToByte(data,&dataType);

                  //当数据类型为时,表示本行包含的是普通数据记录

                  if (dataType == 0x00)

                  {

                       for (i=0;i<dataLen;i++)

                       {

                           data[0] = fgetc(myFile);

                           data[1] = fgetc(myFile);

                           CharToByte(data,&byteData);

                           outBuf[adressHigh*256+adressLow+i] = byteData;

                       }

                       totalLen += dataLen;

                  }

                  //当数据类型为时,表示到了最后一行

                  if (dataType == 0x01)

                  {

                       printf("文件结束记录!");

                  }

                  //当数据类型为时,表示本行包含的是扩展段地址记录

                  if (dataType == 0x02)

                  {

                       printf("不支持扩展段地址记录!");

                       return 0;

                  }

                  //当数据类型为时,表示本行包含的是扩展线性地址记录

                  if (dataType == 0x04)

                  {

                       printf("不支持扩展线性地址记录!");

                       return 0;

                  }

             }

         }

         fclose(myFile);

         printf("请输入保存的BIN格式文件名:");

         scanf_s("%s",fileName);

         if (fopen_s(&myFile,fileName,"w") != 0)

         {

             printf("打开文件%s失败!",fileName);

         }

         for (i=0;i<totalLen;i++)

         {

             fputc(outBuf[i],myFile);

         }

         return 0;

    }

  • hex格式介绍及转bin格式的源程序1(转帖)

    2011-02-11 17:14:34

    最近在写一个编程器,遇到hex格式文件转换为bin格式文件的问题,通过查阅各类资料,对该格式有了了解。所以在此介绍一下hex格式,并将自己的程序思路写下来,供大家探讨一下。

           Intel HEX文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录,由十六进制数组成的机器码或者数据常量。Intel HEX文件经常被用于将程序或数据传输存储到ROMEPROM,大多数编程器和模拟器使用Intel HEX文件。

           很多编译器的支持生成HEX格式的烧录文件,尤其是Keil c。但是编程器能够下载的往往是BIN格式,因此HEXBIN是每个编程器都必须支持的功能。

           HEX格式文件以行为单位,每行由“:”(0x3a)开始,以回车键结束(0x0d,0x0a)。行内的数据都是由两个字符表示一个16进制字节,比如01”就表示数0x010a,就表示0x0a。对于16位的地址,则高位在前低位在后,比如地址0x010a,在HEX格式文件中就表示为字符串010a。下面为HEX文件中的一行:

    :10000000FF0462FF051EFF0A93FF0572FF0A93FFBC

           “:”表示一行的开始。

           “:”后的第12个字符“10表示本行包含的数据的长度,这里就是0x1016个。

           3456个字符“0000表示数据存储的起始地址,这里表示从0x0000地址开始存储16个数据,其中高位地址在前,低位地址在后。

           78个字符“00表示数据的类型。该类型总共有以下几种:

    00 ----数据记录      
    01 ----
    文件结束记录
    02 ----
    扩展段地址记录
    04 ----
    扩展线性地址记录

    这里就是0x00即为普通数据记录。

    自后的32个字符就是本行包含的数据,每两个字符表示一个字节数据,总共有16个字节数据跟行首的记录的长度相一致。

    最后两个字符表示校验码。

    每个HEX格式的最后一行都是固定为:

    :00000001FF

           以上的信息其实就足够进行HEXBIN格式的程序的编写。首先我们只处理数据类型为0x000x01的情况。0x02表示对应的存储地址超过了64K,由于我的编程器只针对64K以下的单片机,因此在次不处理,0x04也是如此。

           我的编程思路是从文件中一个一个读出字符,根据“:”判断一行的开始,然后每两个字符转换成一个字节,并解释其对应的意义。然后将数据从该行中剥离出来保存到缓冲区中,并最终输出到文件中。

           具体程序如下,该程序在VC2005下采用控制台项目编译,需要在release下编译,在debug模式中会提示一个dll文件无法找到,这可能是VC自身的错误。

    // hextobin.cpp : 定义控制台应用程序的入口点。

    //

     

    #include "stdafx.h"

    #include <malloc.h>

    #include <memory.h>

    typedef unsigned char BYTE;

     

    //将两个字符转化为一个字节量

    void CharToByte(char* pChar,BYTE* pByte)

    {

         char h,l;

         h=pChar[0];//高位

         l=pChar[1];//低位

         if(l>='0'&&l<='9')

             l=l-'0';

         else if(l>='a' && l<='f')

             l=l-'a'+0xa;

         else if(l>='A' && l<='F')

             l=l-'A'+0xa;

         if(h>='0'&&h<='9')

             h=h-'0';

         else if(h>='a' && h<='f')

             h=h-'a'+0xa;

         else if(h>='A' &&h <='F')

             h=h-'A'+0xa;

         *pByte=(BYTE)h*16+l;

    }

     

    余下内容见:hex格式介绍及转bin格式的源程序2(转帖)
  • 运行MFC程序提示没有找到MFC42D.DLL文件的解决方法

    2011-02-11 15:12:27

        运行MFC AppWizard(exe)程序,汇编成功,可是运行时,出现错误:“没有找到MFC42D.DLL,因此这个应用程序未能启动.重新安装应用程序可能会修复此问题. ”
        解决方案为:出现上述提示的原因是默认情况下MFC程序是使用的动态联编方式,这种情况下在对方机器中没有安装VC++程序的情况下就会出现这个错误提示。解决的方法很简单,就是编译的时候采用静态联编的方式,也就是说将用到的dll文件编译到程序中。
        具体操作方法:Project -> Settings… 在General标签下面的Microsoft Foundation Class下面选择Use MFC in a Static Library即可。

    疑问:   
      1:Use   MFC   in   a   Static   Library和Use   MFC   in   a   Shared   DLL这两个选项有什么区别.?  
      2:MFC42D.DLL这个文件是干什么用的?  

      1.Use   MFC   in   a   Static   Library,在静态库中使用MFC,这样发行时就不需要MFC的DLL,否则,发行时需要一并发生MFC的动态库。  
      2.MFC42D.DLL是4.2版的MFC的DLL。

  • MFC编程学习之2:界面中添加RichEdit后界面无法弹出问题

    2011-01-13 10:39:52

    这简直就是我学习过程中的一超级大难题,折腾了两天,我都准备放弃了,终于发现原因了。

    在界面中添加RichEdit控件后,之所以不显示,是少了一个初始化的过程

    找到工程中:InitInstance()
    在他的第一句話中加入
    AfxInitRichEdit();

    重新编译运行,OK,解决!!

    感觉自己真是一超级大菜鸟啊!学习,学习…………

  • MFC编程学习之1补充:CComboBoxEx中不能使用AddString(转帖)

    2011-01-13 10:36:12

    CComboBoxEx中不能使用AddString

    工具栏中使用了CComboBoxEx控件,但是一调用AddString就出错,花了N多的时间,原来是CComboBoxEx不能使用AddString。很初级的问题,不过为避免更多人走这个弯路,所以在这里稍微提一下.CComboBoxEx用法如下:
       COMBOBOXEXITEM   Item;
       Item.mask   =   CBEIF_TEXT   ;
       Item.pszText   =   _T("Text Sample");
       Item.iItem   =   0;//index
       m_comboboxex.InsertItem(&Item);

    组合窗口是由一个输入框和一个列表框组成。创建一个组合窗口可以使用成员函数:
    BOOL CListBox::Create( LPCTSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff );
    其中dwStyle将指明该窗口的风格,除了子窗口常用的风格WS_CHILD,WS_VISIBLE外,你可以针对列表控件指明专门的风格。

    CBS_DROPDOWN 下拉式组合框
    CBS_DROPDOWNLIST 下拉式组合框,但是输入框内不能进行输入
    CBS_SIMPLE 输入框和列表框同时被显示
    LBS_SORT 所有的行按照字母顺序进行排序

    由于组合框内包含了列表框,所以列表框的功能都能够使用,如可以利用:
    int AddString( LPCTSTR lpszItem )添加行,
    int DeleteString( UINT nIndex )删除指定行,
    int InsertString( int nIndex, LPCTSTR lpszItem )将行插入到指定位置。
    void ResetContent( )可以删除列表框中所有行。
    通过调用int GetCount( )得到当前列表框中行的数量。

    如果需要得到/设置当前被选中的行的位置,可以调用int GetCurSel( )/int SetCurSel(int iIndex)。通过调用int GetLBText( int nIndex, LPTSTR lpszText )得到列表框内指定行的字符串。

    此外通过调用int FindString( int nStartAfter, LPCTSTR lpszItem )可以在当前所有行中查找指定的字符传的位置,nStartAfter指明从那一行开始进行查找。
    int SelectString( int nStartAfter, LPCTSTR lpszItem )可以选中包含指定字符串的行。

    此外输入框的功能都能够使用,如可以利用:
    DWORD GetEditSel( ) /BOOL SetEditSel( int nStartChar, int nEndChar )得到或设置输入框中被选中的字符位置。
    BOOL LimitText( int nMaxChars )设置输入框中可输入的最大字符数。
    输入框的剪贴板功能Copy,Clear,Cut,Paste动可以使用。

    最后介绍一下列表框几种常用的消息映射宏:

    ON_CBN_DBLCLK 鼠标双击
    ON_CBN_DROPDOWN 列表框被弹出
    ON_CBN_KILLFOCUS / ON_CBN_SETFOCUS 在输入框失去/得到输入焦点时产生
    ON_CBN_SELCHANGE 列表框中选择的行发生改变
    ON_CBN_EDITUPDATE 输入框中内容被更新
    使用以上几种消息映射的方法为定义原型如:afx_msg void memberFxn( );的函数,并且定义形式如ON_Notification( id, memberFxn )的消息映射。如果在对话框中使用组合框,Class Wizard会自动列出相关的消息,并能自动产生消息映射代码。

    在MFC 4.2中对组合框进行了增强,你可以在组合框中使用ImageList,有一个新的类CComboBoxEx(由CComboBox派生)来实现这一功能。在CComboBoxEx类中添加了一些新的成员函数来实现新的功能:首先你需要调用
    CImageList* SetImageList( CImageList* pImageList );来设置ImageList,然后调用
    int InsertItem( const COMBOBOXEXITEM* pCBItem );来添加行,其中COMBOBOXEXITEM定义如下:

    typedef struct
    {
    UINT mask;
    int iItem;
    LPTSTR pszText;
    int cchTextMax;
    int iImage;
    int iSelectedImage;
    int iOverlay;
    int iIndent;
    LPARAM lParam;
    } COMBOBOXEXITEM, *PCOMBOBOXEXITEM;

    你需要设置mask=CBEIF_IMAGE|CBEIF_TEXT,并设置iItem为插入位置,设置pszText为显示字符串,设置iImage为显示的图标索引。下面的代码演示了如何进行插入:
    /*m_cbeWnd 为已经创建的CComboBox对象
    m_list 为CImageList对象IDB_IMG 为16*(16*4)的位图,每个图片为16*16共4个图标*/
    m_list.Create(IDB_IMG,16,4,RGB(0,0,0));
    m_cbeWnd.SetImageList(&m_list);

    COMBOBOXEXITEM insItem;
    insItem.mask=CBEIF_IMAGE|CBEIF_TEXT;
    insItem.iItem=0;
    insItem.iImage=0;
    insItem.pszText="Line 1";
    m_cbeWnd.InsertItem(&insItem);
    insItem.iItem=1;
    insItem.iImage=1;
    insItem.pszText="Line 2";
    m_cbeWnd.InsertItem(&insItem);

    通过调用int DeleteItem( int iIndex );来删除行,并指明行的位置。
    通过调用BOOL GetItem( COMBOBOXEXITEM* pCBItem )/BOOL SetItem( const COMBOBOXEXITEM* pCBItem );来得到/设置行数据。

    为了CComboBoxEx显示问题,差点没把我折腾死,终于找到原因了。

     

    PS:再补充用到的两个函数

    BOOL SetItemText(int nItem,int nSubItem,LPTSTR lpszText)

    返回值:如果成功,则返回非零值,否则为0。

    参数:

    nItem 要设定文本项的索引值。 
    nSubItem 子项的索引,若为零,则设置项标签。 
    lpszText 指向包含新项文本字符串的指针。 

    说明:改变列表视图项或子项的文本。


    CListCtrl::InsertItem

    int InsertItem(const LVITEM* pItem)
    int InsertItem(int nItem,LPCTSTR lpszItem)
    int InsertItem(int nItem, LPCTSTR lpszItem,int nImage)
    int InsertItem(UINT nMask,
                   int nItem,
                   LPCTSTR lpszItem,
                   UINT nState,
                   UINT nStateMask,
                   int nImage,
                   LPARAM lParam
                  )

    返回值:
    如果成功,则返回新建列的索引值,否则为-1。

    参数:

    pItem 指向指定项属性LVITEM结构的指针,如联机文档“平台SDK”中所述。 
    nItem 被插入项的索引值。 
    lpszItem 包含项标签的字符串的地址,或当项为回调项时,该变量为LPSTR_TEXT CALLBACK。要了解更多有关回调项的信息,请参阅CListCtrl::GetCall backMask. 
    nImage 项图象的索引值,或当项为回调项时,该变量为I_IMAGECALLBACK。要了解更多有关回调项的信息,请参阅CListCtrl::GetCallbackMask 
    nMask 参数nMask指定了哪个项属性作为参数传递是有效的。它可以是联机文档“平台SDK” 中LVITEM结构所描述的一个或多个掩码值。有效的数据能够通过位与运算来组合。 
    nState 指示项的状态、状态图象及轮廓图象。请参阅联机文档“平台SDK”中的LVITEM来获取更多信息,并参阅有效标志列表中的列表视图项状态。 
    nStateMask 指示状态成员中的哪一位将被获取或修改。请参阅联机文档“平台SDK”中的LVITEM来获取更多信息。 
    nImage 图象列表之内项的图象的索引。 
    lParam 与项相关联的应用指定的32位值。如果该参数被指定,那么必须设置nMask的属性为LVIF_PARAM。 

    说明:向列表视图控件中新插入一项。

  • MFC编程学习之1:combo box若干使用技巧--VC

    2011-01-13 10:33:22

    1、combo box的"Data"属性添加多行数据的方法:Ctrl + Enter ;

     

    2、combo box下拉列表无法显示的问题:

       combo box下拉列表无法显示的原因是:我们没有设置“下拉窗口”的大小。

       设置“下拉窗口”大小的方法:点击Combo Box的“向下箭头”,就会显示下拉列表的大小,这时你可以调节。

     

    3、清空元素的方法:每次删除第一个元素
    int nCount = ctrComBox.GetCount();
    for(; nCount>0; nCount--)
      ctrComBox.DeleteString(0);

     

    4、在输入时自动显示下拉列表:

    //添加combo box的消息响应:CBN_EDITCHANGE、CBN_DROPDOWN

    void CcombofixDlg::OnEditChangeComboMain()

    {

            m_cbxMain.ShowDropDown();

    }

    void CCombofixDlg::OnDropdownCombomain()
    {
            SendMessage(WM_SETCURSOR,0,0);       
    }

  • C/S架构的性能测试(转)

    2010-03-30 10:25:42

    很多人关心LR在C/S架构上如何实施性能测试,我想根本原因在于两个方面,一是很多时候脚本无法录制,即LR无法成功调用被测的应用程序,二是测试脚本即使录制下来,可读性不强,往往不能运行通过,调试时无从下手,像音视频、电子地图类的测试差不多也是这个问题。

      根据我以往的项目经验,LR是可以做到的,因为它提供了Windows Sockets协议,解决方案实施起来简单但需要足够的细心以及一定的判断力、想象力,可参考如下步骤进行:

      1、通过抓包工具捕捉客户端与服务器之间的所有通讯。

      关键点:IP过滤,端口过滤,报文类型过滤

      目的:弄清楚业务操作过程中,客户端向服务器提交的请求原型,以及服务器对我们请求所做的正确响应

      2、将过滤后的报文整理成测试脚本。

      关键点:Socket的建立与关闭,send buf的整理,receive buf的整理

      目的:将抓包获得的报文转成LR测试脚本(提示:选取合适的抓包工具,使得报文能被保存成文档格式;开发小工具,通过报文中的各个关键字抽取报文中 Data Area中的部分作为buf 区的内容,根据IP字段,端口号等特征完成lrs_send,lrs_receive语句的填写。这部分看上去挺难,但只要对报文做好分析,把握规律,编程的事随便拉个开发都可以轻松搞定)

      3、调试脚本

      关键点:定位错误,添加校验点

      目的:使脚本真正可以拿来进行压力测试

      这是最难的一个环节,耐心、细心、判断力都体现在此处。每个人处理问题的方式的不同,我只能提供自己的一点经验。

      将脚本RUN-TIME SETTINGS中的扩展日志全部打上钩,并且将脚本拿到controller中单用户执行,注意设置好日志路径。

      脚本出错后,用EDIT PLUS或其他的文本工具打开log,找到出错行,然后向上逐一对比服务器返回的数据与录制过程中抓包获得的报文。

      在这里,我用了一个小技巧,生成buf内容时,使buf的编号与该buf在抓包获得的报文中编号保持一致,比较起来很方便。

      如果服务器返回的buf与抓包时的原始数据一致,自然表示该步骤回放成功,如果不一样,则需要具体情况具体对待。就我的经验来说,往往是因为数据唯一性问题或者是关联的问题造成某一步骤返回的BUF为0或-1,从而导致最终脚本失败。

      找到第一个出错的地方后,参数化,关联等手段都可以用上了,这里可能需要重复两次抓包过程,先行比较自己发送的报文是否有区别。

      总体思路便是如此,写了一堆,也不知道对大家是否有帮助,对于此类问题,网络上的协助很难派上用场,事情还是要在现场才有可能得到解决啊。本来有意将这东西工具化,甚至产品化,但几个项目实施下来发现变数较多,特别是最后一个环节,完全依赖于测试工程师的自身能力,只好就此作罢。

    对C/S架构下的软件性能测试依然在摸索中,故借鉴一下别人的总结经验,谢谢那个作者了。

  • 常用的网站功能测试方法和GUI基本测试内容(转载)

    2010-03-26 17:32:36

    网站功能测试就是对产品的各功能进行验证,根据功能测试用例,逐项测试,检查产品是否达到用户要求的功能。常用的测试方法如下:

     

    1、页面链接检查: 每一个链接是否都有对应的页面,并且页面之间切换工具,如LinkBotProFile-AIDCSHTML Link ValidaterXenu等工具。LinkBotPro不支持中文,中文字符显示为乱码;HTML Link Validater只能测试以Html或者htm结尾的网页链接;Xenu无需安装,支持aspdojsp等结尾的网页,同时能够生成html格式的测试报告。

     

    2、相关性检查:删除/增加一项会不会对其他项产生影响,如果产生影响,这些影响是否都正确检查按钮的功能是否正确 如新建、编辑、删除、关闭、返回、保存、导入等功能是否正确。

     

    3、字符类型检查:在应该输入指定类型的内容的地方输入其他类型的内容(如在应该输入整型的地方输入其他字符类型),看系统是否检查字符类型。

     

    1)标点符号检查:输入内容包括各种标点符号,特别是空格,各种引号,回车键。看系统处理是否正确。

     

    2)特殊字符检查:输入特殊符号,如@#$%!等,看系统处理是否正确。

     

    3)字符串长度检查: 输入超出需求所说明的字符串长度的内容, 看系统是否检查字符串长度。

     

    4、中文字符处理:在可以输入中、英文的系统输入中文,看会否出现乱码或出错。

     

    检查信息的完整性 在查看信息和更新信息时,查看所填写的信息是不是全部更新,更新信息和添加信息是否一致。

     

    5、信息重复:在一些需要命名,且名字应该唯一的信息输入重复的名字或ID,看系统有没有处理,会否报错,重名包括是否区分大小写,以及在输入内容的前后输入空格,系统是否作出正确处理。

     

    6、检查删除功能:在一些可以一次删除多个信息的地方,不选择任何信息,按“delete,看系统如何处理,会否出错;然后选择一个和多个信息,进行删除,看是否正确处理。

     

    7、检查添加和修改是否一致:检查添加和修改信息的要求是否一致,例如添加要求必填的项,修改也应该必填;添加规定为整型的项,修改也必须为整型

     

    8、检查修改重名:修改时把不能重名的项改为已存在的内容,看会否处理,报错.同时,也要注意,会不会报和自己重名的错

     

    9、重复提交表单:一条已经成功提交的纪录,返回后再提交,看看系统是否做了处理。对于Web系统检查多次使用返回键的情况   在有返回键的地方,返回到原来页面,重复多次,看会否出错

     

    10、搜索检查:有搜索功能的地方输入系统存在和不存在的内容,看搜索结果是否正确.如果可以输入多个搜索条件,可以同时添加合理和不合理的条件,看系统处理是否正确。

     

    11、输入信息位置:注意在光标停留的地方输入信息时,光标和所输入的信息会否跳到别的地方。

     

    12、上传下载文件检查:上传下载文件的功能是否实现,上传文件是否能打开。对上传文件的格式有何规定,系统是否有解释信息,并检查系统是否能够做到。下载文件能否打开或者保存,下载的文件是否有格式要求,如需要特殊工具才可以打开等。

     

    13、必填项检查:应该填写的项没有填写时系统是否都做了处理,对必填项是否有提示信息,如在必填项前加“*”;对必填项提示返回后,焦点是否会自动定位到必填项。

     

    14、快捷键检查:是否支持常用快捷键,如Ctrl+C Ctrl+V Backspace等,对一些不允许输入信息的字段,如选人,选日期对快捷方式是否也做了限制。

     

    15、回车键检查:在输入结束后直接按回车键,看系统处理如何,会否报错。

     

    16、刷新键检查:在Web系统中,使用浏览器的刷新键,看系统处理如何,会否报错。  

     

    17、回退键检查:在Web系统中,使用浏览器的回退键,看系统处理如何,会否报错。对于需要用户验证的系统,在退出登录后,使用回退键,看系统处理如何;多次使用回退键,多次使用前进键,看系统如何处理。

     

    18、直接URL链接检查:在Web系统中,直接输入各功能页面的URL地址,看系统如何处理,对于需要用户验证的系统更为重要。

     

    19、空格检查:在输入信息项中,输入一个或连串空格,查看系统如何处理。如对于要求输入整型、符点型变量的项中,输入空格,既不是空值,又不是标准输入。

     

    20、输入法半角全角检查:在输入信息项中,输入半角或全角的信息,查看系统如何处理。如对于要求输入符点型数据的项中,输入全角的小数点(“。”或“.”,如4.5);输入全角的空格等。

     

    21、密码检查:一些系统的加密方法采用对字符Ascii码移位的方式,处理密码加密相对较为简单,且安全性较高,对于局域网系统来说,此种方式完全可以起到加密的作用,但同时,会造成一些问题,即大于128Ascii对应的字符在解密时无法解析,尝试使用“uvwxyz”等一些码值较大的字符作为密码,同时,密码尽可能的长,如17位密码等,造成加密后的密码出现无法解析的字符。

     

    22、用户检查:任何一个系统,都有各类不同的用户,同样具有一个或多个管理员用户,检查各个管理员之间是否可以相互管理,编辑、删除管理员用户。同时,对于一般用户,尝试删除,并重建同名的用户,检查该用户其它信息是否重现。同样,提供注销功能的系统,此用户再次注册时,是否作为一个新的用户。

     

    23、系统数据检查:这是功能测试最重要的,如果系统数据计算不正确,那么功能测试肯定是通不过的。数据检查根据不同的系统,方法不同。对于业务管理平台,数据随业务过程、状态的变化保持正确,不能因为某个过程出现垃圾数据,也不能因为某个过程而丢失数据。

     

    24、系统可恢复性检查:以各种方式把系统搞瘫,测试系统是否可正常迅速恢复。

     

     

     

                                      GUI基本测试内容

     

    图形用户界面( GUI )对软件测试提出了有趣的挑战,因为 GUI 开发环境有可复用的构件,开发用户界面更加省时而且更加精确。同时, GUI 的复杂性也增加了,从而加大了设计和执行测试用例的难度。因为现在 GUI 设计和实现有了越来越多的类似,所以也就产生了一系列的测试标准。下列问题可以作为常见 GUI 测试的指南:

     

    窗口:

    · 窗口是否基于相关的输入和菜单命令适当地打开?

    · 窗口能否改变大小、移动和滚动?

    · 窗口中的数据内容能否用鼠标、功能键、方向键和键盘访问?

    · 当被覆盖并重新调用后,窗口能否正确地再生?

    · 需要时能否使用所有窗口相关的功能?

    · 所有窗口相关的功能是可操作的吗?

    · 是否有相关的下拉式菜单、工具条、滚动条、对话框、按钮、图标和其他控制可为窗口使用,并适当地显示?

    · 显示多个窗口时,窗口的名称是否被适当地表示?

    · 活动窗口是否被适当地加亮?

    · 如果使用多任务,是否所有的窗口被实时更新?

    · 多次或不正确按鼠标是否会导致无法预料的副作用?

    · 窗口的声音和颜色提示和窗口的操作顺序是否符合需求?

    · 窗口是否正确地被关闭?

     

    下拉式菜单和鼠标操作:

    · 菜单条是否显示在合适的语境中?

    · 应用程序的菜单条是否显示系统相关的特性(如时钟显示)?

    · 下拉式操作能正确工作吗?

    · 菜单、调色板和工具条是否工作正确?

    · 是否适当地列出了所有的菜单功能和下拉式子功能?

    · 是否可以通过鼠标访问所有的菜单功能?

    · 文本字体、大小和格式是否正确?

    · 是否能够用其他的文本命令激活每个菜单功能?

    · 菜单功能是否随当前的窗口操作加亮或变灰?

    · 菜单功能是否正确执行?

    · 菜单功能的名字是否具有自解释性?

    · 菜单项是否有帮助,是否语境相关?

    · 在整个交互式语境中,是否可以识别鼠标操作?

    · 如果要求多次点击鼠标,是否能够在语境中正确识别?

    · 光标、处理指示器和识别指针是否随操作恰当地改变?

     

    数据项:

    · 字母数字数据项是否能够正确回显,并输入到系统中?

    · 图形模式的数据项(如滚动条)是否正常工作?

    · 是否能够识别非法数据?

    · 数据输入消息是否可理解?

     

     

    谢谢晓蕾LUCKY,总结的很全面,转过来了!

  • 安装LR8.1成功步骤

    2010-01-26 09:32:03

    昨天装了一整天的loadrounner8.1版本,因为一开始用的不是自己装的,没想到loadrounner从卸载到重新安装如此的麻烦

    现在记录一下成功安装的步骤吧:

    1.setup.exe安装,直至需要填写序列号处,会有个默认的8888-88888888之类的,不用修改,直接点击next;

    2.安装最后让你重新启动,也暂时不要重新启动,把破解文件 lm70.dll,mlr5lprg.dll

    4h.A Hs1VN Ce242309这两个文件复制并粘贴到LR8.1安装目录下的bin文件夹下,一般是C:\Program Files\Mercury\LoadRunner\bin;

    3.重新启动系统,启动LR,菜单项“CONFIGURATION”-->“LoadRunner License”下选中“LicenseKey1”,点击“New License”输入7.8、8.0通用的license:51Testing软件测试网\,OQ7{b

    golba-100: AEAMAUIK-YAFEKEKJJKEEA-BCJGI

    .NT7TP6e1[VU3pG242309web-10000: AEABEXFR-YTIEKEKJJMFKEKEKWBRAUNQJU-KBYGB(我输入的是这个)即可

    上面两个license,第一个是100个用户(无时间限制),第二个是10000个用户(有时间限制)。

    如果是卸载后重新安装loadrounner,记得千万要卸干净,要不然license无法填入。

    昨天安装好以后出现录制脚本0 events的现象,不过修改IE的高级选项,取消选中“启用第三方浏览器扩展*”(我用的是IE8,应该每个版本的描述都差不多)可以了。但是今天一来一用又那样了,真搞不清楚是怎么回事?看来今天又要重新研究这个问题了,而且昨天录制了脚本还出现录制程序错误的提示,录完点击stop就异常退出了,也不清楚是什么问题?

    研究,研究,继续研究中....

    (有个高手就好了....)

  • 卸载LR8.1

    2010-01-25 12:01:40

    一直认为LR只有重装系统才能在装,每次装LR都要求自己只许成功,不许失败,下面的方法是我转来的,非常受用,适合新手,呵呵。

     

     

    一、卸载LR8.1程序
    1.
    保证所有LoadRunner的相关进程(包括ControllerVuGenAnalysisAgent Process)全部关闭。


    2.
    操作系统控制面板的删除与添加程序中运行LoadRunner的卸载程序。

    3.删除整个LoadRunner目录。(包括Agent Process

    4.在搜索中查找下列文件,并且删除它们。
    1
    wlrun.*
    2
    vugen.*

    二、删除注册表(最重要的)
    1.
    运行注册表程序(开始- 运行- regedit

    2.删除下列键值。 
    HKEY_CLASSES_ROOT\Mercury.Lm70Control
    HKEY_CLASSES_ROOT\Mercury.Lm70Control.1

    同时删除
    Mercury.Lm70ControlMgr
    Mercury.Lm70ControlMgr.1
    一定要多查找几遍,发现Lm70Contro字样的东西都要删除掉!

    3.最后删除下面内容:
    HKEY_CURRENT_USER\Software\Mercury Interactive\LoadRunner
    HKEY_LOCAL_MACHINE\SOFTWARE\Mercury Interactive\LoadRunner

        这些步骤都走了一遍,确定注册表里没有那些关键字以后,重启一下电脑,开始安装LR9.0!!
        我的解压过程没有遇到其他网友说的问题,直接双击运行,一直顺利通过!


    loadrunner9.0
    破解方法

    1、过程和方法:
    打开Loadrunner,发现以下几个dll可能和注册有关,mlr5lprg.dlllicensebundles.dlllm50.dlllm70.dll
    如果熟悉LR的朋友,LR7.88.08.1中都没有Licensebundles.dll,这是一个新的综合捆绑dll,所以我在之前的一些朋友的帖子里说破解难度大,也是这个原因。
    但是万幸的是,我在LR8.1.4.0中发现了licensebundles.dll,也就是LR8.1打上FP4补丁,并且用我以前的针对LR8.1的办法有效,因此,LR9.0的破解方案也就很快出现:
    a
    、用LR8.1.4.0中的lm50.dlllicensebundles.dll覆盖LR9.0安装目录下
    bin文件夹中的对应文件;
    b
    、用LR8.0中的mlr5lprg.dlllm70.dll覆盖LR9.0安装目录下
    bin文件夹中的对应文件;
    c
    、然后使用老的注册码就可以使用了;
    d
    golba-100: AEAMAUIK-YAFEKEKJJKEEA-BCJGI
          web-10000: AEABEXFR-YTIEKEKJJMFKEKEKWBRAUNQJU-KBYGB

    2、遇到的问题
    在破解的过程中我还遇到了个问题,就是通过上述的方法注册时提示
    License security violation……”,无法注册,后通过针对LR注册表删除的工具运行后再注册就通过了。


    (这个问题我也没有遇到,直接输入了License就可以了)

        安装完毕后,通过简单录制查看安装是不是真的成功,就在这时问题出现了!
    1.LR
    打开IEIE不自动出来
    2.
    LR打开的IE中访问不到服务,并且服务正常

    还好,在网上搜索到了云层老师的博客,里面正好有这方面的解决方法:
    1.
    这个问题还是IE的,找到IE的高级选项,里面有个第三方扩展支持,去掉就行了
    2.
    这个问题是LR8.x系列会篡改IE的代理设置,关闭LR,打开IE中的选项,找到代理服务器,把最下面的对本地不使用代理服务器勾上,再把上面的使用代理服务器去掉,打开LR在录制选项中将代理设置为无。

    再次录制,OK,成功!!
  • 软件测试工具LoadRunner常见问题整理

    2010-01-21 10:55:52

    1.LoadRunner录制脚本时为什么不弹出IE浏览器?
      当一台主机上安装多个浏览器时,LoadRunner录制脚本经常遇到不能打开浏览器的情况,可以用下面的方法来解决

      启动浏览器,打开Internet选项对话框,切换到高级标签,去掉“启用第三方浏览器扩展(需要重启动)”的勾选,然后再次运行VuGen即可解决问题

      提示:通常安装Firefox等浏览器后,都会勾选上面得选项,导致不能正常录制。因此建议运行LoadRunner得主机上保持一个干净的测试环境。

      2.录制Web脚本时,生成的脚本中存在乱码该如何解决?

      录制脚本前,打开录制选项配置对话框Record-Options,进入到Advanced标签,先勾选“Support charset”,然后选择中支持UTF-8。再次录制,就不会出现中文乱码问题了。

      3.HTML-based script与URL-based script的脚本有什么区别?

      使用“HTML-based script”的模式录制脚本,VuGen为用户的每个HTML操作生成单独的步骤,这种脚本看上去比较直观;使用“URL-based script”模式录制脚本时,VuGen可以捕获所有作为用户操作结果而发送到服务器的HTTP请求,然后为用户的每个请求分别生成对应方法。

      通常,基于浏览器的Web应用会使用“HTML-based script”模式来录制脚本;而没有基于浏览器的Web应用、Web应用中包含了与服务器进行交互的Java Applet、基于浏览器的应用中包含了向服务器进行通信的JavaScript/VBScript代码、基于浏览器的应用中使用了HTTPS安全协议,这时使用“URL-based script”模式进行录制。

      4.为什么脚本中添加了检查方法Web-find,但是脚本回放时却没有执行?

      由于检查点功能会耗费一定的资源,因此LoadRunner默认关闭了对文本及图像的检查。要想开启检查功能,必须修改运行时的配置Run-time Setting。

      进入“Run-time Setting”对话框,依次进入“Internet Protocol→Preferences”,勾选Checks下的“Enable Image and text check”选项即可。

      检查执行结果时推荐使用web_reg_find方法。

      5.运行时的Pacing设置主要影响什么?

      Pacing主要用来设置重复迭代脚本的间隔时间。共有三种方法:上次迭代结束后立刻开始、上次迭代结束后等待固定时间、按固定或随机的时间间隔开始执行新的迭代。

      根据实际需要设置迭代即可。通常,没有时间间隔会产生更大的压力

      6.运行时设置Log标签中,如果没有勾选“Enable logging”,则手工消息可以发送吗?

      Enable logging选项仅影响自动日志记录和通过lr_log_message发送的消息。即使没有勾选,虚拟用户脚本中如果使用lr_message、lr_output_message、lr_error_message,仍然会记录其发出的消息。

      7.LoadRunner 8.0版本的VuGen在录制Web Services协议的脚本时一切正常,而回放时报出错误提示“Error:server returned an incorrectly formatted SOAP response”。这时说明原因引起的?

      造成这种情况的主要原因是LoadRunner 8.0的VuGen在录制Web Service协议的脚本时存在一个缺陷:如果服务器的操作系统是中文的,VuGen会自动将WSDL文件的头改为,因此会有上面的错误提示。

      解决方法:把“LR80WebservicesFPI_setup.exe”和“lrunner_web_sevices_path_1.exe”两个补丁打上即可解决。
     8.VuGen支持Netscape的客户证书吗?

      不支持。目前的VuGen 8.0版本中仅支持Internet Explorer的客户端证书。录制脚本时可以先从Netscape中导出所需的证书,然后将其导入到Internet Explorer中,并确保以相同的顺序导出和导入这些证书。而且,在每台将要录制或运行需要证书的Web Vuser脚本的计算机上都要重复执行前面的过程。

      9.VuGen会修改录制浏览器中的代理服务器设置吗?

      会修改。在开始录制基于浏览器的Web Vuser脚本时,VuGen首先会启动指定的浏览器。然后,VuGen会指示浏览器访问VuGen代理服务器。为此,VuGen会修改录制浏览器上的代 理服务器设置。默认情况下,VuGen会立即将代理服务器设置更改为Localhost:7777。录制之后,VuGen会将原始代理服务器设置还原到该 录制浏览器中。因此,在VuGen进行录制的过程中,不可以更改代理服务器设置,否则将无法正常进行。

       10.在LoadRunner脚本如何输出当前系统时间?

      LoadRunner提供了char *ctime(const time_t *time)函数,调用参数为一个Long型的整数指针,用于存放返回时间的数值表示。

      调用语句与返回值如下示例:

      
    1. typedef long time_t;

    2.   Action()

    3.   {

    4.   time_t t;

    5.   lr_message(“Time in seconds since 1/1/70: %ld\n”,time(&t));

    6.   lr_message(“System time and date: %s”,ctime(&t));

    7.   }
    复制代码
      输出结果为:

      Time in seconds since 1/1/70: 1185329968

      System time and date:Wed Jul 25 10:19:28 2007

      11.一些Web虚拟用户脚本录制后立刻回放没有任何问题,但是当设置迭代次数大于1时,如果进行回放则只能成功迭代一次。为什么从第二次迭代开始发生错误?

      这种现象多是由于在“Run-time Setting”的“Browse Emulation”的设置中,勾选了“Simulate a new user on each iteration”及其下面的选项“Clear cache on each iteration”这两个选项的含义是每次迭代时模拟一个新的用户及每次迭代时清除缓存。

      由于脚本迭代时,init和end只能执行一次,如果每次迭代都模拟一个新的用户并清除缓存,
    则用户登录信息将一并清除,因此迭代时可能会发生错误。

      12.虚拟客户脚本“Run-time Setting”中的线程和进程运行方式的区别?

      如果选择“Run Vuser as a process”,则场景运行时会为每一个虚拟用户创建一个进程;选择“Run Vuser as a thread”则将每个虚拟用户作为一个线程来运行,在任务管理器中只看到一个mmdrv.exe,这种方式的运行效率更高,能造成更大的压力,时默认选项。

      另外,如果启用了IP欺骗功能,则先在Controller中选中Tools菜单下的“Expert Mode”,然后将Tools菜单下的“Options>General”标签页中的IP地址分配方式也设置为与Vuser运行方式一致,同为线程或进程方式。

      13.在Controller中运行Web相关测试场景时,经常会有很多超时错误提示,如何处理这类问题?

      这主要有脚本的默认超时设置引起。当回放Web脚本时,有时候由于服务器响应时间较长,会产生超时的错误。这时需要修改脚本的运行时配置。

      进入“Run-time Setting”对话框后,依次进入“Internet Protocol→Preference”。然后点击“Options…”按钮,进入高级设置对话框,可以修改各类超时设置的默认值。

      14.为什么Windows系统中的CPU、内存等资源仍然充足,但是模拟的用户数量却上不去?

      在Windows计算机的标准设置下,操作系统的默认限制只能使用几百个Vuser,这个限制与CPU或内存无关,主要是操作系统本身规定了默认的最 大线程数所导致。要想突破Windows这个限制,须修改Windows注册表。以Windows XP Professional为例。

      (1)打开注册表后,进入注册表项HKEY_LOCAL_MACHINE中的下列关键字:System\CurrentControlSet\Control\Session Manager\SubSystems。

      (2)找到Windows关键字,Windows关键字如下所示:

      %SystemRoot%\system32\csrss.exe bjectDirectory=\Windows

      SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1

      ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2

      ProfileControl=Off MaxRequestThreads=16

      SharedSection=1024,3072,512关键字的格式为xxxx,yyyy,zzz。其中,xxxx定义了系统范围堆的最大值(以KB为单位),yyyy定义每个桌面堆得大小。

      (3)将yyyy的设置从3072更改为8192(即8MB),增加SharedSection参数值。

      通过对注册表的更改,系统将允许运行更多的线程,
    因而可以在计算机上运行更多的Vuser。这意味着能够模拟的最大并发用户数量将不受Windows操作系统的限制,而只受硬件和内部可伸缩性限制的约束。
  • BUG发现率及严重程度重定义

    2010-01-06 11:45:20

    1.BUG等级划分建议:

      目前project上的BUG严重程度分为五个等级,按照CMM5中定义的规范,BUG严重等级可分为3-5个等级,由于我们公司的CMM水平 还处于初级阶段,将BUG等级划分过细不符合我们当前的CMM水平,同时也不利于测试人员对BUG等级的精确划分。根据我们公司的情况,同时参照其它中小 公司的等级划分标准,建议将BUG等级划分四个等级,分别为致命、严重、一般、提示。

      ● 致命(可对应目前BUG体系中的“非常严重”):

      致命性问题主要为:系统无法执行、崩溃或严重资源不足、应用模块无法启动或异常退出、无法测试、造成系统不稳定。

      具体基本上可分为:

      ○ 严重花屏

      ○ 内存泄漏

      ○ 用户数据丢失或破坏

      ○ 系统崩溃/死机/冻结

      ○ 模块无法启动或异常退出

      ○ 严重的数值计算错误

      ○ 功能设计与需求严重不符

      ○ 其它导致无法测试的错误

      ● 严重(可对应目前BUG体系中的“严重”)

      严重性问题主要为:影响系统功能或操作,主要功能存在严重缺陷,但不会影响到系统稳定性。

      具体基本上可分为:

      ○ 功能未实现

      ○ 功能错误

      ○ 系统刷新错误

      ○ 语音或数据通讯错误

      ○ 轻微的数值计算错误

      ○ 系统所提供的功能或服务受明显的影响

      ● 一般(可对应于目前BUG体系中的“普通”)

      一般性问题主要为:界面、性能缺陷

      具体基本上可分为:

      ○ 操作界面错误(包括数据窗口内列名定义、含义是否一致)

      ○ 边界条件下错误

      ○ 提示信息错误(包括未给出信息、信息提示错误等)

      ○ 长时间操作无进度提示

      ○ 系统未优化(性能问题)

      ○ 光标跳转设置不好,鼠标(光标)定位错误

      ● 提示(可对应于目前BUG体系中的“轻微及建议”)

      提示性问题主要为:易用性及建议性问题

      具体基本上可分为:

      ○ 界面格式等不规范

      ○ 辅助说明描述不清楚

      ○ 操作时未给用户提示

      ○ 可输入区域和只读区域没有明显的区分标志

      ○ 个别不影响产品理解的错别字

      ○ 文字排列不整齐等一些小问题

      ○ 建议

      注意:对于结构及硬件问题,由于产品测试部仅是进行辅助测试,碰到此类问题时,均将于定位于等级“致命”,具体情况由结构及硬件部门相关人员确认。

    2.BUG发生率划分建议:

      目前通用的对BUG发生率的划分主要有两种划分方法:一种是测试发生率:即按照特定步骤执行多次的BUG重现率;另外一种是用户使用发生率:即 模拟用户在使用产品发生此问题的概率。第一种方法计量精确简单,可操作性高,但不太符合产品的实际使用情况。第二种方法,则需要推断用户使用某一业务的频 率,因此计量相对没有第一种精确,操作性高,但比较符合产品的实际使用情况。由于产品的最终使用总是用户,因此建议我司的BUG发生率采用第二种方法—— 即用户使用发生率。

      用户使用发生率=用户类别*业务类别*测试发生率

      ● 用户类别:

      我们公司的主要客户群有生产人员、客服人员、最终用户。根据其对公司产品的生产、销量、声誉、维护的不同可以分配不同的权重(权重范围为0-1之间)。

      如:生产人员——>0.3

      客服人员——>0.5

      最终用户——>1.0

      ● 业务类别:

      业务类别根据具体项目的业务情况分为主要业务、次要业务及辅助业务。

      业务类别的确认具有人为的主观因素,若需求文档有明确说明各个业务功能的优先级(业务功能优先级由“风险”,“复杂度”及“用户需要”在撰写需 求时确认),那么一般可参考此优先级来确认。优先级高的为主要业务,优先级其次的为次要业务,其它为辅助业务(注:仅可作为参考,确认业务类别最好由市场 相关人员来确认。如产品经理,市场分析人员等。)

      若需求中没有明确说明各业务功能的优先级,哪么应当在测试开始前,召开由产品,研发及测试部门一同出席的会议,确认各业务功能的分类,并将其记录于需求文档中。

      ● 测试发生率

      测试发生率为按照特定步骤执行多次的BUG重现率

      测试发生率=BUG重现次数/按照特定步骤执行的总次数。

      其中:对于概率性问题,执行的总次数应结果BUG的复杂程度执行(20-50次)

      用户使用发生率等级划分:

      如上所述,用户使用发生率=用户类别*业务类别*测试发生率,根据最终得到的用户使用发生率的值的不同,可以将用户使用发生率划分为如下几个等级(也可沿用旧等级划分,将<2%的问题划入等级“低”):

    用户使用发生率 新 等 级 划 分 对应于目前的等级划分
    70%-100% 常常发生
    30%-70% 经常发生
    2%-30% 有时发生
    <2% 一次发生
  • 软件测试的十六种测试类型

    2010-01-06 10:18:54

    最近去了一家大公司面试,发现自己在测试用例的设计方面真是考虑的不够全面,一直呆在只有自己一个测试人员的小公司,自己不随时居安思危真是一件很可怕的事!
    现在转载以下别人的软件测试测试类型及基本测试项的总结,希望能时刻提醒自己。
       一:功能测试(10个方面)

      菜单、工具栏、快捷键、下拉框、按钮、单选按钮、复选按钮、切换、链接、触发键

      二:界面测试

      登陆界面、总界面、输入界面(增、删、改、查)、处理界面、输出界面、报表界面、提示界面

      三:容错测试

      数据长度、数据类型、非法此操作

      四:接口测试

      接口测试也叫业务流程测试(包括功能模块之间、模块与模块之间、子系统之间)

      内部接口:例如:导入、导出(通俗的讲是接口就是调用)

      外部接口:

      五:性能测试(TPS吞吐量、响应速度、cpu占用率、内存占用率)

      平均吞吐量:单位时间内处理事务的个数

      平均响应速度:做一个事务处理所用时间

      例如:界面操作效率测试;报表输出及查询效率测试

      六:负载测试(压力测试、强度测试、容量测试)

      压力测试即就是大用户测试(针对B/S而言)

      容量测试即就是大数据量测试

      七:并发测试

      指多个用户在同一时间对同一条数据的删除或者修改等处理

      八:稳定性测试

      例如:1小时触发600条信息,那么8个、10个等发信息的条数测试

      九:恢复测试

      突然断电(系统触发正常启动;数据包要在断电的地方继续进行处理)

      十:配置测试

      最低配置:

      推荐配置:大多数用户所用的配置

      十一:安装测试

      安装过程;卸载过程

      十二:文档测试

      交给用户的文档。例如:系统帮助、用户使用手册、用户安装手册

      十三:可用性测试(纯粹靠经验)

      十四:初始化测试

      是指系统刚刚安装完成后,在数据位空的情况下,如果被调用的模块为空,点击调用模块的时候,是否进行容错的测试。

      十五:数据完整性测试

      是指当主表的某一条件信息被删除后,和这一条相关的从表的信息都应该被删除。

      如果某些数据的主键是由数据库本身而实现的,可以不用删除,如果有些主从表是由程序员写的代码而实现,则要进行数据完整性的测试。

      16种测试类型归类

      1、此软件能做什么?

      针对数据进行”功能、接口、容错、界面、权限、初始化、数据完整性测试“

      2、软件做的怎么样?

      性能、负载、恢复、稳定性、并发、系统安全

      3、软件在什么环境条件下做?

      配置、安装、文档、可用性


  • 学习测试计划编写

    2009-12-25 14:17:03

    最近很烦恼,一个人摸索测试计划怎么写,什么需求文档、设计说明书都没有,只能硬掰。看论坛上有前辈整理的超级全面的测试计划,转载学习一下:

    1.简介        3
      1.1目的        3
      1.2背景        3
      1.3范围        3
    2.测试参考文档和测试提交文档        3
      2.1测试参考文档        3
      2.2测试提交文档        3
    3.测试进度        3
    4.测试资源        3
      4.1人力资源        3
      4.2测试环境        3
      4.3测试工具        3
    5.系统风险、优先级        3
    6.测试策略        3
      6.1数据和数据库完整性测试        3
      6.2接口测试        3
      6.3集成测试        3
      6.4功能测试        3
      6.5用户界面测试        3
      6.6性能评测        3
      6.7负载测试        3
      6.8强度测试        3
      6.9容量测试        3
      6.10安全性和访问控制测试        3
      6.11故障转移和恢复测试        3
      6.12配置测试        3
      6.13安装测试        3
    7.问题严重度描述        3
    8.附录:项目任务        3


    1.        简介
    1.        1目的
    <项目名称>的这一“测试计划”文档有助于实现以下目标:

    [确定现有项目的信息和应测试的软件构件。
    列出推荐的测试需求(高级需求)。
    推荐可采用的测试策略,并对这些策略加以说明。
    确定所需的资源,并对测试的工作量进行估计。
    列出测试项目的可交付元素]
    1.        2背景
    [对测试对象(构件、应用程序、系统等)及其目标进行简要说明。需要包括的信息有:主要的功能和性能、测试对象的构架以及项目的简史。]
    1.3范围
    [描述测试的各个阶段(例如,单元测试、集成测试或系统测试),并说明本计划所针对的测试类型(如功能测试或性能测试)。
    简要地列出测试对象中将接受测试或将不接受测试的那些性能和功能。
    如果在编写此文档的过程中做出的某些假设可能会影响测试设计、开发或实施,则列出所有这些假设。
    列出可能会影响测试设计、开发或实施的所有风险或意外事件。
    列出可能会影响测试设计、开发或实施的所有约束。]


    2.测试参考文档和测试提交文档
    2.1测试参考文档
    下表列出了制定测试计划时所使用的文档,并标明了各文档的可用性:
    [注:可适当地删除或添加文档项。]
    文档(版本/日期)        已创建或可用        已被接收或已经过复审        作者或来源        备注
    可行性分析报告        是□ 否□        是□ 否□               
    软件需求定义        是□ 否□        是□ 否□               
    软件系统分析(STD,DFD,CFD,DD)        是□ 否□        是□ 否□               
    软件概要设计        是□ 否□        是□ 否□               
    软件详细设计        是□ 否□        是□ 否□               
    软件测试需求        是□ 否□        是□ 否□               
    硬件可行性分析报告        是□ 否□        是□ 否□               
    硬件需求定义        是□ 否□        是□ 否□               
    硬件概要设计        是□ 否□        是□ 否□               
    硬件原理图设计        是□ 否□        是□ 否□               
    硬件结构设计(包含PCB)        是□ 否□        是□ 否□               
    FPGA设计        是□ 否□        是□ 否□               
    硬件测试需求        是□ 否□        是□ 否□               
    PCB设计        是□ 否□        是□ 否□               
    USB驱动设计        是□ 否□        是□ 否□               
    Tuner BSP 设计        是□ 否□        是□ 否□               
    MCU设计        是□ 否□        是□ 否□               
    模块开发手册        是□ 否□        是□ 否□               
    测试时间表及人员安排        是□ 否□        是□ 否□               
    测试计划      是□ 否□        是□ 否□               
    测试方案        是□ 否□        是□ 否□               
    测试报告        是□ 否□        是□ 否□               
    测试分析报告        是□ 否□        是□ 否□               
    用户操作手册        是□ 否□        是□ 否□               
    安装指南        是□ 否□        是□ 否□               
    2.2测试提交文档
    [下面应当列出在测试阶段结束后,所有可提交的文档]
    3.测试进度
    测试活动        计划开始日期        实际开始日期        结束日期
    制定测试计划                       
    设计测试                       
    集成测试                       
    系统测试                       
    性能测试                       
    安装测试                       
    用户验收测试                       
    对测试进行评估                       
    产品发布                       


    4.测试资源
    4.1人力资源
    下表列出了在此项目的人员配备方面所作的各种假定。
    [注:可适当地删除或添加角色项。]
    角色        所推荐的最少资源(所分配的专职角色数量)        具体职责或注释
                   
                   
    4.2测试环境
    下表列出了测试的系统环境
    软件环境(相关软件、操作系统等)

    硬件环境(网络、设备等)


    4.3测试工具
    此项目将列出测试使用的工具:
    用途        工具        生产厂商/自产        版本


    5.系统风险、优先级
    [简要描述测试阶段的风险和处理的优先级]


    6.测试策略
    [测试策略提供了对测试对象进行测试的推荐方法。
    对于每种测试,都应提供测试说明,并解释其实施的原因。
    制定测试策略时所考虑的主要事项有:将要使用的技术以及判断测试何时完成的标准。
    下面列出了在进行每项测试时需考虑的事项,除此之外,测试还只应在安全的环境中使用已知的、有控制的数据库来执行。]
    注意:不实施某种测试,则应该用一句话加以说明,并陈述这样的理由。例如,“将不实施该测试。该测试本项目不适用”。
    6.1数据和数据库完整性测试
    [要<项目名称>中,数据库和数据库进程应作为一个子系统来进行测试。在测试这些子系统时,不应将测试对象的用户界面用作数据的接口。对于数据库管理系统(DBMS),还需要进行深入的研究,以确定可以支持以下测试的工具和技术。]

    测试目标:        [确保数据库访问方法和进程正常运行,数据不会遭到损坏]
    测试范围:       
    技术:        [调用各个数据库访问方法和进程,并在其中填充有效的和无效的数据(或对数据的请求)。检查数据库,确保数据已按预期的方式填充,并且所有的数据库事件已正常发生;或者检查所返回的数据,确保正当的理由检索到了正确的数据]
    开始标准:       
    完成标准:        [所有的数据库访问方法和进程都按照设计的方式运行,数据没有遭到损坏。]
    测试重点和优先级:       
    需考虑的特殊事项:        [测试可能需要DBMS开发环境或驱动程序在数据库中直接输入或修改数据。进程应该以手工方式调用。应使用小型或最小的数据库(记录的数量有限)来使所有无法接受的事件具有更大的可视度。]


    6.2接口测试
    测试目标        确保接口调用的正确性       
    测试范围:        所有软件、硬件接口,记录输入输出数据
    技术:       
    开始标准:       
    完成标准:       
    测试重点和优先级:       
    需考虑的特殊事项:        接口的限制条件


    6.3集成测试
    [集成测试―主要目的检测系统是否达到需求对业务流程及数据流的处理是否符合标准,检测系统对业务流处理是否存在逻辑不严谨及错误,检测需求是否存在不合理的标准及要求。此阶段测试基于功能完成的测试。]
    测试目标        检测需求中业务流程,数据流的正确性
    测试范围:        需求中明确的业务流程,或组合不同功能模块而形成一个大的功能。
    技术:        [利用有效的和无效的数据来执行各个用例、用例流或功能,以核实以下内容:在使用有效数据时得到预期的结果。在使用无效数据时显示相应的错误消息或警告消息。各业务规则都得到了正确的应用。]
    开始标准:        在完成某个集成测试时必须达到标准
    完成标准:        [所计划的测试已全部执行。所发现的缺陷已全部解决。]
    测试重点和优先级:        测试重点指在测试过程中需着重测试的地方,优先级可以根据需求及严重来定
    需考虑的特殊事项:        [确定或说明那些将对功能测试的实施和执行造成影响的事项或因素(内部的或外部的)]


    6.4功能测试
    [对测试对象的功能测试应侧重于所有可直接追踪到用例或业务功能和业务规则的测试需求。这种测试的目标是核实数据的接受、处理和检索是否正确,以及业务规 则的实施是否恰当。此类测试基于黑盒技术,该技术通过图形用户界面(GUI)与应用程序进行交互,并对交互的输出或结果进行分析,以此来核实应用程序及其 内部进程。以下为各种应用程序列出了推荐使用的测试概要:]

    测试目标        [确保测试的功能正常,其中包括导航,数据输入,处理和检索等功能。]
    测试范围:       
    技术:        [利用有效的和无效的数据来执行各个用例、用例流或功能,以核实以下内容:在使用有效数据时得到预期的结果。在使用无效数据时显示相应的错误消息或警告消息。各业务规则都得到了正确的应用。]
    开始标准:       
    完成标准:       
    测试重点和优先级:       
    需考虑的特殊事项:        [确定或说明那些将对功能测试的实施和执行造成影响的事项或因素(内部的或外部的)]


    6.5用户界面测试
    [用户界面(UI)测试用于核实用户与软件之间的交互。UI测试的目标是确保用户界面会通过测试对象的功能来为用户提供相应的访问或浏览功能。另外,UI测试还可确保UI中的对象按照预期的方式运行,并符合公司或行业的标准。]

    测试目标        [核实以下内容:通过测试进行的浏览可正确反映业务的功能和需求,这种浏览包括窗口与窗口之间、字段与字段之间的浏览,以及各种访问方法(Tab键、鼠标 移动、和快捷键)的使用窗口的对象和特征(例如,菜单、大小、位置、状态和中心)都符合标准。]
    测试范围:       
    技术:        [为每个窗口创建或修改测试,以核实各个应用程序窗口和对象都可正确地进行浏览,并处于正常的对象状态。]
    开始标准:       
    完成标准:        [成功地核实出各个窗口都与基准版本保持一致,或符合可接受标准]
    测试重点和优先级:       
    需考虑的特殊事项:        [并不是所有定制或第三方对象的特征都可访问。]


    6.6性能评测
    [性能评测是一种性能测试,它对响应时间、事务处理速率和其他与时间相关的需求进行评测和评估。性能评测的目标是核实性能需求是否都已满足。实施和执行性能评测的目的是将测试对象的性能行为当作条件(例如工作量或硬件配置)的一种函数来进行评测和微调。
    注:以下所说的事务是指“逻辑业务事务”。这种事务被定义为将由系统的某个Actor通过使用测试对象来执行的特定用例,添加或修改给定的合同。]

    测试目标        [核实所指定的事务或业务功能在以下情况下的性能行为:正常的预期工作量预期的最繁重工作量]
    测试范围:       
    技术:        [使用为功能或业务周期测试制定的测试过程。通过修改数据文件来增加事务数量,或通过修改脚本来增加每项事务的迭代数量。脚本应该在一台计算机上运行(最 好是以单个用户、单个事务为基准),并在多个客户机(虚拟的或实际的客户机,请参见下面的“需要考虑的特殊事项”)上重复。]
    开始标准:       
    完成标准:        [单个事务或单个用户:在每个事务所预期时间范围内成功地完成测试脚本,没有发生任何故障。][多个事务或多个用户:在可接受的时间范围内成功地完成测试脚本,没有发生任何故障。]
    测试重点和优先级:       
    需考虑的特殊事项:        [综合的性能测试还包括在服务器上添加后台工作量。可采用多种方法来执行此操作,其中包括:直接将“事务强行分配到”服务器上,这通常以“结构化语言” (SQL)调用的形式来实现。通过创建“虚拟的”用户负载来模拟许多个(通常为数百个)客户机。此负载可通过“远程终端仿真(Remote Terminal Emulation)工具来实现。此技术还可用于在网络中加载“流量”。使用多台实际客户机(每台客户机都运行测试脚本)在系统上添加负载。性能测试应该 在专用的计算机上或在专用的机时内执行,以便实现完全的控制和精确的评测。性能测试所用的数据库应该是实际大小或相同缩放比例的数据库。]


    6.7负载测试
    [负载测试是一种性能测试。在这种测试中,将使测试对象承担不同的工作量,以评测和评估测试对象在不同工作量条件下的性能行为,以及持续正常运行的能力。 负载测试的目标是确定并确保系统在超出最大预期工作量的情况下仍能正常运行。此外,负载测试还要评估性能特征,例如,响应时间、事务处理速率和其他与时间 相关的方面。]
    [注:以下所说的事务是指“逻辑业务事务”。这各事务被定义为将由系统的某个最终用户通过使用应用程序来执行的特定功能,例如,添加或修改给定的合同。]

    测试目标        [核实所指定的事务或商业理由在不同的工作量条件下的性能行为时间。]
    测试范围:       
    技术:        [使用为功能或业务周期测试制定的测试。通过修改数据文件来增加事务数量,或通过修改脚本来增加每项事务发生的次数。]
    开始标准:       
    完成标准:        [多个事务或多个用户:在可接受的时间范围内成功地完成测试,没有发生任何故障。]
    测试重点和优先级:       
    需考虑的特殊事项:        [负载测试应该在专用的计算机上或在专用的机时内执行,以便实现完全的控制和精确的评测。负载测试所用的数据库应该是实际大小或相同缩放比例的数据库。]


    6.8强度测试
    [强度测试是一种性能测试,实施和执行此类测试的目的是找出因资源不足或资源争用而导致的错误。如果内存或磁盘空间不足,测试对象就可能会表现出一些在正 常条件下并不明显的缺陷。而其他缺陷则可能由于争用共享资源(如数据库锁或网络带宽)而造成的。强度测试还可用于确定测试对象能够处理的最大工作量。]
    [注:以下提到的事务都是指逻辑业务事务。]
    测试目标        [核实测试对象能够在以下强度条件下正常运行,不会出现任何错误:服务器上几乎没有或根本没有可用的内存(RAM和DASD)连接或模拟了最大实际(实际 允许)数量的客户机多个用户对相同的数据或帐户执行相同的事务最繁重的事务量或最差的事务组合(请参见上面的“性能测试”)。注:强度测试的目标可表述为 确定和记录那些使系统无法继续正常运行的情况或条件。客户机的强度测试在“配置测试”的第3.1.11节中进行了说明。]
    测试范围:       
    技术:        [使用为性能评测或负载测试制定的测试。要对有限的资源进行测试,就应该在一台计算机上运行测试,而且应该减少或限制服务器上的RAM和DASD。对于其 他强度测试,应该使用多台客户机来运行相同的测试或互补的测试,以产生最繁重的事务量或最差的事务组合。]
    开始标准:       
    完成标准:        [所计划的测试已全部执行,并且在达到或超出指定的系统限制时没有出现任何软件故障,或者导致系统出现故障条件的并不在指定的条件范围之内。]
    测试重点和优先级:       
    需考虑的特殊事项:        [如果要增加网络工作强度,可能会需要使用网络工具来给网络加载消息或信息包。应该暂时减少用于系统的DASD,以限制数据库可用空间的增长。使多个客户机对相同的记录或数据帐户同时进行的访问达到同步。]


    6.9容量测试
    [容量测试使测试对象处理大量的数据,以确定是否达到了将使软件发生故障的极限。容量测试还将确定测试对象在给定时间内能够持续处理的最大负载或工作量。 例如,如果测试对象正在为生成一份报表而处理一组数据库记录,那么容量测试就会使用一个大型的测试数据库。检验该软件是否正常运行并生成了正确的报表。]

    测试目标        [核实测试对象在以下高容量条件下能否正常运行:连接或模拟了最大(实际或实际允许)数量的客户机,所有客户机在长时间内执行相同的、且情况(性能)最坏 的业务功能。已达到最大的数据库大小(实际的或按比例缩放的),而且同时执行多个查询或报表事务。]
    测试范围:       
    技术:        [使用为性能评测或负载测试制定的测试。应该使用多台客户机来运行相同的测试或互补的测试,以便在长时间内产生最繁重的事务量或最差的事务组合(请参见上 面的“强度测试”)创建最大的数据库大小(实际的、按比例缩放的、或填充了代表性数据的数据库),并使用多台客户机在长时间内同时运行查询和报表事务。]
    开始标准:       
    完成标准:        [所计划的测试已全部执行,而且达到或超出指定的系统限制时没有出现任何软件故障。]
    测试重点和优先级:       
    需考虑的特殊事项:        [对于上述的高容量条件,哪个时间段是可以接受的时间?]


    6.10安全性和访问控制测试
    [安全性和访问控制测试侧重于安全性的两个关键方面:
    应用程序级别的安全性,包括对数据或业务功能的访问。
    系统级别的安全性,包括对系统的登录或远程访问。
    应用程序级别的安全性可确保:在预期的安全性情况下,Actor只能访问特定的功能或用例,或者只能访问有限的数据。例如,可能会允许所有人输入数据,创 建新帐户,但只有管理员才能删除这些数据或帐户。如果具有数据级别的安全性,测试就可确保“用户类型一”能够看到所有客户消息(包括财务数据),而“用户 二”看见同一客户的统计数据。
    系统级别的安全性可确保只有具备系统访问权限的用户才能访问应用程序,而且只能通过相应的网关来访问。]
    测试目标        应用程序级别的安全性:[核实Actor只能访问其所属用户类型已被授权访问的那些功能或数据。]系统级别的安全性:[核实只有具备系统和应用程序访问权限的Actor才能访问系统和应用程序。]
    测试范围:       
    技术:        应用程序级别的安全性:[确定并列出各用户类型及其被授权访问的功能或数据。][为各用户类型创建测试,并通过创建各用户类型所特有的事务来核实其权 限。]修改用户类型并为相同的用户重新运行测试。对于每种用户类型,确保正确地提供或拒绝了这些附加的功能或数据。系统级别的访问:[请参见以下的“需考 虑的特殊事项”。]
    开始标准:       
    完成标准:        [各种已知的Actor类型都可访问相应的功能或数据,而且所有事务都按照预期的方式运行,并在先前的应用程序功能测试中运行了所有的事务。]
    测试重点和优先级:       
    需考虑的特殊事项:        [必须与相应的网络或系统管理员一直对系统访问权进行检查和讨论。由于此测试可能是网络管理可系统管理的职能,可能会不需要执行此测试。]


    6.11故障转移和恢复测试
    [故障转移和恢复测试可可确保测试对象能成功完成转移,并能从导致意外数据损失或数据完整性破坏的各种硬件、软件可网络故障中恢复。
    故障转移测试可确保:对于必须持续运行的系统,一旦发生故障,备用系统就将不失时机地“顶替”发生故障的系统,以避免丢失任何数据或事务。
    恢复测试是一种对抗性的测试过程。在这种测试中,将把应用程序或系统置于极端的条件下(或者是模拟的极端条件下),以产生故障(例如设备输入/输出(I /O)故障或无效的数据库指针和关键字)。然后调用恢复进程并监测和检查应用程序和系统,核实应用程序或系统和数据已得到了正确的恢复。]

    测试目标        [确保恢复进程(手工或自动)将数据库、应用程序和系统正确地恢复到预期的已知状态。测试中将包括以下各种情况:客户机断电服务器断电通过网络服务器产生 的通信中断DASD和/或DASD控制器被中断、断电或与DASD和/或DASD控制器的通信中断周期未完成(数据过滤进程被中断,数据同步进程被中 断)。数据库指针或关键字无效数据库中的数据元素无效或遭到破坏]
    测试范围:       
    技术:        [应该使用为功能和业务周期测试创建的测试来创建一系列的事务。一旦达到预期的测试起点,就应该分别执行或模拟以下操作:²       
    客户机断电:关闭PC机的电源。²       
    服务器断电:模拟或启动服务器的断电过程。²       
    通过网络服务器产生的中断:模拟或启动网络的通信中断(实际断开通信线路的连接或关闭网络服务器或路由器的电源)。²       
    DASD和DASD控制器被中断、断电或与DASD和DASD控制器的通信中断:模拟与一个或多个DASD控制器或设备的通信,或实际取消这种通信。²       
    一旦实现了上述情况(或模拟情况),就应该执行其他事务。而且一旦达到第二个测试点状态,就应调用恢复过程。²      
    在测试不完整的周期时,所使用的技术与上述技术相同,只不过应异常终止或提前终止数据库进程本身。²       
    对以下情况的测试需要达到一个已知的数据库状态。当破坏若干个数据库字段、指针和关键字时,应该以手工方式在数据库中(通过数据库工具)直接进行。其他事 务应该通过使用“应用程序功能测试”和“业务周期测试”中的测试来执行,并且应执行完整的周期。]
    开始标准:       
    完成标准:        [在所有上述情况中,应用程序、数据库和系统应该在恢复过程完成时立即返回到一个已知的预期状态。此状态包括仅限于已知损坏的字段、指针或关键字范围内的数据损坏,以及表明进程或事务因中断面未被完成的报表。]
    测试重点和优先级:       
    需考虑的特殊事项:        ²       
    [恢复测试会给其他操作带来许多的麻烦。断开缆线连接的方法(模拟断电或通信中断)可能并不可取或不可行。所以,可能会需要采用其他方法,例如诊断性软件 工具。²       
    需要系统(或计算机操作)、数据库和网络组中的资源。²       
    这些测试应该在工作时间之外或在一台独立的计算机上运行。]


    6.12配置测试
    [配置测试核实测试对象在不同的软件和硬件配置中的运行情况。在大多数生产环境中,客户机工作站、网络连接和数据库服务器的具体硬件规格会有所不同。客户 机工作站可能会安装不同的软件 例如,应用程序、驱动程序等 而且在任何时候,都可能运行许多不同的软件组合,从而占用不同的资源。]

    测试目标        [核实测试可在所需的硬件和软件配置中正常运行。]
    测试范围:       
    技术:        ²       
    [使用功能测试脚本。²       
    在测试过程中或在测试开始之前,打开各种与非测试对象相关的软件(例如Microsoft应用程序:Excel和Word),然后将其关闭。²       
    执行所选的事务,以模拟Actor与测试对象软件和非测试对象软件之间的交互。²       
    重复上述步骤,尽量减少客户机工作站上的常规可用内存。]
    开始标准:       
    完成标准:        [对于测试对象软件和非测试对象软件的各种组合,所有事务都成功完成,没有出现任何故障。]
    测试重点和优先级:       
    需考虑的特殊事项:        ²       
    [需要、可以使用并可以通过桌面访问哪种非测试对象软件?²       
    通常使用的是哪些应用程序?²       
    应用程序正在运行什么数据?例如,在Excel中打开的大型电子表格,或是在Word中打开的100页文档。²       
    作为此测试的一部分,应将整修系统、Netware、网络服务器、数据库等都记录下来。]


    6.13安装测试
    [安装测试有两个目的。
    第一个目的是确保该软件在正常情况和异常情况的不同条件下
    例如,进行首次安装、升级、完整的或自定义的安装 都能进行安装。
    异常 情况包括磁盘空间不足、缺少目录创建权限等。
    第二个目的是核实软件在安装后可立即正常运行。这通常是指运行大量为功能测试制定的测试。]
    测试目标        核实在以下情况下,测试对象可正确地安装到各种所需的硬件配置中:
    首次安装。以前从未安装过<项目名称>的新计算机²       
    更新。以前安装过相同版本的<项目名称>的计算机²       
    更新。以前安装过<Project Name>的较早版本的计算机
    测试范围:       
    技术:        ²
    [手工开发脚本或开发自动脚本,以验证目标计算机的状况 首次安装<项目名称>从未安装过;<项目名称>安装过相同或较早的版本。²       
    启动或执行安装。²       
    使用预先确定的功能测试脚本子集来运行事务。]
    开始标准:       
    完成标准:        <项目名称>事务成功执行,没有出现任何故障。
    测试重点和优先级:       
    需考虑的特殊事项:        [应该选择<项目名称>的哪些事务才能准确地测试出<项目名称>应用程序已经成功安装,而且没有遗漏主要的软件构件?。]


    7.问题严重度描述
     问题严重度  描述 响应时间
     高  例如使系统崩溃  程序员在多长时间改正此问题
     中    
     低    
       
                   
                   
    8.附录:项目任务
    以下是一些与测试有关的任务:
    ²        制定测试计划
    n        确定测试需求
    n        评估风险
    n        制定测试策略
    n        确定测试资源
    n        创建时间表
    n        生成测试计划
    ²        设计测试
    n        准备工作量分析文档
    n        确定并说明测试用例
    n        确定测试过程,并建立测试过程的结构
    ²        复审和评估测试覆盖
    ²        实施测试
    n        记录或通过编程创建测试脚本
    n        确定设计与实施模型中的测试专用功能
    n        建立外部数据集
    ²        执行测试
    ²        执行测试过程
    ²        评估测试的执行情况
    ²        恢复暂停的测试
    ²        核实结果
    ²        调查意外结果
    ²        记录缺陷
    ²        对测试进行评估
    ²        评估测试用例覆盖
    ²        评估代码覆盖
    ²        分析缺陷
    ²        确定是否达到了测试完成标准与成功标准
  • web性能测试步骤

    2009-12-25 14:13:25

    web性能测试步骤


    web性能测试的步骤:
      第一,分析产品结构,明确性能测试的需求,包括并发、极限、配置和指标等方面的性能要求,必要时基于LOAD测试的相同测略需同时考虑稳定性测试的需求。
      第一,分析应用场景和用户数据,细分用户行为和相关的数据流,确定测试点或测试接口,列示系统接口的可能瓶颈,一般是先主干接口再支线接口,并完成初步的测试用例设计。
      第三,依据性能测试需求和确定的测试点进行测试组网设计,并明确不同组网方案的重要程度或优先级作为取舍评估的依据,必要时在前期产品设计中提出支持性能测试的可测试性设计方案和对测试工具的需求。
      第四,完成性能测试用例设计、分类选择和依据用户行为分析设计测试规程,并准备好测试用例将用到的测试数据。
          第五,确定采用的测试工具。
          第六,进行初验测试,以主干接口的可用性为主,根据测试结果分析性能瓶颈,通过迭代保证基本的指标等测试的环境。
          第七,迭代进行全面的性能测试,完成计划中的性能测试用例的执行。
          第八,完成性能测试评估报告。
      在进行性能测试的时候,我们需要知道一些有效的性能指标,下面我们来列出一些主要的性能指标:
      一是,通用指标(指Web应用服务器、数据库服务器必需测试项):
          *ProcessorTime:指服务器CPU占用率,一般平均达到70%时,服务就接近饱和;
          *Memory Available Mbyte:可用内存数,如果测试时发现内存有变化情况也要注意,如果是内存泄露则比较严重;
          *Physicsdisk Time :物理磁盘读写时间情况。
          二是,Web服务器指标:
          *Avg Rps:平均每秒钟响应次数=总请求时间/秒数;
          *Avg time to last byte per terstion(mstes):平均每秒业务角本的迭代次数;*Successful Rounds:成功的请求;
          *Failed Rounds:失败的请求;
          *Successful Hits:成功的点击次数;
          *Failed Hits:失败的点击次数;
          *Hits Per Second:每秒点击次数;
          *Successful Hits Per Second:每秒成功的点击次数;
          *Failed Hits Per Second:每秒失败的点击次数;
          *Attempted Connections:尝试链接数。
          三是,数据库服务器指标:
          *User 0 Connections :用户连接数,也就是数据库的连接数量;
          *Number of deadlocks:数据库死锁;
          *Butter Cache hit:数据库Cache的命中情况。
  • TCP和UDP的区别

    2009-12-15 21:22:53

    (1)TCP是面向连接的传输控制协议,而UDP提供了无连接的数据报服务;
    (2)TCP具有高可靠性,确保传输数据的正确性,不出现丢失或乱序;UDP在传输数据前不建立连接,不对数据报进行检查与修改,无须等待对方的应答,所以会出现分组丢失、重复、乱序,应用程序需要负责传输可靠性方面的所有工作;
    (3)也正因为以上特征,UDP具有较好的实时性,工作效率较TCP协议高;
    (4)UDP段结构比TCP的段结构简单,因此网络开销也小。
  • P2P释义

    2009-12-15 21:21:20

       P2P是英文Peer-to-Peer(对等)的简称(因为,2 和to在英文里同音),又被称为“点对点”。“对等”技术,是一种网络新技术,依赖网络中参与者的计算能力和带宽,而不是把依赖都聚集在较少的几台服务器上。
      P2P还是英文Point to Point (点对点)的简称。它是下载术语,意思是在你自己下载的同时,自己的电脑还要继续做主机上传,这种下载方式,人越多速度越快,但缺点是对你的硬盘损伤比较大(在写的同时还要读),还有就是对你内存占用较多,影响整机速度。
  • 典型Bug管理工具比较

    2009-12-15 21:19:25

    功能特征 \ 产品

    Testdirector

    ClearQuest

    微创BMS

    Bugzilla

    华创BMS

    构架模式

    B/S

    C/S,B/S

    B/S

    B/S

    B/S

    用户友好性

    一般

    流程定制

    Y

    Y

    N

    Y

    Y

    查询功能定制

    Y

    Y

    Y

    Y

    Y

    功能域定制

    Y

    Y

    Y

    Y

    Y

    附件支持

    Y

    Y

    Y

    Y

    Y

    用户权限分级管理

    Y

    Y

    Y

    Y

    Y

    Email通知

    Y

    Y

    Y

    Y

    Y

    批量修改

    N

    N

    N

    Y

    Y

    导出至外部文档

    Word文档

    N

    N

    N

    Excel,HTML

    报表定制功能

    Y

    ,集成Crystal Report

    有标准报表和高级报表,定制功能不够

    Y

    ,有标准报表,定制方便

    数据更改历史

    Y

    Y

    Y

    N

    Y

    支持平台

    Windows

    Windows, Unix

    Windows

    Linux,FreeBSD

    Windows

    支持数据库

    Oracle, M$ Access, SQL Server

    Oracle, M$ Access, SQL Server

    SQL ServerMSDE

    MySQL

    Access, SQL Server

    安装配置的复杂度

    简单

    复杂

    容易

    有些复杂

    简单

    售后服务

    国内有多家代理公司提供相关服务

    在国内有分公司提供技术支持

    技术支持和服务体系完备

    有技术支持和服务,在线升级

    与其他工具集成

    本身又是测试需求、测试案例管理工具,winRunner, LoadRunner集成,具有多种主流Case工具接口AddIn

    rational公司的其它产品无缝集成,特别与Clear Case配合以可实现UCM的配置管理体系

    M$ VSS, Project

    开源配置管理工具CVS

    公司背景

    世界主流测试软件提供商

    已被IBM合并,世界著名软件公司

    微软与上海市政府成立的

    世界著名开源项目

    国产软件

    价格

    几十万,昂贵

    几十万,昂贵

    几万,适中

    免费

    一二千

    官方网址

    http://www.mercuryinteractive.com

    http://www.rational.com

    http://www.wicresoft.com

    http://www.bugzilla.org

    http://www.hc-software.com

  • 用LoadRunner编写socket应用的测试脚本

    2009-12-11 10:55:01

    loadRunner提供了很好的对socket应用的支持,用户可以通过录制方法完全获得客户端发送和接收的数据,然后在录制的基础上对相应的数据进行参数化和关联等处理。

            但在有些情况下(例如,客户端程序没有windows上的版本),我们就很难通过录制达成生成脚本的目标了。但如果我们能够完全知晓服务端和客户端的交互过程,完全手工编写一个测试脚本也并不是一件特别困难的事情。

           在本文中,我们以一个实际的例子说明如何根据服务端和客户端交互的过程,用LoadRunner自行编写相应的脚本。

            以下是服务端工作线程的代码:
    DWORD WINAPI mythread( LPVOID lpParameter)    //客户线程
    {
        
    struct My my;
        memcpy(
    &my,lpParameter,sizeof(My));    
        printf(
    "One client connect!/n");
        
    char str1[1024];            //接收字符串
        char str2[1024];
                            
        
    int i;
        i
    =recv(my.skt,str1,sizeof(str1),0);    //接收客户请求
        str1[i]=0;

        
    char *filename;
        filename
    =new char[255];
        
    for(int j=2;j<i;j++)            //获得文件名
        {
            filename[j
    -2]=str1[j];
        }
        filename[i
    -2]=0;
       

        
    if (str1[0]=='S')
        {
            printf(
    "The file name : %s/n",filename);
            ofstream 
    out(filename);                //创文件流   
            if (!out)
            {
                printf(
    "cannot open file./n");        //文件是否正确打开,打开错误则退出
                send(my.skt,"q",1,0);            //向客户发送退出信息
                closesocket(my.skt);            //解除客户连接;
                return 0;
            }
            str2[
    0]='O';                       
            str2[
    1]='K';
            str2[
    2]=0;
            send(my.skt,str2,strlen(str2),
    0);        //回复OK信息

            i
    =recv(my.skt,str1,sizeof(str1),0);        //接收文件长度
            str1[4]=0;
           
            
    int len;
            len
    =str1[0]*1000+str1[1]*100+str1[2]*10+str1[3];
            printf(
    "The File lenght is: %d Byte/n",len);
           
            
    for(int j=0;j<len;j++)
                {
                    
    char str[1];
                    i
    =recv(my.skt,str,sizeof(str),0);//接收文件,按字节接收,接收字符串为2个字节
                    str[i]=0;
                    
    out.put(str[0]);
                }

            
    out.close();                    //关闭文件
            printf("over!One client quit!/n");        //接收文件完毕
            closesocket(my.skt);                //解除此客户连接
            return 0;
        }

        
    if (str1[0]=='R')
        {       
           
            ifstream 
    in(filename);
            
    if (!in)
            {
                printf(
    "cannot open file or file not exist./n");    //文件是否正确打开,打开错误则退出
                send(my.skt,"q",1,0);                    //向客户发送退出信息
                closesocket(my.skt);                    //解除客户连接;
                return 0;
            }
            
    char ch;
            
    int len=0;
            
    while(in.get(ch))
            {
                len
    ++;                            //get file lenght
            }
            
    in.close();
            str2[
    0]='O';
            str2[
    1]='K';
            str2[
    2]=len/1000;                       
            str2[
    3]=(len%1000)/100;
            str2[
    4]=(len%100)/10;
            str2[
    5]=len%10;
            printf(
    "%s",str2);
            send(my.skt,str2,
    6,0);                        //发OK+文件长度

            
    in.open(filename);
            
    if (!in)
            {
                printf(
    "cannot open file or file not exist./n");    //文件是否正确打开,打开错误则退出
                send(my.skt,"q",1,0);                    //向客户发送退出信息
                closesocket(my.skt);                    //解除客户连接;
                return 0;
            }

            
    while(in.get(ch))                        //发文件
            {               
                
    char str[1];
                strcpy(str,
    "");
                str[
    0]=ch;
                str[
    1]=0;
                send(my.skt,str,
    1,0);                    //发送一个字符
            }
            
    in.close();
            printf(
    "over,One client quit!/n");                //传输文件完毕
            closesocket(my.skt);                        //解除此客户连接
            return 0;
        }

        printf(
    "Bad command!/n");
        closesocket(my.skt);
        
    return 0;
    }

            从这段代码中可以看到,当客户端和服务端建立连接后,客户端会先向服务端发送一个请求,该请求的第一个字节是大写的“S”或是“R”,分别向服务端写文件或是从服务端读取文件。从第三个字节开始,后面的内容是请求文件的文件名。

            服务端在接收到客户端的请求后,根据请求的类型,如果是“S”,则打开指定的文件,并返回一个字符串“OK”;如果是“R”,则打开指定的文件并向客户端发送“OK”+“文件长度”。

            随后,如果是“S”,则由客户端发送写入的文件长度和文件内容给服务端;如果是“R”,则向客户端发送文件的内容。

            到此我们已经完全明了了客户端和服务端的交互过程,因此,我们可以尝试在LR中建立一个脚本用户模拟客户端行为。

            下面我们以“S”的处理过程为例编写脚本。

            1、打开VUGen应用;
            2、新建脚本,选择“windows sockets”协议,不需录制;
            3、在Action Section中增加以下内容:
        //建立到服务端的连接
        lrs_create_socket("socket1","TCP","RemoteHost=127.0.0.1:8000",LrsLastArg);
       
        
    //发送“S”和文件名
        lrs_send("socket1""buf0", LrsLastArg);
        lrs_receive(
    "socket1""buf1", LrsLastArg);
       
        
    //发送要写入的数据的长度
        lrs_send("socket1""buf2", LrsLastArg);

        
    //发送数据内容
        lrs_send("socket1""buf3", LrsLastArg);
       
        
    //关闭连接
        lrs_close_socket("socket1");
       
            4、这样就成功的描述了整个交互过程,但还没有给出实际要发送的数据。在采用“Windows Sockets”协议的脚本中,实际发送的数据存放在data.ws Section中,因此,打开该Section,直接输入:
    send  buf0 7
        
    "S"
        
    "/x00"
        
    "1.txt"

    recv buf1 
    2
        
    "OK"

    send buf2 
    3
        
    "/x00"
        
    "/x00"
        
    "/x02"
        
    "/x00"

    send buf3 
    20
        
    "12345678901234567890"

            每个发送和接收的数据包在这里都有登记,“send”和“recv”表示数据的方向;“buf0”等表示数据包的描述,和脚本中的内容对应;接下来的一个整数表示数据包的长度;然后是数据包的内容,“/x00”表示16进制的00。

            该脚本描述了客户端向服务端请求写入一个文件1.txt,文件内容为“12345678901234567890”的过程。
291/212>
Open Toolbar