[android]android自动化测试十一之代码覆盖率报告EMMA

简介:
以下代码时监听测试程序结束后将Emma测试报告写入到虚拟机上,然后可以使用adb pull命令发送至硬盘上,这里需要测试程序集成Emma jar包,并需要修改ant build文件。
package com.example.instrumentation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.example.i2at.tc.TemperatureConverterActivity;
//import com.vladium.emma.rt.RT;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;

public class EmmaInstrumentation extends Instrumentation implements FinishListener {

    private static final String TAG = "EmmaInstrumentation";

    private static final boolean LOGD = true;

    private static final String DEFAULT_COVERAGE_FILE_PATH = "/mnt/sdcard/coverage.ec";

    private final Bundle mResults = new Bundle();

    private Intent mIntent;

    private boolean mCoverage = true;

    private String mCoverageFilePath;

    /**
     * Extends the AUT to provide the necessary behavior to invoke the
     * {@link FinishListener} that may have been provided using
     * {@link #setFinishListener(FinishListener)}.
     * 
     * It's important to note that the original Activity has not been modified.
     * Also, the Activity must be declared in the
     * <code>AndroidManifest.xml</code> because it is started by an intent in
     * {@link EmmaInstrumentation#onStart()}. This turns more difficult to use
     * other methods like using template classes. This latter method could be
     * viable, but all Activity methods should be re-written to invoke the
     * template parameter class corresponding methods.
     * 
     * @author diego
     * 
     */
    public static class InstrumentedActivity extends
    TemperatureConverterActivity {
        private FinishListener mListener;

        public void setFinishListener(FinishListener listener) {
            mListener = listener;
        }

        @Override
        public void finish() {
            if (LOGD)
                Log.d(TAG + ".InstrumentedActivity", "finish()");
            super.finish();
            if (mListener != null) {
                mListener.onActivityFinished();
            }
        }

    }

    /**
     * Constructor
     */
    public EmmaInstrumentation() {

    }

    @Override
    public void onCreate(Bundle arguments) {
        if (LOGD)
            Log.d(TAG, "onCreate(" + arguments + ")");
        super.onCreate(arguments);

        if (arguments != null) {
            mCoverage = getBooleanArgument(arguments, "coverage");
            mCoverageFilePath = arguments.getString("coverageFile");
        }

        mIntent = new Intent(getTargetContext(), InstrumentedActivity.class);
        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        start();
    }

    @Override
    public void onStart() {
        if (LOGD)
            Log.d(TAG, "onStart()");
        super.onStart();

        Looper.prepare();
        InstrumentedActivity activity = (InstrumentedActivity) startActivitySync(mIntent);
        activity.setFinishListener(this);
    }

    private boolean getBooleanArgument(Bundle arguments, String tag) {
        String tagString = arguments.getString(tag);
        return tagString != null && Boolean.parseBoolean(tagString);
    }

    private void generateCoverageReport() {
        if (LOGD)
            Log.d(TAG, "generateCoverageReport()");

        java.io.File coverageFile = new java.io.File(getCoverageFilePath());

        // We may use this if we want to avoid refecltion and we include
        // emma.jar
        // RT.dumpCoverageData(coverageFile, false, false);

        // Use reflection to call emma dump coverage method, to avoid
        // always statically compiling against emma jar
        try {
            Class<?> emmaRTClass = Class.forName("com.vladium.emma.rt.RT");
            Method dumpCoverageMethod = emmaRTClass.getMethod(
                    "dumpCoverageData", coverageFile.getClass(), boolean.class,
                    boolean.class);
            dumpCoverageMethod.invoke(null, coverageFile, false, false);
        } catch (ClassNotFoundException e) {
            reportEmmaError("Is emma jar on classpath?", e);
        } catch (SecurityException e) {
            reportEmmaError(e);
        } catch (NoSuchMethodException e) {
            reportEmmaError(e);
        } catch (IllegalArgumentException e) {
            reportEmmaError(e);
        } catch (IllegalAccessException e) {
            reportEmmaError(e);
        } catch (InvocationTargetException e) {
            reportEmmaError(e);
        }
    }

    private String getCoverageFilePath() {
        if (mCoverageFilePath == null) {
            return DEFAULT_COVERAGE_FILE_PATH;
        } else {
            return mCoverageFilePath;
        }
    }

    private void reportEmmaError(Exception e) {
        reportEmmaError("", e);
    }

    private void reportEmmaError(String hint, Exception e) {
        String msg = "Failed to generate emma coverage. " + hint;
        Log.e(TAG, msg, e);
        mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT, "\nError: "
                + msg);
    }

    /* (non-Javadoc)
     * @see com.example.instrumentation.FinishListener#onActivityFinished()
     */
    @Override
    public void onActivityFinished() {
        if (LOGD)
            Log.d(TAG, "onActivityFinished()");
        if (mCoverage) {
            generateCoverageReport();
        }
        finish(Activity.RESULT_OK, mResults);
    }

}


