Android ActivityUnitTestCase如何整合目标应用程序';s AndroidManifest.xml?

Android ActivityUnitTestCase如何整合目标应用程序';s AndroidManifest.xml?,android,testing,Android,Testing,我有个活动,比如说 它在给定的应用程序及其相应的清单中定义。此活动仅通过静态R索引加载contentView。比如说R.layout.foo。该布局中碰巧有一个组件,用于查看非基本android属性的内容。我看到,当一个测试应用程序运行这个活动时,主题和主题中的样式没有填充任何内容 样本清单 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.

我有个活动,比如说

它在给定的应用程序及其相应的清单中定义。此活动仅通过静态R索引加载contentView。比如说R.layout.foo。该布局中碰巧有一个组件,用于查看非基本android属性的内容。我看到,当一个测试应用程序运行这个活动时,主题和主题中的样式没有填充任何内容

样本清单

   <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.foo.bar"
        android:versionCode="1"
        android:versionName="Test"
        android:installLocation="auto">

       <uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8" />
       <uses-permission android:name="android.permission.INTERNET" />

       <application 
                  android:icon="@drawable/app_icon"
              android:label="@string/app_name"
              android:description="@string/description"
              android:theme="@style/Theme.Custom"
              android:name=".MyApplicationObject">

          <activity android:name=".activity.A"/>

          <supports-screens
              android:smallScreens="true"
                  android:normalScreens="true"
                  android:largeScreens="true"
                  android:anyDensity="true" />
    </manifest>
A布局,foo.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
   <com.foo.bar.CustomView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
    />

</LinearLayout>
值文件中的某些资源

public class A extends Activity {
   public void onCreate(Bundle a) {
     setContentView(R.layout.foo);
   }
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- Used to define a namespace for our special types -->
    <declare-styleable name="CustomTypes">
        <attr name="CustomViewStyle" format="reference"/>
    </declare-styleable>

    <!-- Used to define Attributes specific to our new View, "CustomView" -->
    <declare-styleable name="CustomViewAttrs">
        <attr name="layout" format="reference"/>
        <attr name="anotherOne" format="reference"/>
    </declare-styleable>

    <!-- A usable style that we can reference later to pass to an instance of CustumView -->
    <style name="CustomView">
         <item name="layout">@layout/foo</item>
         <item name="AnotherOne">@drawable/icon</item>
    </style>

    <!-- A Style to act as our Theme, referenced in our Manifest as the Theme for all activities -->
    <style name="Theme.Custom" parent="android:Theme">
        <item name="CustomViewStyle">@style/CustomView</item>
    </style>
<resources>

@布局图/foo
@可绘图/图标
@样式/自定义视图
这很好,但当我使用ActivityUnitTest加载一个实例时,TypedArray中的值是空的

一些测试类

public class ActivityTester extends ActivityUnitTestCase<A> {
   public ActivityTester() {
     super(A.class);
   }

   public void testOne() {
      Intent intent = new Intent(getInstrumentation().getTargetContext(), A.class);
      // This fails with my IllegalStateException 
      startActivity(intent, null, null);
   }
}
公共类ActivityTester扩展ActivityUnitTestCase{
公共活动测试仪(){
超级(A级);
}
公共void testOne(){
Intent Intent=newintent(getInstrumentation().getTargetContext(),A.class);
//但我的非法国家例外
startActivity(意向、无效、无效);
}
}
知道目标应用程序如何/如果得到它的清单解析吗?似乎这个主题还没有加载。startActivity()的文档说明它将以与context.startActivity()相同的方式启动活动。我不认为会发生这种情况,因为它似乎不尊重活动的清单数据。

您可以改用它来测试使用系统基础结构创建的活动:

import android.test.ActivityInstrumentationTestCase2;

public class ActivityTester  extends ActivityInstrumentationTestCase2<ActivityTester> {
    public ActivityTester() {
        super(ActivityTester.class);
    }

    public void testOne() {
        //Intent intent = new Intent(getInstrumentation().getTargetContext(), ActivityTester.class);
        // This fails with my IllegalStateException 
        //startActivity(intent, null, null);
        getActivity();
    }
}
导入android.test.ActivityInstrumentationTestCase2;
公共类ActivityTester扩展ActivityInstrumentationTestCase2用于独立的单元测试活动


您的代码中还有一些其他错误,但我认为它们是复制此处删除某些部分的结果。

因此,在花费了大量时间尝试这样做之后,我发现,个人而言,最好的方法是模仿主题本身

   public void setUp() {
      ContextThemeWrapper context = new ContextThemeWrapper(getInstrumentation().getTargetContext(), R.style.Theme_MyTheme);
      setActivityContext(context);
   }

   public void testOne() {
      Intent intent = new Intent(getInstrumentation().getTargetContext(), A.class);
      startActivity(intent, null, null);
   }

就我个人而言,我不喜欢这样,因为它将单元测试实现与我想要抵消到另一个角色(如视觉设计师或图形艺术家)的风格细微差别结合起来,并增加了测试与即将发布的实现完全不同步的可能性。i、 e.有人更改清单文件,以便与
活动
关联的
主题
资源与正在测试的内容不同。这种测试用例类型看起来真的很短视,因为它可能会导致像这样的一系列糟糕的事情。我的意思是,您将得到一组测试基本功能的
ActivityUnitTestCase
实例,然后是同一
Activity
的一些测试用例,这些测试用例只是启动它或经历可能调用布局膨胀的转换。不是一个真正的应用程序正在测试

所以,当你说单元测试活动是孤立的,我的代码的哪一部分不这样做?我的意思是,如果调用onCreate()和onSaveInstanceState不是单独调用的方法,那么这个框架就有问题了。这甚至不能回答问题,也不能测试我想测试的两个东西。你怎么知道这不能测试你想测试的东西?你试过了吗?因为你刚刚创建了一个活动。我想实际测试一下我模拟出来的create。一次处于普通状态,一次从bundle状态恢复,一次使用非配置状态,一次使用提供的实例和非配置状态。所有这些我都可以嘲笑。你的解决方案基本上是说不要测试那些状态。嘿@Greg,你有没有找到解决你这个问题的方法?你介意把它贴出来作为回答吗?遗憾的是我没有。我个人想到的最多的方法是在测试上下文中手动设置主题。但即便如此,也不是很好-/该死的。:/也许你可以在这个问题上悬赏以吸引新的关注?谢谢!几个月来,我一直在寻找我为什么会遇到这个问题,以及可以做些什么来解决这个问题。
   public void setUp() {
      ContextThemeWrapper context = new ContextThemeWrapper(getInstrumentation().getTargetContext(), R.style.Theme_MyTheme);
      setActivityContext(context);
   }

   public void testOne() {
      Intent intent = new Intent(getInstrumentation().getTargetContext(), A.class);
      startActivity(intent, null, null);
   }