背景:
提起随机自动化操作,相信大家并不陌生,目前使用最为普遍的adb monkey命令应该都有所耳闻。monkey优点不言而喻,它使用起来很简单,只需要在命令输入命令即可完成对app的各种随机操作,期间发现的崩溃也会捕获记录下来。但是在搜狗手机输入法项目中,这一方法就有些局限了:
1.输入法稳定性测试重点之一是输入各种语料内容,也就是输入ni'hao等比较有规律的词语,这一点monkey无法满足。
2.输入法稳定性测试需要定制有一些有序的动作,例如:输入ni'hao后,点击候选词文字进行上屏;又或者是切换输入键盘等。
3.以上2中定制的动作数量很多,希望能够在测试前进行灵活配置,例如:覆盖安装输入法权重低,打字上屏权重高。
基于以上几点,在搜狗手机输入法自动化测试中,我们设计了一种随机自动化的框架,与大家进行分享。
具体内容:
一、输入法随机自动化测试框架图:
二、随机操作稳定性主界面
主界面主要提供的功能是:
1.配置测试时间
2.控制随机自动化的开始和结束
3.配置随机动作的权重
private void initAction(){ if (mstrIme == "搜狗输入法"){ mExecCoreManager.AddPrepareAction("com.sogou.inputmethod.autotest.SogouInputTypeUtil.setDefaultIme"); }else{ mExecCoreManager.AddPrepareAction("com.sogou.inputmethod.autotest.BaiduInputTypeUtil.setDefaultIme"); } //切换拼音9键 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputSwitchKBUtil.switchPY9", 40); //切换拼音26键 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputSwitchKBUtil.switchPY26", 10); //切换笔画 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputSwitchKBUtil.switchBihua", 1); //切换英文9 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputSwitchKBUtil.switchEn9", 4); //切换英文26 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputSwitchKBUtil.switchEn26", 1); //随机打字并点击空格上屏 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputTypeUtil.tapRandomString_Candidate", 40); //随机打字并点击候选词上屏 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputTypeUtil.tapRandomString_Blank", 10); //纯随机点击 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputTypeUtil.randomTap", 100); //切换焦点到编辑框 mExecCoreManager.AddAction("com.sogou.inputmethod.autotest.SogouInputTypeUtil.tapEditControl", 5); mExecCoreManager.SetLogPath( StateValue.getDoraemonDir() + File.separator + "IMEStabilyTest.log"); mExecCoreManager.SetTempPath( StateValue.getDoraemonDir() + File.separator + "IMEStabilyTestTempindex.log"); }
三、ProbManager概率动作计算
假设我们要配置的动作列表如下:
通过map,记录每个Action的起始点和结束点,然后随机函数获取1到175(最大结束点)的随机数,这样即可得到对应权重的比例。
四、ExecCoremanager随机动作执行内核
1.随机动作序列的执行
class ExecThread implements Runnable { Thread t; private AtomicBoolean m_bFlagRun = new AtomicBoolean(); ExecThread() { t = new Thread(this, "ExecAction Thread"); System.out.println("Thread: " + t); this.m_bFlagRun.set(false); } public void run() { //1.执行前置操作 for(int i = 0; i< m_listPrepareActionList.size(); i++ ){ DoPrepare(i); } //2.循环执行随机动作 m_lStartTime = System.currentTimeMillis(); while (true) { //System.out.println("Running..."); //System.out.println(DoAction()); DoAction(); //3.定时记录执行的动作个数 m_iCountActionDone++; if( (m_iCountActionDone % 5) == 0 ){ SaveActionIndex(); } //4.检查执行时间是否已经到了 long currentTime = System.currentTimeMillis(); if ((currentTime - m_lStartTime) >= m_lInterval) { System.out.println("执行时间到,退出!"); break; } //5.检查执行停止是否被设置 if (!this.m_bFlagRun.get()) { System.out.println("执行被停止,退出!"); break; } } m_bRunningFlag = false; System.out.println("Exiting thread."); } public void start() { t.start(); this.m_bFlagRun.set(true); } public void stop() { this.m_bFlagRun.set(false); } }
2.反射方法调用包名下的方法
private String DoAction(){ String strActionName = null; String strAction = null; String strPackageName = null; //list中的动作已经执行完了,重头执行 if( m_iDoneActionIndex >= this.m_listActionList.size()){ m_iDoneActionIndex = 0; } strAction = this.m_listActionList.get(this.m_iDoneActionIndex); int beginIndex =strAction.lastIndexOf("."); strActionName = strAction.substring( beginIndex + 1, strAction.length()); strPackageName = strAction.substring(0, beginIndex); try { Method bMethod; Object bObj; if( m_mapReflict.containsKey(strPackageName)){ Class<?> bClazz = Class.forName(strPackageName); bObj = m_mapReflict.get(strPackageName); bMethod = bClazz.getDeclaredMethod(strActionName); }else{ Class<?> bClazz = Class.forName(strPackageName); bObj = bClazz.newInstance(); bMethod = bClazz.getDeclaredMethod(strActionName); m_mapReflict.put(strPackageName, bObj); } bMethod.invoke(bObj); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } this.m_iDoneActionIndex++; return strActionName; }
作者:搜狗测试 诸葛东明
来源:51Testing软件测试网原创