实验测试单元

Posted xy1229

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实验测试单元相关的知识,希望对你有一定的参考价值。

一、实验目的

1)掌握单元测试的方法

2) 学习XUnit测试原理及框架;

3)掌握使用测试框架进行单元测试的方法和过程。

二、实验内容与要求

1)源码

#include "stdio.h"
#include "string.h"
#include "windows.h"
#include "time.h"
 
#define N 49//1表示棋子,只有黑色棋子
 
int chess[N+2][N+2];//定义棋盘大小
int chess0[N+2][N+2];//辅助棋盘
 
 
void Initialize();//初始化一个对局函数
void RunGame();//进行游戏
int count_cellsNumber(int i,int j);//计算生命周围的生命数量
void Data();//调用已存的游戏数据
 
void main()
{
    system("mode con cols=99 lines=50");//设置窗口大小
    system("color 70");//设置颜色
    Initialize();//初始化一个对局函数
    RunGame();//进行游戏
}
 
void Initialize()//初始化一个对局函数
{
    Data();//调用已存的游戏数据
}
 
void Data()//调用已存的游戏数据
{
    int i,j;
    srand((unsigned)time(NULL));
    for(i=0;i<N;i++){
        for(j=0;j<N;j++)
            chess[i][j]=rand()%2;
    }
    /*
    int p=12;
    int l;
    for(l=-16;l<=16;l++)
        //if(l!=-8&&l!=0&&l!=4)
        chess[N/2+1][N/2+1+l]=1;
        */
 
/*
//滑翔机
chess[1][3]=1;chess[2][1]=1;chess[2][3]=1;chess[3][2]=1;chess[3][3]=1;
*/
/*
//高斯帕滑翔机
chess[1][p+11]=1;chess[1][p+13]=1;
chess[2][p+10]=1;chess[2][p+13]=1;
chess[3][p+9]=1;chess[3][p+10]=1;chess[3][p+21]=1;chess[3][p+28]=1;
chess[4][p+1]=1;chess[4][p+2]=1;chess[4][p+7]=1;chess[4][p+8]=1;chess[4][p+12]=1;chess[4][p+21]=1;chess[4][p+27]=1;chess[4][p+29]=1;
chess[5][p+1]=1;chess[5][p+2]=1;chess[5][p+9]=1;chess[5][p+10]=1;chess[5][p+20]=1;chess[5][p+27]=1;chess[5][p+28]=1;chess[5][p+30]=1;
chess[6][p+10]=1;chess[6][p+13]=1;chess[6][p+16]=1;chess[6][p+17]=1;chess[6][p+27]=1;chess[6][p+28]=1;chess[6][p+30]=1;chess[6][p+31]=1;chess[6][p+35]=1;chess[6][p+36]=1;
chess[7][p+11]=1;chess[7][p+13]=1;chess[7][p+16]=1;chess[7][p+19]=1;chess[7][p+20]=1;chess[7][p+21]=1;chess[7][p+22]=1;chess[7][p+27]=1;chess[7][p+28]=1;chess[7][p+30]=1;chess[7][p+35]=1;chess[7][p+36]=1;
chess[8][p+16]=1;chess[8][p+17]=1;chess[8][p+18]=1;chess[8][p+19]=1;chess[8][p+27]=1;chess[8][p+29]=1;
chess[9][p+17]=1;chess[9][p+18]=1;chess[9][p+28]=1;
*/
}
 
void cells_state(int i,int j)
{
    int living_cellsnumber=0;
    living_cellsnumber=count_cellsNumber(i,j);
    if(chess[i][j]==1){
        if(living_cellsnumber<2)
            chess0[i][j]=0;//如果一个生命周围的生命少于2个,它在回合结束后死亡。
        else if(living_cellsnumber>3)
            chess0[i][j]=0;//如果一个生命周围的生命超过3个,它在回合结束后死亡。
        else if(living_cellsnumber==2||living_cellsnumber==3)
            chess0[i][j]=1;//如果一个生命周围有2或3个生命,它在回合结束时保持原样。
    }
    else if(chess[i][j]==0){
        if(living_cellsnumber==3)
            chess0[i][j]=1;//如果一个死格周围有3个生命,它在回合结束时获得生命。
    }
}