定义finish接口 
package com.example.instrumentation;

/**
 * Listen for an Activity to finish and invokes {@link #onActivityFinished()} when this happens.
 * 
 * @author diego
 *
 */
public interface FinishListener {

        /**
         * Invoked when the Activity finishes.
         */
        void onActivityFinished();

}


修改ant build.xml文件
 <!-- It only instruments class files, not any external libs -->
            <emma enabled="true">
               <instr verbosity="${verbosity}"
                               mode="overwrite"
                               instrpath="${out.absolute.dir}/classes"
                               outdir="${out.absolute.dir}/classes">
                    <!-- DTM: 2011-12-23: added filter for R -->
                     <filter excludes="*.R" />
                     <filter excludes="*.R$*" />
                </instr>
                <!-- TODO: exclusion filters on R*.class and allowing custom exclusion from
                             user defined file -->
</emma>


https://wiki.jenkins-ci.org/display/JENKINS/Building+an+Android+app+and+test+project 
http://dtmilano.blogspot.com/search/label/android
目录
相关文章
|
27天前
|
Java 测试技术 Android开发
Android性能测试——发现和定位内存泄露和卡顿
本文详细介绍了Android应用性能测试中的内存泄漏与卡顿问题及其解决方案。首先,文章描述了使用MAT工具定位内存泄漏的具体步骤,并通过实例展示了如何分析Histogram图表和Dominator Tree。接着,针对卡顿问题,文章探讨了其产生原因,并提供了多种测试方法,包括GPU呈现模式分析、FPS Meter软件测试、绘制圆点计数法及Android Studio自带的GPU监控功能。最后,文章给出了排查卡顿问题的四个方向,帮助开发者优化应用性能。
86 4
Android性能测试——发现和定位内存泄露和卡顿
|
4月前
|
Android开发 iOS开发
android自动化编译
android自动化编译
|
27天前
|
测试技术 Shell Android开发
Android 性能测试初探 (六)
本节聊聊性能测试的最后一项- 流量,当然我所指的性能测试是针对大部分应用而言的,可能还有部分应用会关注网速、弱网之类的测试,但本系列文章都不去一一探讨了。
40 6
|
27天前
|
JavaScript 测试技术 Android开发
Android 性能测试初探 (四)
本文介绍了GPU在移动端性能测试中的重要性,并详细解释了过度绘制、帧率和帧方差的概念。针对GPU测试,文章列举了三项主要测试内容:界面过度绘制、屏幕滑动帧速率和平滑度。其中,过度绘制测试需遵循特定标准,而帧速率和平滑度测试则可通过软件或硬件方法实现。在软件测试中,使用Systrace插件和高速相机是两种常用手段。对于不同机型,帧率及帧方差的测试标准也需相应调整。
35 5
|
27天前
|
测试技术 Shell Android开发
Android 性能测试初探 (三)
本文承接《Android性能测试初探(二)》,深入探讨CPU与内存测试。介绍了移动端内存测试的重要性及其测试目标,并详细列举了不同状态下应用内存消耗情况的测试项目。此外,还提供了多种内存测试方法,包括使用`procrank`等工具的具体操作步骤。最后,文章也简要提及了CPU测试的相关内容,帮助读者更好地理解Android性能测试的关键要素。
37 5
|
27天前
|
测试技术 Shell 定位技术
Android 性能测试初探 (五)
聊聊大家不常关注的测试项- 功耗
36 3
|
27天前
|
算法 测试技术 Android开发
Android 性能测试初探 (二)
上回大体介绍了下在 android 端的性能测试项,现在我们就细节测试项做一些阐述(包括如何自己 DIY 测试)
33 4
|
27天前
|
测试技术 API Android开发
Android 性能测试初探 (一)
Android 性能测试,跟pc性能测试一样分为客户端及服务器,但在客户端上的性能测试分为 2 类: 一类为 rom 版本的性能测试;一类为应用的性能测试。
40 3
|
1月前
|
Android开发
Android学习 —— 测试init.rc中的条件触发的处理顺序
Android学习 —— 测试init.rc中的条件触发的处理顺序
|
5月前
|
安全 物联网 测试技术
构建未来:Android与IoT设备的无缝交互深入探索软件自动化测试的未来趋势
【5月更文挑战第30天】在物联网(IoT)技术快速发展的当下,Android系统因其开放性和广泛的用户基础成为了连接智能设备的首选平台。本文将探讨如何通过现代Android开发技术实现智能手机与IoT设备的高效、稳定连接,并分析其中的挑战和解决方案。我们将深入挖掘Android系统的底层通信机制,提出创新的交互模式,并通过实例演示如何在Android应用中集成IoT控制功能,旨在为开发者提供一套可行的指导方案,促进IoT生态系统的进一步发展。