一、实验目的
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语言程序是否正确。用户界面是只能看见五个用例是否通过,没有测试用例的具体信息,我从来没想过这个用例是需要人为思考添加的。这次试验让我知道了一个程序更幕后的工作,也对”程序“的编写有了更多的了解,程序不仅仅是编写出来,测试等等这些“善后”的工作也帮助程序变得更加完善。