• 实验五 单元测试


    一、实验目的

    1)掌握单元测试的方法

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

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

    二、实验内容

    1、源码

    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 20
    //定义两个栈,分别存放运算数和运算符
    struct SNode_Num
    {
    int datas[MAX];
    int top;
    };
    typedef struct SNode_Num OperateNum;
    struct SNode_Symbol
    {
    char symbol[MAX];
    int top;
    };
    typedef struct SNode_Symbol OperateSymbol;

    //取出相应的数
    int GetOperateNum(OperateNum *StackNum)
    {
    return StackNum->datas[StackNum->top];
    }

    //取出相应运算符
    char GetOperateSymbol(OperateSymbol *StackSymbol)
    {
    return StackSymbol->symbol[StackSymbol->top];
    }

    //运算数进栈
    void PushOperateNum(OperateNum *StackNum, int x)
    {
    StackNum->top++;
    StackNum->datas[StackNum->top] = x;
    }

    //运算符进栈
    void PushOperateSymbol(OperateSymbol *StackSymbol, char ch)
    {
    StackSymbol->top++;
    StackSymbol->symbol[StackSymbol->top] = ch;
    }

    //运算数退栈
    int PopOperateNum(OperateNum *StackNum)
    {
    int num;
    num = StackNum->datas[StackNum->top];
    StackNum->top--;
    return num;
    }

    //运算符退栈
    char PopOperateSymbol(OperateSymbol *StackSymbol)
    {
    char ch;
    ch = StackSymbol->symbol[StackSymbol->top];
    StackSymbol->top--;
    return ch;
    }

    //判断输入的符号是否是四则运算符号
    int IsOperateSymbolOrNum(char ch)
    {
    if(ch == '+' || ch == '-' || ch == '*'|| ch == '/' || ch == ' ') return 1;
    else return 0;
    }

    //判断符号的优先级
    char Priority(char inputnum, char ch)
    {
    switch(inputnum)
    {
    //加减在同一个优先级上
    case '+':
    case '-':
    {
    if(ch == '+' || ch == '-') return '>';
    else if(ch == '*' || ch == '/') return '<';
    else return '>';
    }
    break;

    //乘除在同一优先级
    case '*':
    case '/':
    {
    if(ch == '+' || ch == '-') return '>';
    else if(ch == '*' || ch == '/') return '>';
    else return '>';
    }
    break;

    case ' ':
    {
    if(ch == ' ') return '=';
    else return '<';
    }
    break;
    }
    }
    int Calculate(int num1, char ch, int num2)
    {
    int result;
    switch(ch)
    {
    case '+':
    result = num1 + num2;
    break;
    case '-':
    if(num1<num2)
    result=-1000;
    else
    result=num1-num2;
    break;
    case '*':
    result = num1 * num2;
    break;
    case '/':
    if(num1%num2==0)
    result = num1 / num2;
    else
    result=-1000;
    }
    return result;
    }
    //用于用户输入和计算结果
    int MainCalc()
    {
    //主函数进行计算
    OperateNum datas;
    OperateSymbol symbol;
    int num1, num2, result, num;
    char ch, sign;
    //初始化顺序栈
    datas.top=-1; //操作数栈顶指针
    symbol.top=-1; //操作符栈顶指针
    //把回车计算的操作符放在栈中
    PushOperateSymbol(&symbol, ' ');
    ch = getchar();
    while((ch != ' ') || (GetOperateSymbol(&symbol) != ' '))
    {
    if(!IsOperateSymbolOrNum(ch))
    {
    num = atoi(&ch); //将字符转换为整数
    ch = getchar(); //获取输入
    while(!IsOperateSymbolOrNum(ch))
    {
    num = num * 10 + atoi(&ch);
    ch = getchar(); //当没有输入回车时,继续获取输入
    }
    PushOperateNum(&datas, num);
    }
    else
    {
    //考虑第一个数是负数的情况
    if(ch=='-'&&symbol.top==0&&datas.top==-1)PushOperateNum(&datas, 0);
    switch(Priority(GetOperateSymbol(&symbol), ch))
    {
    //判断优先级后进行计算
    case '<':
    PushOperateSymbol(&symbol, ch);
    ch = getchar();
    break;
    case '=':
    sign = PopOperateSymbol(&symbol);
    ch = getchar(); //获取输入
    break;
    case '>':
    sign = PopOperateSymbol(&symbol);
    num2 = PopOperateNum(&datas);
    num1 = PopOperateNum(&datas);
    result = Calculate(num1, sign, num2);
    PushOperateNum(&datas, result);
    break;

    }
    }
    }
    result = GetOperateNum(&datas);
    return result;
    }

    int main(int argc, char *argv[])
    {
    int result,cj=0,answer,i;

    for(i=0;i<10;){
    getchar();
    printf("请第%d出题:",i+1);
    result = MainCalc();
    if(result>=0){
    i++;
    printf("请输入你的答案:");
    scanf("%d",&answer);
    if(result==answer){
    cj+=10;
    printf("恭喜您答对了 ");
    }
    else{
    printf("哦,您答错了,正确答案是:%d ",result);
    }
    }
    else{
    printf("不符合规则,请重新出题 ");
    }

    }
    printf("您答对了%d题 ",cj/10);
    printf("您的总分为%d ",cj);
    }

    2、测试用例设计

    四则混合运算中运算顺序的问题

    测试用例:2+3*2

    运算结果出现分数会不报错

    测试用例:7/3

     

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

    一个MinUnit测试实例是一个通过测试则返回0(NULL)的函数。如果测试失败,这个函数应该返回一个测试失败的描述字符串。mu_assert 是一个当表达式失败时返回字符串的宏。而宏mu_runtest重复调用测试实例直到测试实例失败。这就是MinUnit的全部。就没有安装过程了

      4 测试代码

    运行测试

    mu_run_test(test)

    运行测试函数 int test();同时统计成功和失败的次数

    mu_test_results()

    显示测试结果,包括成功和失败的测试数量

      5测试结果与分析

     创建一个miniunit.h文件,并在主程序中调用即可。

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

    我的github地址:https://github.com/zhanglingluan233/-

     图上所示的四则运算是我的代码。

    思考题

    我是觉得工匠一的做法比较好,

    根据我查阅的资料:

    作者:腾讯技术工程
    链接:https://www.zhihu.com/question/28729261/answer/1058317111
    来源:知乎

    下面这张图,来自微软的统计数据:bug在单元测试阶段被发现,平均耗时3.25小时,如果漏到系统测试阶段,要花费11.5小时。

    下面这张图,旨在说明两个问题:85%的缺陷都在代码设计阶段产生,而发现bug的阶段越靠后,耗费成本就越高,指数级别的增高。所以,在早期的单元测试就能发现bug,省时省力,一劳永逸,何乐而不为呢

    由上述说明已经非常明确的表明了,不论是砌砖,还是编写程序,越晚发现错误,越会花费更多的时间精力和金钱,所以要做好单元测试,虽然他会花费一些时间,但是为了代码可以重复运行,要做好维护。

    小结

    1、针对C语言的测试框架相比其他语言要少一些,开始打算使用CUnit,结果网上面找不到CUnit的源码包,CUnit官网也打不开,可能是我的问题。或许是更多的新语言出现了?网络上对这个软件的教程都是很多年前的了。我最后使用了miniuint框架。

    2、C语言的测试框架与Java、python有很大不同。比如JUnit就是全功能的单元测试模板。

    3、我之前在一个网站上做过C语言的练习题,它就是可以自动测试我编写的C语言程序是否正确。用户界面是只能看见五个用例是否通过,没有测试用例的具体信息,我从来没想过这个用例是需要人为思考添加的。这次试验让我知道了一个程序更幕后的工作,也对”程序“的编写有了更多的了解,程序不仅仅是编写出来,测试等等这些“善后”的工作也帮助程序变得更加完善。

  • 相关阅读:
    USACO 3.3 A Game
    USACO 3.3 Camelot
    USACO 3.3 Shopping Offers
    USACO 3.3 TEXT Eulerian Tour中的Cows on Parade一点理解
    USACO 3.3 Riding the Fences
    USACO 3.2 Magic Squares
    USACO 3.2 Stringsobits
    USACO 3.2 Factorials
    USACO 3.2 Contact
    USACO 3.1 Humble Numbers
  • 原文地址:https://www.cnblogs.com/lingluan23333/p/13021861.html
Copyright © 2020-2023  润新知