首页 > 代码库 > 自动化脚本中运到的一些简单算法
自动化脚本中运到的一些简单算法
背景简介
在写一个自动化脚本时,要模拟发送网络请求,其中网络请求包含hid、md5、机器是64位还是32位等众多情况,而且这些因子还是不确定的,产品和开发可能会随时更改,这里我们就想通过自动化脚本根据这些因子全排列地自动去生成Case。
这里就怎么写个扩展性较好的生成全排列Case的代码,做下简单分享,具体前因后果请关注另外一篇文章(待发)。
问题分析
现在假设就下面这三个case
hid | md5 | 64位/32位 |
---|---|---|
123 | abc | 32 |
456 | cde | 64 |
现在又三个因子,每个因子2种情况,全排列就是8种,我们最容易想到的就是for循环,伪码如下:
for(hid)
for(md5)
for(64位/32位)
这样写起来简单,但是如果我们现在又加了一个因子,比如是否安装搜狗浏览器,这个带代码我们就需要去改了,得加一层循环。这样到最后代码不仅维护起来特别麻烦,而且不美观。
怎么办?
我想到的有两种解决办法:
递归解法
第一次在第一个数组去一个因子,递归调用去第二个数组取因子,直到取到最后一个数组,这时候就是一条完整的Case。然后每个数组遍历取元素,就可以得到所有路径了。
伪码如下(我们把所有因子以及对应的情况维护在一个文档,函数自己去文档按顺序读出所有因子,这部比较简单我就不多说了):
//dep表示当前是第几个因子,line代表一共有多少个因子void GetFullAz(int dep, int Line)
{
if(dep >= Line) //最后一个因子了
return;
for(int i = 1; i <= len(dep); i++) //遍历第dep个因子
GetFullAz(dep + 1,Line);
}
这里涉及一些路径记录的技巧,就不一一说说了,统一看附录代码
类似于状态压缩的解法
其实这里就是一个全状态为的枚举,我们用一位数记录一个因子的状态,最后将这些数合起来,从下到大枚举,得到的就是全状态。
示例:对于上面个例子,由于每个因子只有两种状态,我们就可以用三个二进制数来表示,那么合起来后就是一个三位的二进制数,最小值为0,最大值为7,我们从0枚举到7,就可以得到全状态。
伪码如下:
//将一个数字解码到各个位,以形成case,比如上面枚举0到7枚举到5时,先把5解码成101,让后去看101对应的情况,既:hid = 456 md5 = abc system = 64位void Decode(int state, int Line) //state当前状态位、line因子个数
{
printf("Case:%-4d ",CaseNum++);
for(int i = Line - 1; i >= 0; i--)
{
int Temp = state % FactorNum[i]; //FactorNum[i]第i个因子有多少种情况
state /= FactorNum[i];
cout<<CaseArr[i][0]<<" = "<<CaseArr[i][Temp+1]<<" ";
}
cout<<endl;
}
//枚举状态位for(int i = 0; i < State; i++)
{
Decode(i, Line);
}
总结
相信在做测试时我们遇到的有多因子的情况还是非常之多的,而且因子的改变也会经常发生,手工的话我们可以用一些工具生成正交试验或者就是全排列的用例,但是用自动化我们必须要去自己实现一遍对应的算法。这里给大家做下简单的分享,还望批评指正。
代码附录
/* * main.cpp * * Created on: 2014-12-9 * Author: fangyu */#include <functional>#include <algorithm>#include <iostream>#include <sstream>#include <iomanip>#include <numeric>#include <cstring>#include <cassert>#include <cstdio>#include <string>#include <vector>#include <bitset>#include <queue>#include <stack>#include <cmath>#include <ctime>#include <list>#include <set>#include <map>using namespace std; //#pragma comment(linker,"/STACK:102400000,102400000")string CaseArr[1000][100]; int FactorNum[1000], CaseNum; //递归解法vector<int> CasePath; void OutPut() { int Len = CasePath.size(); printf("Case:%-4d ",CaseNum++); for(int i = 0; i < Len; i++) { cout<<CaseArr[i][0]<<" = "<<CaseArr[i][CasePath[i]]<<" "; } cout<<endl; } void GetFullAz(int dep, int Line) { if(dep >= Line) { OutPut(); return; } for(int i = 1; i <= FactorNum[dep]; i++) { //cout<<CaseArr[Line][0]<<" = "<<CaseArr[Line][i]<<" "; //if(Line == 1) cout<<endl; CasePath.push_back(i); GetFullAz(dep + 1,Line); CasePath.pop_back(); } } //状态压缩解法void Decode(int state, int Line) { printf("Case:%-4d ",CaseNum++); //cout<<"Case:"<<CaseNum++<<" "; for(int i = Line - 1; i >= 0; i--) { int Temp = state % FactorNum[i]; state /= FactorNum[i]; cout<<CaseArr[i][0]<<" = "<<CaseArr[i][Temp+1]<<" "; } cout<<endl; } int main() { freopen("testin.txt","r",stdin); string FactorName; int Line = 0; int State = 1; while(cin>>FactorName) { cin>>FactorNum[Line]; State *= FactorNum[Line]; CaseArr[Line][0] = FactorName; for(int i = 1; i <= FactorNum[Line]; i++) { cin>>CaseArr[Line][i]; } Line++; //getchar(); } //递归 CasePath.clear(); CaseNum = 1; GetFullAz(0, Line); //状态压缩// CaseNum = 1;// for(int i = 0; i < State; i++)// {// Decode(i, Line);// } return 0; } /*testin.txt*/ Hid 3 11 22 33 Md5 3 qw as zx SE 2 有 无
总结
以上是对工作过程中的一个小问题,做的一些总结,欢迎大家提出建议或疑问,另外,想要获取更多信息,请关注公众号"搜狗测试"
自动化脚本中运到的一些简单算法