Sto provando a creare un test unitario per un'attività con molti metodi da testare. Ma dopo circa 31 test l'applicazione viene uccisa perché l'heap ha esaurito la memoria.Perché i test di unità di attività Android di grandi dimensioni non riescono?
1152 E SurfaceFlinger createSurface() failed, generateId = -12
1152 W WindowManager OutOfResourcesException creating surface
1152 I WindowManager Out of memory for surface! Looking for leaks...
1152 W WindowManager No leaked surfaces; killing applicatons!
1152 W ActivityManager Killing processes Free memory at adjustment 1
Ho fatto un test unitario con 40 semplici test-cases identici solo per trovare il problema. Ma sembra che il GC non sia abbastanza veloce da pulire la memoria durante i test.
Ecco il mio leaktest test-case:
package my.app;
import android.os.Debug;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
public class leakTest extends
ActivityInstrumentationTestCase2<TestActivityAndroid> {
String TAG = "leakTest";
TestActivityAndroid mActivity = null;
public leakTest() {
super(TestActivityAndroid.class);
}
protected void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
}
protected void tearDown() throws Exception {
super.tearDown();
}
private void printHeapSize() {
Log.e(TAG,
"NativeHeapAllocatedSize = "
+ Debug.getNativeHeapAllocatedSize());
Log.e(TAG, "NativeHeapFreeSize = " + Debug.getNativeHeapFreeSize());
Log.e(TAG, "NativeHeapSIZE = " + Debug.getNativeHeapSize());
}
public void test_1() {
assertNotNull(mActivity);
}
public void test_2() {
assertNotNull(mActivity);
}
public void test_3() {
assertNotNull(mActivity);
}
public void test_4() {
assertNotNull(mActivity);
}
public void test_5() {
assertNotNull(mActivity);
}
public void test_6() {
assertNotNull(mActivity);
}
public void test_7() {
assertNotNull(mActivity);
}
public void test_8() {
assertNotNull(mActivity);
}
public void test_9() {
assertNotNull(mActivity);
}
public void test_10() {
assertNotNull(mActivity);
}
public void test_11() {
assertNotNull(mActivity);
}
public void test_12() {
assertNotNull(mActivity);
}
public void test_13() {
assertNotNull(mActivity);
}
public void test_14() {
assertNotNull(mActivity);
}
public void test_15() {
assertNotNull(mActivity);
}
public void test_16() {
assertNotNull(mActivity);
}
public void test_17() {
assertNotNull(mActivity);
}
public void test_18() {
assertNotNull(mActivity);
}
public void test_19() {
assertNotNull(mActivity);
}
public void test_20() {
assertNotNull(mActivity);
}
public void test_21() {
assertNotNull(mActivity);
}
public void test_22() {
assertNotNull(mActivity);
}
public void test_23() {
assertNotNull(mActivity);
}
public void test_24() {
assertNotNull(mActivity);
}
public void test_25() {
assertNotNull(mActivity);
}
public void test_26() {
assertNotNull(mActivity);
}
public void test_27() {
assertNotNull(mActivity);
}
public void test_28() {
assertNotNull(mActivity);
}
public void test_29() {
assertNotNull(mActivity);
}
public void test_30() {
assertNotNull(mActivity);
}
public void test_31() {
assertNotNull(mActivity);
}
public void test_32() {
assertNotNull(mActivity);
}
public void test_33() {
assertNotNull(mActivity);
}
public void test_34() {
assertNotNull(mActivity);
}
public void test_35() {
assertNotNull(mActivity);
}
public void test_36() {
assertNotNull(mActivity);
}
public void test_37() {
assertNotNull(mActivity);
}
public void test_38() {
assertNotNull(mActivity);
}
public void test_39() {
assertNotNull(mActivity);
}
public void test_40() {
assertNotNull(mActivity);
}
}
L'attività di prova che si estende attività:
package my.app;
import android.app.Activity;
import android.os.Bundle;
public class TestActivityAndroid extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Ecco l'utilizzo della memoria in cui lo spazio libero nativo scende al di sotto 30kB e che il l'app viene uccisa.
Applications Memory Usage (kB): Uptime: 3804373 Realtime: 3804373
** MEMINFO in pid 7315 [my.app] **
native dalvik other total
size: 4048 3271 N/A 7319
allocated: 3942 2306 N/A 6248
free: 105 965 N/A 1070
(Pss): 844 1590 1806 4240
(shared dirty): 1404 4120 2288 7812
(priv dirty): 736 672 992 2400 Objects
Views: 0 ViewRoots: 0
AppContexts: 0 Activities: 0
Assets: 2 AssetManagers: 2
Local Binders: 11 Proxy Binders: 10
Death Recipients: 0
OpenSSL Sockets: 0
SQL
heap: 0 memoryUsed: 0
pageCacheOverflo: 0 largestMemAlloc: 0
Asset Allocations
zip:/data/app/my.app-1.apk:/resources.arsc: 1K
Qualcuno ha una soluzione migliore che i 2 secondi dormono all'interno di tearDown()? Non mi piace il sonno all'interno di tearDown(). E poiché abbiamo circa 100 test all'interno della nostra suite di test, i 2 secondi saranno un enorme ritardo.
Spero che qualcuno possa aiutarmi e se la mia domanda non è chiara per favore fatemelo sapere.
Grazie in anticipo.
Ciao, grazie per la risposta. Voglio una nuova attività pulita per ogni test nei nostri test attuali. In modo che il test precedente non possa influenzare il prossimo test. Ma trovo strano che un ritardo di 2 secondi corregge l'errore 'OutOfResourcesException creando superficie'. Sembra un bug in Android o qualcosa che non rilasci abbastanza velocemente le risorse di superficie. Ma per ora accetteremo il ritardo di 2 secondi mentre viene eseguito ogni giorno in una configurazione rapida. – kuipers