CI/CD技艺实践敏捷转型

单元测试并行运行实践

2017-12-11  本文已影响38人  而立不惑之年

1 问题提出

项目现在有775个用例,160个测试用例程序,ZCIP通过脚本UnitTest.sh执行用例程序,并获取用例统计信息。整个流程执行大概8分钟左右,在单元测试运行环境花费204秒,约分钟,将近50%。在后续测试不用不断增加下,这个比例会不断增高。
实现一个UnitTestNew.sh可以并行执行用例,值得研究,以下记录改造中解决的问题。

2 执行脚本重构

参考UnitTest.sh重新实现一个UnitTestNew.sh。

2.1子shell并行

将串行脚本并行化的方法比较,本次改造使用子shell,即() & wait的组合。示例代码如下:

for cur_gtest in $gtest_list
do
         echo "running ${cur_gtest} ..."
     logfile=../log/${cur_gtest}_${cur_time}.log
     (${cur_gtest} >${logfile} 
     if [ $? -gt 1 ]
     then
         echo "Run ${cur_gtest} Error!|${result_file_list}|1" 2>&1 | tee $1
         exit 0
     fi)&       
done
wait

2.2并发控制

为了防止所有程序一并执行,可以采用管道通信等方式进行进程数控制。这里给出一种简单实现,每执行10个用例,sleep 1s。来缓解并发数。(最终实现后,发现这一步其实没有必要,不控制也正常,当时出现问题是其他问题引起)

2.3统计信息问题

UnitTest.sh每执行完一个用例,就去分析日志,来获取用例执行结果打印出来。并累计全量数据,输出用例执行情况。
这种方式不适用于并行执行,在不同子进程执行后,统计系统是无法累计的。
实现思路,在脚本执行时,不再统计分析日志,在脚本执行结束后,分析全部日志并获取统计日志。

2.4其他改进

3用例中的典型问题

3.1串行并行的问题

完成脚本测试时,发现早期用例余额数据存在冲突的情况,早期基于RuleCache的数据需要取最新版本等情况,导致部分用例只能串行执行。
而后期改造基于新框架的用例由于运行指定版本,互不干扰,可以并行执行。
考虑用例命名差异,用例以utest_打头时,并行执行,否则就串行执行。

3.2新测试框架用例并行执行冲突问题

新测试框架用例在执行时会自己创建共享内存版本,执行用例,最后删除版本。
共享内存版本的Create,Destory接口存在临界点问题,并行执行会冲突,使用文件锁进行控制。
示例代码:

        int fd=-1;
        if ((fd = open("../file_lock.test",  O_RDWR|O_CREAT,0666)) == -1) //打开文件
        {
              cout<<"file open error!\n"<<errno<<endl;
              return false;
        }
        int iret=lockf(fd, F_LOCK,0); //文件加锁 
        if(iret==-1)
        {
           cout<<"flock error!\n"<<errno<<endl;
           return false;
        }
                ......
        close(fd); //关闭文件  

3.3用例创建RuleCache版本数问题

测试框架中gtest_RuleCache参考RuleCache应用的实现,包含了创建版本数的控制,在并行执行时,可能会突破这个数目,创建失败。因此取消gtest_RuleCache中对版本数控制。RuleCache的代码不受影响。

4测试结果

用time执行UnitTestNew.sh执行结果:
Pass(775)--Total(775)--Percentage(100.00%)<font color="#FF0000"></font>||0

real 1m16.967s
user 2m39.032s
sys 0m15.402s
相比较串行204秒有50%以上的提升,考虑后续用例基于新框架,这种优势会更加明显。

5小结

由于业务的复杂性,实现UnitTestNew.sh无法通用性的解决并行的问题。
但是通过规则给出用例并行执行思路,供参考。以上。

上一篇 下一篇

猜你喜欢

热点阅读