void RunGame()//进行游戏
{
    int i,j,s=0;
    int flag=0;
    while(1)
    {
        system("cls");//清理屏幕,准备写入
        for(i=1;i<N+1;i++)
        {
            for(j=1;j<N+1;j++)
                if(chess[i][j]==1)
                    printf("");//printf("■");
                else if(chess[i][j]==0)
                    printf("  ");
            printf("
");
        }
        for(i=1;i<N+1;i++)
            for(j=1;j<N+1;j++)
            {
                cells_state(i,j);
            }
         for(i=1;i<N+1;i++)
            for(j=1;j<N+1;j++)
                chess[i][j]=chess0[i][j];
        Sleep(10);
        if(flag==0)
        {
            getchar();
            flag=1;
        }
    }
}
 
int count_cellsNumber(int xline,int yline)//计算生命周围的生命数量
{
    int living_cellsnumber=0,i,j;
    for(i=-1;i<=1;i++){
        for(j=-1;j<=1;j++){
            if(!(i==0&&j==0)&&chess[xline+i][yline+j]==1)
                living_cellsnumber++;
        }
    }return living_cellsnumber;
}

2)测试用例设计 (结合单元测试的内容和模块功能设计测试用例)

测试用例流程:需求文档分析>功能模块划分>测试用例编写>测试用例整理与维护

1.生命游戏需求分析:

  • 每个细胞的状态由该细胞及周围 8 个细胞上一次的状态所决定;

  • 如果一个细胞周围有 3 个细胞为生,则该细胞为生,即该细胞若原先为死则转为生,若原先为生则保持不变;

  • 如果一个细胞周围有 2 个细胞为生,则该细胞的生死状态保持不变;

  • 在其它情况下,该细胞为死,即该细胞若原先为生则转为死,若原先为死则保持不变。

2.生命游戏的功能划分:

Initialize()初始化功能,RunGame()进行游戏功能,count_cellsNumber()计算生命数量功能,Data()调用游戏数据功能

3.测试用例编写:

用例编号 1 2 3
测试数据 无细胞 全部都是细胞 一半是细胞,一半不是细胞
测试步骤

运行.c文件,出现细胞初始化情况,回车开始生命游戏,设置成无细胞情况:

技术图片

 

 

 

 运行.c文件,出现细胞初始化情况,会传染开始生命游戏,设置成全都是细胞的情况:

技术图片

 

 

 运行.c文件,出现细胞初始化情况,会传染开始生命游戏,设置成一半细胞的情况:

技术图片

 

 

预期结果  运行后无细胞产生  技术图片

 

 

 技术图片

 

 

实际结果  技术图片

 

 

 无

 

 

备注  源文件是按细胞随机生成编写的,极少数会出现0细胞情况,所以会有细胞产生  源文件无法设置,预期结果采用网页上的生命游戏给出   源文件无法设置,预期结果采用网页上生命游戏给出

3)选择的测试框架介绍、安装过程

一.PC-lint v9介绍:

  PC-lint/FlexeLint发现C和C+ +程序中的怪癖、异质、失灵和臭虫。这样分析的目的是发现这些程序中的在集成前的潜在的问题,揭示可能包含敏感的、未检测到的错误的不寻常的结构。因为它寻找几个模块而不仅仅是一个,可以发现编译器不能发现的事情。它通常比编译关于很多细节更爱挑剔。

  PC-LintC/C++软件代码静态分析工具,你可以把它看作是一种更加严格的编译器。它不仅可以检查出一般的语法错误,还可以检查出那些虽然符合语法要求但不易发现的潜在错误。

  PC-lint 中文手册:https://max.book118.com/html/2018/0202/151550624.shtm

二、安装过程:

 1.安装PC-lint v9.0:

技术图片 技术图片

 技术图片 技术图片

  技术图片 技术图片

技术图片 技术图片

2.PC-lint v9配置过程:

 技术图片 技术图片

技术图片技术图片

技术图片技术图片

 技术图片 技术图片

 技术图片 技术图片

 技术图片 技术图片

 技术图片 技术图片

 技术图片 技术图片

 技术图片

3.VC++6.0配置过程: 

PC-Lint与VC集成的方式就是在VC的集成开发环境中添加几个定制的命令,添加定制命令的方法是选择“工具”的“定制”命令,在弹出的定制窗口中选择“工具”标签,在定制工具命令的标签页中添加定制命令。

