Home | History | Annotate | Download | only in runner
      1 /*
      2  * Copyright (C) 2013 DroidDriver committers
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.android.droiddriver.runner;
     18 
     19 import android.app.Activity;
     20 import android.os.Build;
     21 import android.os.Bundle;
     22 import android.test.AndroidTestRunner;
     23 import android.test.InstrumentationTestRunner;
     24 import android.test.suitebuilder.TestMethod;
     25 import android.util.Log;
     26 
     27 import com.android.internal.util.Predicate;
     28 import com.google.android.droiddriver.util.ActivityUtils;
     29 import com.google.android.droiddriver.util.Logs;
     30 import com.google.common.base.Supplier;
     31 import com.google.common.collect.Lists;
     32 import com.google.common.collect.Sets;
     33 
     34 import junit.framework.AssertionFailedError;
     35 import junit.framework.Test;
     36 import junit.framework.TestListener;
     37 
     38 import java.lang.annotation.Annotation;
     39 import java.util.Iterator;
     40 import java.util.List;
     41 import java.util.Set;
     42 
     43 /**
     44  * Adds activity watcher to InstrumentationTestRunner.
     45  */
     46 public class TestRunner extends InstrumentationTestRunner {
     47   private final Set<Activity> activities = Sets.newIdentityHashSet();
     48   private final AndroidTestRunner androidTestRunner = new AndroidTestRunner();
     49   private Activity runningActivity;
     50 
     51   /**
     52    * Returns an {@link AndroidTestRunner} that is shared by this and super, such
     53    * that we can add custom {@link TestListener}s.
     54    */
     55   @Override
     56   protected AndroidTestRunner getAndroidTestRunner() {
     57     return androidTestRunner;
     58   }
     59 
     60   /**
     61    * {@inheritDoc}
     62    * <p>
     63    * Adds a {@link TestListener} that finishes all created activities.
     64    */
     65   @Override
     66   public void onStart() {
     67     getAndroidTestRunner().addTestListener(new TestListener() {
     68       @Override
     69       public void endTest(Test test) {
     70         runOnMainSync(new Runnable() {
     71           @Override
     72           public void run() {
     73             Iterator<Activity> iterator = activities.iterator();
     74             while (iterator.hasNext()) {
     75               Activity activity = iterator.next();
     76               iterator.remove();
     77               if (!activity.isFinishing()) {
     78                 try {
     79                   Logs.log(Log.INFO, "Stopping activity: " + activity);
     80                   activity.finish();
     81                 } catch (RuntimeException e) {
     82                   Logs.log(Log.ERROR, e, "Failed to stop activity");
     83                 }
     84               }
     85             }
     86           }
     87         });
     88       }
     89 
     90       @Override
     91       public void addError(Test arg0, Throwable arg1) {}
     92 
     93       @Override
     94       public void addFailure(Test arg0, AssertionFailedError arg1) {}
     95 
     96       @Override
     97       public void startTest(Test arg0) {}
     98     });
     99 
    100     ActivityUtils.setRunningActivitySupplier(new Supplier<Activity>() {
    101       @Override
    102       public Activity get() {
    103         return runningActivity;
    104       }
    105     });
    106 
    107     super.onStart();
    108   }
    109 
    110   // Overrides InstrumentationTestRunner
    111   List<Predicate<TestMethod>> getBuilderRequirements() {
    112     List<Predicate<TestMethod>> requirements = Lists.newArrayList();
    113     requirements.add(new Predicate<TestMethod>() {
    114       @Override
    115       public boolean apply(TestMethod arg0) {
    116         MinSdkVersion minSdkVersion = getAnnotation(arg0, MinSdkVersion.class);
    117         if (minSdkVersion != null && minSdkVersion.value() > Build.VERSION.SDK_INT) {
    118           Logs.logfmt(Log.INFO, "filtered %s#%s: MinSdkVersion=%d", arg0.getEnclosingClassname(),
    119               arg0.getName(), minSdkVersion.value());
    120           return false;
    121         }
    122 
    123         UseUiAutomation useUiAutomation = getAnnotation(arg0, UseUiAutomation.class);
    124         if (useUiAutomation != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
    125           Logs.logfmt(Log.INFO,
    126               "filtered %s#%s: Has @UseUiAutomation, but ro.build.version.sdk=%d",
    127               arg0.getEnclosingClassname(), arg0.getName(), Build.VERSION.SDK_INT);
    128           return false;
    129         }
    130         return true;
    131       }
    132 
    133       private <T extends Annotation> T getAnnotation(TestMethod testMethod, Class<T> clazz) {
    134         T annotation = testMethod.getAnnotation(clazz);
    135         if (annotation == null) {
    136           annotation = testMethod.getEnclosingClass().getAnnotation(clazz);
    137         }
    138         return annotation;
    139       }
    140     });
    141     return requirements;
    142   }
    143 
    144   @Override
    145   public void callActivityOnDestroy(Activity activity) {
    146     super.callActivityOnDestroy(activity);
    147     activities.remove(activity);
    148   }
    149 
    150   @Override
    151   public void callActivityOnCreate(Activity activity, Bundle bundle) {
    152     super.callActivityOnCreate(activity, bundle);
    153     activities.add(activity);
    154   }
    155 
    156   @Override
    157   public void callActivityOnResume(Activity activity) {
    158     super.callActivityOnResume(activity);
    159     runningActivity = activity;
    160   }
    161 
    162   @Override
    163   public void callActivityOnPause(Activity activity) {
    164     super.callActivityOnPause(activity);
    165     if (activity == ActivityUtils.getRunningActivity()) {
    166       runningActivity = null;
    167     }
    168   }
    169 }
    170