zoukankan      html  css  js  c++  java
  • 自动化测试用例排序(三个算法随机、贪心、额外贪心)

    接着前面自动化测试的测试用例生成和收集,下面我们就需要做的是对测试用例进行排序,简单来说就是达到语句的全部覆盖。说到排序就涉及到三个算法,下面就是我对三个算法的阐述及代码实现。咱们由易入难。

    1’自动用例生成(使用Randoop)>

    2‘评价(对用例筛选冗余)>功能覆盖、语句覆盖(一般用后者)

               >插桩  (插入语句)

                  用Javassist实现自动插入语句

    3’测试用例排序排序>三种算法实现测试用例排序

        1‘  随机算法:测试用例会排序就是生成一个用例序列,随机算法就是随机生成一个测试用例序列

          下面是对序列进行打乱随机排序的两种方法:

    //(1)利用math的random方法
    List l=new ArrayList( input); //将input数组放入arraylist,input为集合 List res=new ArrayList(); //用来存放随机产生元素的结果 Random r=new Random();//随机数 int size=l.size(); for(int i=0;i<size;i++){ res.add(l.remove( r.nextInt(l.size()))); //为了保证不重复,每次随机产生后都删除该元素。 } //此时res中存放的就是随机排序的结果。
    //(2)利用collections的buffle方法
    import java.util.Collections;
    import java.util.LinkedList;
    import java.util.List;
     public class Test {
    List list = new LinkedList(); public static void main(String[] args) { List list = new LinkedList(); for ( int i = 0 ; i < 9 ; i ++ ) { list.add( " a " + i); } Collections.sort(list); // 顺序排列 System.out.println(list); Collections.shuffle(list); //随机打乱一个序列 System.out.println(list); Collections.reverse(list); // 倒序排列 System.out.println(list); System.out.println(Collections.binarySearch(list, " a5 " )); // 折半查找 }

         对此我简单的用list输入一个测试用例序列并进行随机排序,输出结果:   

    package testpaixu;
    
    import java.util.*;
    
    public class randomA {
    	public static void main(String args[]){
    		//测试用例数目
    		int N=6;	
    		List<Integer> lis=new ArrayList<Integer>();	
    		//添加测试用例1,2,3,4,5,6为序列
    		for(int i=1;i<=N;i++){
    			lis.add(i);
    		}
    		//输出原测试用例序列
    		System.out.println("测试用例序列:"+lis);
    		//随机排序
    		Collections.shuffle(lis);
    		System.out.println("随机排序后测试用例序列:"+lis);		
    	}
    }
    

        结果显示:

        

        2’·  贪心算法:

          一种能够得到某种度量意义下的最优解的分级处理方法,它总是做出在当前看来是最优的选择,也就是说贪心策略并不是从整体上加以考虑,它所做出的选择只是在某种意义上的局部最优解算法。   

          该算法存在问题:
    1. 不能保证求得的最后解是最佳的;
    2. 不能用来求最大或最小解问题;
    3. 只能求满足某些约束条件的可行解的范围。
          实现该算法的过程:
    从问题的某一初始解出发;
    while 能朝给定总目标前进一步 do
     求出可行解的一个解元素;
    由所有解元素组合成问题的一个可行解;      

        

    现在我用一个简单的覆盖矩阵进行代码实现:

        首先我在F:\目录下创建了一个txt文件,文件名 greedyA.txt,内容如下:

        

        (横向为四个测试用例,纵向为5个覆盖语句,0为未覆盖,1为已覆盖)

        首先我们先整体上对排序的逻辑过程进行考量一下,先从F:\greedyA.txt目录下读取文件,并置入数组,然后对每个测试用例进行相加,数字最大的为覆盖范围最大的,将此加入新的数组,并将该测试用例之和重置为-1,以此类推,直到序列排序完成。

        下面进行代码实现:

    package testpaixu;
    import java.io.*;
    import java.util.*;
    
    //贪婪算法
    public class greedyA {
    	public static void main(String args[]){
    		//test number
    		int tn=4;
    		String[] test=new String[tn];
    		//下标为测试用例-1,数字为测试用例覆盖范围
    		int[] sum=new int[tn];
    		for(int i=0;i<sum.length;i++){
    			sum[i]=0;		//初始化为0
    		}
    		
    		//读取测试用例覆盖矩阵
    		String filePath="F:\greedyA.txt";
    
    	        try {
    	                String encoding="GBK";
    	                File file=new File(filePath);
    	                   //判断文件是否存在
    	                if(file.isFile() && file.exists()){ 
    	                	//考虑到编码格式
    	                    InputStreamReader read = new InputStreamReader(	                   
    	                    						new FileInputStream(file),encoding);	                   	                    
    	                    BufferedReader br = new BufferedReader(read);	                    
    	                    String lineTxt = null;
    	                    
    	                    System.out.println("测试用例覆盖矩阵(横向测试用例,纵向覆盖语句(“0”未覆盖,“1”已覆盖)):");
    	                    while((lineTxt =br.readLine()) != null){
    	                    	//分解覆盖矩阵
    	                    	test=lineTxt.split(" ");	                    	
    	                    	System.out.println(test[0]+test[1]+test[2]+test[3]);
    	                    	//每个测试用例的覆盖范围
    	                    	sum[0]=sum[0]+Integer.parseInt(test[0]);
    	                    	sum[1]=sum[1]+Integer.parseInt(test[1]);
    	                    	sum[2]=sum[2]+Integer.parseInt(test[2]);
    	                    	sum[3]=sum[3]+Integer.parseInt(test[3]);	                    	
    	                    }	
    	                    read.close();
    	        }else{
    	            System.out.println("找不到指定的文件");
    	        }
    	        } catch (Exception e) {
    	            System.out.println("读取文件内容出错");
    	            e.printStackTrace();
    	        }	 
    
    	        System.out.println("测试用例1覆盖范围:"+sum[0]);
    	        System.out.println("测试用例2覆盖范围:"+sum[1]);
    	        System.out.println("测试用例3覆盖范围:"+sum[2]);
    	        System.out.println("测试用例4覆盖范围:"+sum[3]);
    	       	     
    	        //使用贪婪算法对测试用例集排序
    	        List<Integer> ls=new ArrayList<Integer>();	//初始化贪婪算法后序列
    	        int[] tests=new int[tn];
    	        for(int i=0;i<tests.length;i++){
    	        	tests[i]=i+1;	//测试用例集初始序列
    	        }
    	        int index=0;
    	        int max=sum[0];
    	        
    	        for(int j=0;j<sum.length;j++){
    	        //获取数组最大
    	        for(int i=0;i<sum.length;i++){
    	        	if(sum[i]>max){
    	        		max=sum[i];
    	        		index=i;
    	        					}
    	        }
    	        ls.add(tests[index]);
    	        sum[index]=-1;	
    	        max=sum[index];
    	        }	        
    	        System.out.println("测试用例集排序后序列:	"+ls);	        
    	}	       
    }
    			
    	
    

        运行结果:

      

    3‘  额外贪心:迭代的选取覆盖实体最多的实例,然后对于剩下的测试用例调整覆盖信息,把被选取的测试用例标记为“覆盖的”,重复此过程直至测试实体集中所有的实例都被标记为“覆盖的”。

      算法实现思想:对测试用例集的覆盖与未覆盖标记为“1”和“0”,获取测试用例集原始序列,对各测试的分布进行相加,结果最大的编入结果序列list2。起始设定两个序列list,一个全部为0记为slst,一个全部为1记为slst2。在求和获得最大的测试进行修改,将此项为1的全部编入slst;然后将slst中为1的对应项对所有测试用例集的对应项修改,将他们全部改为0(以便循环相加求和时不会冲突),以此循环直到slst==slst2为true。

             到此,还有一步完善,将结果序列与原始序列相比较,先前未排序的加入到结果序列末端。

      下面进行编译实现,同第二种算法一样,先于extragreedyA.txt中添加一个覆盖矩阵(横向为测试用例序列,纵向为覆盖语句序列),覆盖矩阵如下:

      

      代码实现如下:

    package testpaixu;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.util.*;
    
    //额外贪心算法
    public class extragreedyA {
    	public static void main(String args[]){
    		//test number
    		int tn=4;
    		//覆盖语句数量
    		int sn=5;
    		String[] test=new String[tn];
    		//下标为测试用例-1,数字为测试用例覆盖范围
    		int[] sum=new int[tn];
    		for(int i=0;i<sum.length;i++){
    			sum[i]=0;		//初始化为0
    		}
    		//测试用例的覆盖语句分布
    		ArrayList<Integer> lst1=new ArrayList<Integer>();
    		ArrayList<Integer> lst2=new ArrayList<Integer>();
    		ArrayList<Integer> lst3=new ArrayList<Integer>();
    		ArrayList<Integer> lst4=new ArrayList<Integer>();
    		List<ArrayList<Integer>> lst=new ArrayList<ArrayList<Integer>>();
    		lst.add(lst1);
    		lst.add(lst2);
    		lst.add(lst3);
    		lst.add(lst4);
    		
    		//初始化覆盖均为0,及均未覆盖
    		ArrayList<Integer> slst=new ArrayList<Integer>();
    		for(int i=0;i<sn;i++){
    		slst.add(0);	}
    		System.out.println("初始化语句均为未覆盖:"+slst);
    		//最后覆盖语句均为1
    		ArrayList<Integer> slst2=new ArrayList<Integer>();
    		for(int i=0;i<sn;i++){
    		slst2.add(1);	}
    
    		
    		//读取测试用例覆盖矩阵
    		String filePath="F:\extragreedyA.txt";
    
    	        try {
    	                String encoding="GBK";
    	                File file=new File(filePath);
    	                   //判断文件是否存在
    	                if(file.isFile() && file.exists()){ 
    	                	//考虑到编码格式
    	                    InputStreamReader read = new InputStreamReader(	                   
    	                    						new FileInputStream(file),encoding);	                   	                    
    	                    BufferedReader br = new BufferedReader(read);	                    
    	                    String lineTxt = null;
    	                    
    	                    System.out.println("测试用例覆盖矩阵(横向测试用例,纵向覆盖语句(“0”未覆盖,“1”已覆盖)):");
    	                    while((lineTxt =br.readLine()) != null){
    	                    	//分解覆盖矩阵
    	                    	test=lineTxt.split(" ");	                    	
    	                    	System.out.println(test[0]+test[1]+test[2]+test[3]);
    	                    	//每个测试用例的覆盖范围
    	                    	sum[0]=sum[0]+Integer.parseInt(test[0]);
    	                    	sum[1]=sum[1]+Integer.parseInt(test[1]);
    	                    	sum[2]=sum[2]+Integer.parseInt(test[2]);
    	                    	sum[3]=sum[3]+Integer.parseInt(test[3]);	
    	                    	//每个测试用例覆盖语句分布	               
    	                    	lst.get(0).add(Integer.parseInt(test[0]));
    	                    	lst.get(1).add(Integer.parseInt(test[1]));
    	                    	lst.get(2).add(Integer.parseInt(test[2]));
    	                    	lst.get(3).add(Integer.parseInt(test[3]));
    	                    }	
    	                    read.close();
    	        }else{
    	            System.out.println("找不到指定的文件");
    	        }
    	        } catch (Exception e) {
    	            System.out.println("读取文件内容出错");
    	            e.printStackTrace();
    	        }	
    	        //测试用例覆盖矩阵
    	        for(int i=0;i<tn;i++){
    	        	System.out.println("测试用例"+(i+1)+"覆盖范围:"+sum[i]+"分布:"+lst.get(i));
    	        }
    
    	       	     	        
    	        //使用额外贪婪算法对测试用例集排序
    	        ArrayList<Integer> ls=new ArrayList<Integer>();	//初始化贪婪算法后序列
    	        int[] lstsum;
    	        int add;
    	        int index;
    	        int max;
    	        boolean b=true;
    	        while(b){
    	        	//获得每个测试用例的覆盖范围
    	        	add=0;
    	        	lstsum=new int[tn];
    	        	for(int m=0;m<lst.size();m++){
    	    		for(int n=0;n<lst.get(m).size();n++){
    	    			int j=(Integer)lst.get(m).get(n);
    	    			add+=j;
    	    									}
    	    			lstsum[m]=add;
    	    			add=0;
    	        	}
    	        	//获取覆盖范围最大的测试用例
    	        	index=0;
    		        max=lstsum[0];
    		        
    		        //获取数组最大
    		        for(int i=0;i<lstsum.length;i++){
    		        	if(lstsum[i]>max){
    		        		max=lstsum[i];
    		        		index=i;
    		        				}
    		        }		        
    		        ls.add((index+1));
    		        //将初始序列覆盖范围改掉
    		        for(int i=0;i<slst.size();i++){
    		        	if(lst.get(index).get(i)==1){		        		
    		        		slst.set(i, 1);		       
    		        	}
    		        }		
    		        //将该序列覆盖的均改为0,并延至所有序列
    		        for(int i=0;i<lst.size();i++){
    		        	for(int j=0;j<lst.get(i).size();j++){
    		        		if(slst.get(j)==1){
    		        			lst.get(i).set(j, 0);
    		        			
    		        		}
    		        	}
    		        }	   
    		        max=-1;
    		        
    		        for(int i=0;i<slst.size();i++){
    		        	if(slst.get(i)!=slst2.get(i)){
    		        		b=true;break;
    		        	}
    		        	b=false;
    		        }	       	   	        
    	        }	     	        
    	        //如果排序后还有测试用例没有排序,要对tests[]的剩余进行添加
    	        ArrayList<Integer> tests=new ArrayList<Integer>();
    	        for(int i=0;i<tn;i++){
    	        	tests.add(i+1);
    	        }
    	        System.out.println("测试用例集排序前序列:	"+tests);
    	        for(int i=0;i<tests.size();i++){
    	        	if(!(ls.contains(tests.get(i)))){
    	        		ls.add(tests.get(i));
    	        	}
    	        }
    	        System.out.println("测试用例集排序后序列:	"+ls);
    	       
    	}	
    }
    

        显示结果:

        

    总结:

       自动化测试的整体步骤如下(目标为一个程序a.java):

       1‘先是利用randoop工具对程序自动生成测试用例,得到测试用例集文件(tests.java文件),并撰写生成报告(包含日期时间,原程序名称,测试数量及概述,操作时间等);

       2’其次,对源程序进行插桩(利用Javassist进行方法,语句插桩)得到文件(a.class,与原a.class文件不同,目录不在bin文件夹内);

       3’利用Java Runtime.exec()方法对测试用例集文件进行编译得到tests.class文件。

        (该方法使用方法博客网址:  http://www.cnblogs.com/mingforyou/p/3551199.html )

       运行tests.class查看每个测试用例插桩结果:

          a  获取覆盖信息(覆盖哪些语句,方法)并导入一个txt文件中方便查看、

          b  各个用例的覆盖率(方便用贪心算法和随机算法)、

          c  各个用例的覆盖分布(覆盖于未覆盖),已覆盖矩阵的形式导入txt文件中,以便运用额外贪心算法进行排序。

       并撰写收集报告(包含日期时间,源程序名称,测试用例集名称,以及该集合的覆盖率矩阵,操作时间等);

       4‘排序(三种算法),读取上一个步骤形成的两个txt文件,对覆盖率或者覆盖分布矩阵进行排序;

       5’收集排序结果,并撰写排序报告(包含日期时间,源程序名称,测试用例集名称,排序实现程序名称,测试用例集的覆盖分布,测试用例集的结果序列等)。

       题外话,过此我每个流程都进行了粗糙的代码实现,因此会对一个完整的程序进行完整的流程实现(自动生成测试用例,收集覆盖矩阵,排序,排序结果输出)。

  • 相关阅读:
    delphi 控制音量 静音的类
    delphi java 日期 转换 获取Unix时间戳
    UI颜色值
    ios10 no route to host
    VMWare MAC系统调整磁盘
    手机传文字到电脑
    Delphi JCL JEDI使用 jclDebug
    PS 使用首记 修改png图片的颜色
    delphi Style TBitmapLink
    delphi IOS 获取电池信息
  • 原文地址:https://www.cnblogs.com/1996swg/p/7194295.html
Copyright © 2011-2022 走看看