接下来主要是配置用PC-Lint检查当前的文件是否存在隐藏错误等,注意,命令里的路径是你的安装路径,后续的变量也是如此的,这一点切记,路径不同的话仅需将路径替换。似于配置环境变量,命令:D:softwarePC+lintlintlint-nt.exe;变量:-i"D:softwarePC+lintlint" -u std.lnt env-vc6.lnt "$(FileName)$(FileExt)";std.lnt是为VC编译环境定制的配置文件,$(FileName)和$(FileExt)是VC集成开发环境的环境变量,"$(FileName)$(FileExt)"表示当前文件的文件名。同时选中使用输出窗口选项。

 技术图片

如果要检查当前的整个项目的内容,这一步是必须的,首先需要将这个项目的错误导入到某个文件后,然后通过后一条命令即PCLint Current Project命令将文件中的内容输出。配置PCLint Export Project命令如下:命令:D:softwarePC+lintlintlint-nt.exe;变量:+linebuf$(TargetName).dsp>$(TargetName).lnt;参数+linebuf表示加倍行缓冲的大小,最初是600 bytes,行缓冲用于存放当前行和你读到的最长行的信息。$(TargetName)是VC集成开发环境的环境变量,表示当前激活的Project名字同时选中Use Output Window选项。

技术图片

配置PCLint Cuurent Project命令如下:命令:D:softwarePC+lintlintlint-nt.exe;变量:+ffn -i"D:softwarePC+lintlint" std.lnt env-vc6.lnt $(TargetName).lnt;这个命令的结果就是将整个工程的检查结果输出到与工程同名的.chk文件中。参数中+ffn表示Full File Names,可被用于控制是否使用的完整路径名称表示。同时选中Use Output Window选项

 技术图片

  配置完此项后,便在VC++ 6.0的Tools下出现上述配置的命令,此时PC-Lint关于VC++6.0的安装配置完成,读者可以利用这些命令对整个项目的进行安全性和错误性检查。

4 )测试代码

#include "stdio.h"
#include "string.h"
#include "windows.h"
#include "time.h"
 
#define N 49//1表示棋子,只有黑色棋子
 
int chess[N+2][N+2];//定义棋盘大小
int chess0[N+2][N+2];//辅助棋盘
 
 
void Initialize();//初始化一个对局函数
void RunGame();//进行游戏
int count_cellsNumber(int i,int j);//计算生命周围的生命数量
void Data();//调用已存的游戏数据
 
void main()
{
    system("mode con cols=99 lines=50");//设置窗口大小
    system("color 70");//设置颜色
    Initialize();//初始化一个对局函数
    RunGame();//进行游戏
}
 
void Initialize()//初始化一个对局函数
{
    Data();//调用已存的游戏数据
}
 
void Data()//调用已存的游戏数据
{
    int i,j;
    srand((unsigned)time(NULL));
    for(i=0;i<N;i++){
        for(j=0;j<N;j++)
            chess[i][j]=rand()%2;
    }
    /*
    int p=12;
    int l;
    for(l=-16;l<=16;l++)
        //if(l!=-8&&l!=0&&l!=4)
        chess[N/2+1][N/2+1+l]=1;
        */
 
/*
//滑翔机
chess[1][3]=1;chess[2][1]=1;chess[2][3]=1;chess[3][2]=1;chess[3][3]=1;
*/
/*
//高斯帕滑翔机
chess[1][p+11]=1;chess[1][p+13]=1;
chess[2][p+10]=1;chess[2][p+13]=1;
chess[3][p+9]=1;chess[3][p+10]=1;chess[3][p+21]=1;chess[3][p+28]=1;
chess[4][p+1]=1;chess[4][p+2]=1;chess[4][p+7]=1;chess[4][p+8]=1;chess[4][p+12]=1;chess[4][p+21]=1;chess[4][p+27]=1;chess[4][p+29]=1;
chess[5][p+1]=1;chess[5][p+2]=1;chess[5][p+9]=1;chess[5][p+10]=1;chess[5][p+20]=1;chess[5][p+27]=1;chess[5][p+28]=1;chess[5][p+30]=1;
chess[6][p+10]=1;chess[6][p+13]=1;chess[6][p+16]=1;chess[6][p+17]=1;chess[6][p+27]=1;chess[6][p+28]=1;chess[6][p+30]=1;chess[6][p+31]=1;chess[6][p+35]=1;chess[6][p+36]=1;
chess[7][p+11]=1;chess[7][p+13]=1;chess[7][p+16]=1;chess[7][p+19]=1;chess[7][p+20]=1;chess[7][p+21]=1;chess[7][p+22]=1;chess[7][p+27]=1;chess[7][p+28]=1;chess[7][p+30]=1;chess[7][p+35]=1;chess[7][p+36]=1;
chess[8][p+16]=1;chess[8][p+17]=1;chess[8][p+18]=1;chess[8][p+19]=1;chess[8][p+27]=1;chess[8][p+29]=1;
chess[9][p+17]=1;chess[9][p+18]=1;chess[9][p+28]=1;
*/
}
 
