51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1859|回复: 2
打印 上一主题 下一主题

安卓-Jacoco-精准测试应用

[复制链接]
  • TA的每日心情
    无聊
    2024-9-27 10:07
  • 签到天数: 62 天

    连续签到: 1 天

    [LV.6]测试旅长

    跳转到指定楼层
    1#
    发表于 2018-5-30 16:00:03 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
    不依赖源码执行
    接口测试也能直观看出覆盖度
    知道什么样的用例保证哪块的代码,更好的精准度测试





    1.实现jacoco Instrumentation操作(后面通过命令直接启动该instrument,最下面有),注意最后启动了 InstrumentedActivity

    复制代码
    1. <p>public class JacocoInstrumentation extends Instrumentation</p><p>
    2. </p><p> @Override</p><p>    public void onCreate(Bundle arguments) {</p><p>        super.onCreate(arguments);</p><p>        DEFAULT_COVERAGE_FILE_PATH = "/sdcard/cover.ec";</p><p>
    3. </p><p>        File file = new File(DEFAULT_COVERAGE_FILE_PATH);</p><p>        if (!file.exists()) {</p><p>            try {</p><p>                file.createNewFile();</p><p>            } catch (IOException e) {</p><p>                Log.d(TAG, "异常 : " + e);</p><p>                e.printStackTrace();</p><p>            }</p><p>        }</p><p>        if (arguments != null) {</p><p>            //mCoverage = getBooleanArgument(arguments, "coverage");</p><p>            mCoverageFilePath = arguments.getString("coverageFile");</p><p>        }</p><p>
    4. </p><p>        mIntent = new Intent(getTargetContext(), InstrumentedActivity.class);</p><p>        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);</p><p>        start();</p><p>    }</p>
    复制代码

    复制代码


    2.在InstrumentedActivity  onDestroy设置监听,当触发的时候触发生成jacoco覆盖率文件
    1. <p>
    2. </p><p><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  权限</p><p>复制代码</p><p>InstrumentedActivity extends MainActivity {</p><p>    public static String TAG = "InstrumentedActivity";</p><p>
    3. </p><p>    private FinishListener mListener;</p><p>
    4. </p><p>    public void setFinishListener(FinishListener listener) {</p><p>        mListener = listener;</p><p>    }</p><p>
    5. </p><p>
    6. </p><p>    @Override</p><p>    public void onDestroy() {</p><p>        Log.d(TAG + ".InstrumentedActivity", "onDestroy()");</p><p>        super.finish();</p><p>        if (mListener != null) {</p><p>            mListener.onActivityFinished();</p><p>        }</p><p>    }</p><p>
    7. </p><p>}</p>
    复制代码

    复制代码
    3.触发监听的操作

    复制代码
    1. <p>private void generateCoverageReport() {</p><p>        Log.d(TAG, "generateCoverageReport():" + getCoverageFilePath());</p><p>        OutputStream out = null;</p><p>        try {</p><p>            out = new FileOutputStream(getCoverageFilePath(), false);</p><p>            Object agent = Class.forName("org.jacoco.agent.rt.RT")</p><p>                    .getMethod("getAgent")</p><p>                    .invoke(null);</p><p>
    2. </p><p>            out.write((byte[]) agent.getClass().getMethod("getExecutionData", boolean.class)</p><p>                    .invoke(agent, false));</p><p>        } catch (Exception e) {</p><p>            Log.d(TAG, e.toString(), e);</p><p>        } finally {</p><p>            if (out != null) {</p><p>                try {</p><p>                    out.close();</p><p>                } catch (IOException e) {</p><p>                    e.printStackTrace();</p><p>                }</p><p>            }</p><p>        }</p><p>    }</p>
    复制代码


    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏1
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2024-9-27 10:07
  • 签到天数: 62 天

    连续签到: 1 天

    [LV.6]测试旅长

    3#
     楼主| 发表于 2018-5-30 16:01:14 | 只看该作者
    1.注册广播

    复制代码
    public void onReceive(Context context, Intent intent) {
            String url = intent.getStringExtra("url");
            if (Constants.mListener != null) {
                Constants.mListener.onActivityFinished();
                Toast.makeText(context,"notnull", 0).show();
            }else{
                Toast.makeText(context,url, 0).show();
            }
    }
    复制代码
    <receiver android:name="test.operationReceiver" android:enabled="true" android:exported="true">
                <intent-filter>
                    <action android:name="com.jacs.zhaotang.jscscs.operationReceiver" />
                </intent-filter>
            </receiver>
    发送广播:adb shell am broadcast -a com.jacs.zhaotang.jscscs.operationReceiver --es url 'sdsd'






    解析xml:

    需要提取的覆盖率类型

    复制代码
        public static final String INSTRUCTION="INSTRUCTION";
        public static final String BRANCH="BRANCH";
        public static final String LINE="LINE";
        public static final String COMPLEXITY="COMPLEXITY";
        public static final String METHOD="METHOD";
        public static final String[] COVERES={INSTRUCTION};

    复制代码


    复制代码
    // 获取当前节点的所有属性节点
            List<Attribute> list = node.attributes();
            // 遍历属性节点
            for (Attribute attr : list) {
                if (node.getName().equals("counter")) { // 节点等于 counter
                    if (needCollect(attr.getText()) || is) { // 当属性等于INSTRUCTION拿出covered                                        // INSTRUCTION                                                                    // 拿出该covered
                        is = true;
                    }
                    if (attr.getName().equals("covered") && is) {
                        String p=getFristAttributeText(node.getParent());
                        data += node.getParent().getName() + " -  "
                                + p + " ---  "
                                + currentCovered+"-"+attr.getName() + " ----- " + attr.getText()
                                + "  ";
                        is = false;
                        break;
                    }

                }

            }

    复制代码


    获取A和B两次代码的覆盖率

    复制代码
    method -  unRegisterObserver ---  INSTRUCTION-covered ----- 14  
    method -  getLastLocation ---  INSTRUCTION-covered ----- 18  
    method -  setCachedLocation ---  INSTRUCTION-covered ----- 0  
    method -  getCachedLocation ---  INSTRUCTION-covered ----- 11  
    method -  setCachedLocationTime ---  INSTRUCTION-covered ----- 0  
    method -  getCacheLocationTime ---  INSTRUCTION-covered ----- 11  
    method -  hasCachedLocation ---  INSTRUCTION-covered ----- 10  
    method -  <init> ---  INSTRUCTION-covered ----- 6  
    method -  onReceive ---  INSTRUCTION-covered ----- 10  
    Spent  785  //消耗时间

    打印A/B两次的不同覆盖值

    A:  class -  com/android/browser/AutoLoginLinearLayout ---  INSTRUCTION-covered ----- 20  
    B:  class -  com/android/browser/AutoLoginLinearLayout ---  INSTRUCTION-covered ----- 0  
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2024-9-27 10:07
  • 签到天数: 62 天

    连续签到: 1 天

    [LV.6]测试旅长

    2#
     楼主| 发表于 2018-5-30 16:00:56 | 只看该作者


    复制代码


    启动:

    2.1注册instrumentation,通过instrumentation启动被测应用
    1. <p>
    2. </p><p>adb shell am instrument com.jacs.zhaotang.jscscs/test.JacocoInstrumentation</p><p>
    3. </p><p>    <instrumentation</p><p>        android:handleProfiling="true"</p><p>        android:label="CoverageInstrumentation"</p><p>        android:name="test.JacocoInstrumentation"</p><p>        android:targetPackage="com.jacs.zhaotang.jscscs"/></p>
    复制代码



    3.把生成的jacoco覆盖率文件放在指定文件夹,用gradle生成htmlreport

    将该文件拖至入app根目录/build/outputs/code-coverage/connected下(文件夹没有的话可新建)

    运行gradlew jacocoTestReport

    复制代码
    1. <p>task jacocoTestReport(type: JacocoReport) {</p><p>    group = "Reporting"</p><p>    description = "Generate Jacoco coverage reports after running tests."</p><p>    reports {</p><p>        xml.enabled = true</p><p>        html.enabled = true</p><p>    }</p><p>    classDirectories = fileTree(</p><p>            dir: './build/intermediates/classes/debug',</p><p>            excludes: ['**/R*.class',</p><p>                       '**/*$InjectAdapter.class',</p><p>                       '**/*$ModuleAdapter.class',</p><p>                       '**/*$ViewInjector*.class'</p><p>            ])</p><p>    sourceDirectories = files(coverageSourceDirs)</p><p>    executionData = files("$buildDir/outputs/code-coverage/connected/coverage.ec")</p><p>
    2. </p><p>    doFirst {</p><p>        new File("$buildDir/intermediates/classes/").eachFileRecurse { file -></p><p>            if (file.name.contains('
    3. ))</p><p>            }</p><p>        }</p><p>    }</p><p>}</p>
    复制代码

    复制代码


    4.report路径:\jscscs\app\build\reports\jacoco\jacocoTestReport





    通过广播驱动生成ec:

    1. <div>
    2. </div>
    复制代码

    )) {</p><p>                file.renameTo(file.path.replace('
    ))</p><p>            }</p><p>        }</p><p>    }</p><p>}</p>[/code]
    复制代码


    4.report路径:\jscscs\app\build\reports\jacoco\jacocoTestReport





    通过广播驱动生成ec:

    1. <div>
    2. </div>
    复制代码

    , '
    复制代码


    4.report路径:\jscscs\app\build\reports\jacoco\jacocoTestReport





    通过广播驱动生成ec:

    1. <div>
    2. </div>
    复制代码

    ))</p><p>            }</p><p>        }</p><p>    }</p><p>}</p>[/code]
    复制代码


    4.report路径:\jscscs\app\build\reports\jacoco\jacocoTestReport





    通过广播驱动生成ec:

    1. <div>
    2. </div>
    复制代码

    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-11-25 22:36 , Processed in 0.072239 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表