回答几个问题
- 为什么是Emma
Emma是Android内置的覆盖率支持的库,Android的SDK本身就含有Emma.jar的二方库。不用考虑引用外部 - 插桩:基于代码还是基于编译出来的class
本方案基于代码的方案,不过对代码无大的侵入性,使用方案简单。没有使用class的后插桩方案的原因主要有3点:- 在编译大型Android的方案的时候class文件比较多,插桩操作繁杂。
- 插桩方案集成复杂: 涉及到在编译class之后,再重新打包和签名,所以过程要经过5,6步,比较麻烦不适合接入MTL等出集成包
- 后插桩的方式出问题不容易调查,另外android内置的emma.jar是2.1版本,不支持tcp的方案实时获取coverage.ec数据
现在方案
- 方案实现原理:
基于Android的BroadCast方案,定义特定的消息,然后使用反射的方式使用android sdk中本身的emma获取coverage.ec数据并保存在/mnt/sdcard中,随时操作随时获取
实施步骤:
1. 将此类放入到代码中,类代码如下:
// package net.sf.andbatdog.batterydog.EmmaInstrument;
package com.qa.emma;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
import java.lang.Exception;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class InstrumentedReceiver extends BroadcastReceiver {
public static String TAG = "EMMACoverageReport";
private static final String DEFAULT_COVERAGE_FILE_PATH = "/mnt/sdcard/coverage.ec";
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);
}
private void generateCoverageReport() {
Log.d(TAG, "generateCoverageReport()");
java.io.File coverageFile = new java.io.File(DEFAULT_COVERAGE_FILE_PATH);
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, true, false);
} catch (ClassNotFoundException e) {
reportEmmaError("Emma.jar not in the