void cells_state(int i,int j)
{
    int living_cellsnumber=0;
    living_cellsnumber=count_cellsNumber(i,j);
    if(chess[i][j]==1){
        if(living_cellsnumber<2)
            chess0[i][j]=0;//如果一个生命周围的生命少于2个,它在回合结束后死亡。
        else if(living_cellsnumber>3)
            chess0[i][j]=0;//如果一个生命周围的生命超过3个,它在回合结束后死亡。
        else if(living_cellsnumber==2||living_cellsnumber==3)
            chess0[i][j]=1;//如果一个生命周围有2或3个生命,它在回合结束时保持原样。
    }
    else if(chess[i][j]==0){
        if(living_cellsnumber==3)
            chess0[i][j]=1;//如果一个死格周围有3个生命,它在回合结束时获得生命。
    }
}

void RunGame()//进行游戏
{
    int i,j,s=0;
    int flag=0;
    while(1)
    {
        system("cls");//清理屏幕,准备写入
        for(i=1;i<N+1;i++)
        {
            for(j=1;j<N+1;j++)
                if(chess[i][j]==1)
                    printf("");//printf("■");
                else if(chess[i][j]==0)
                    printf("  ");
            printf("
");
        }
        for(i=1;i<N+1;i++)
            for(j=1;j<N+1;j++)
            {
                cells_state(i,j);
            }
         for(i=1;i<N+1;i++)
            for(j=1;j<N+1;j++)
                chess[i][j]=chess0[i][j];
        Sleep(10);
        if(flag==0)
        {
            getchar();
            flag=1;
        }
    }
}
 
int count_cellsNumber(int xline,int yline)//计算生命周围的生命数量
{
    int living_cellsnumber=0,i,j;
    for(i=-1;i<=1;i++){
        for(j=-1;j<=1;j++){
            if(!(i==0&&j==0)&&chess[xline+i][yline+j]==1)
                living_cellsnumber++;
        }
    }return living_cellsnumber;
}

5)测试结果与分析

测试结果:

技术图片

 技术图片

 技术图片

分析:

a)include <stdio.h>表示搜索stdio.h这个文件的路径在option中指定的位置,include "stdio.h"表示搜索stdio.h这个文件的路径在当前工作文件所在的位置,即""与<>表示搜索的路径不同。

b).lnt(1)安装路径必须是绝对路径,或者把PC-Lint的安装路径放到系统的Path变量中。

6)push测试报告和测试代码到各自的github仓库

技术图片

技术图片

技术图片

 技术图片

 技术图片

三、思考题

比较以下二个工匠的做法,你认为哪种好?结合编码和单元测试,谈谈你的认识。

技术图片

答:我认为工匠一的做法比较好,我们平时在编写程序的时候,总是整面墙都砌完了,直接进行"集成测试",经常让整面的墙倒塌。而在软件项目中,在“砌砖”时以“水平线”为标准,会降低开发与需求理解的偏差、降低开发过程中的缺陷率、并还会提高bug定位速度。测试驱动开发的精髓在于: 将测试方案设计工作提前,在编写代码之前先做这一项工作; 从测试的角度来验证设计,推导设计; 同时将测试方案当作行为的准绳,有效地利用其检验代码编写的每一步,实时验证其正确性,实现软件开发过程的"小步快走"。 

四、实验小结

  本次实验为单元测试实验,我们小组的命题为生命游戏,使用的语言是c语言,使用的测试工具为PC-lint v9。通过本次实验初步掌握了测试用例的设计方法,掌握了单元测试的方法,学习了PC-lint v9的测试原理及框架;掌握了使用测试框架进行单元测试的方法和过程。

以上是关于实验测试单元的主要内容,如果未能解决你的问题,请参考以下文章

2018-2019-2 20175308实验二《面向对象程序设计》实验报告

单元测试 NPE,当我添加片段自定义转换时

实验二

实验单元测试

实验单元测试

实验五 单元测试