java - ActivityInstrumentationTestCase2 问题 - 由于我正在为其编写测试的代码中的 invalidate() 调用导致测试挂起

标签 java android testing junit instrumentation

我正在对我编写的一些代码进行测试 提炼成下面粘贴的示例项目。 我遇到的问题是测试挂起测试运行器并且 我的测试用例中没有任何测试运行。

我已经将问题追踪到对 invalidate() 的调用 getChildStaticTransformation(View child, Transformation t) 我是 覆盖做一些缩放效果。

如果我注释掉对 invalidate() 的调用,那么测试就会运行。这 我调用 invalidate() 的原因是为了确保 View 得到 应用缩放效果后重新绘制。

如果我不调用 invalidate() 则 View 看起来不正确,直到 用户操作强制重新绘制屏幕。

两个问题:

  1. 为什么 invalidate() 会阻止测试运行?
  2. 我是否应该以不同的方式缩放我的 View ,而不是 需要调用 invalidate() 吗?

以下是 Eclipse Android 控制台的输出,显示位置 测试挂起:

[2011-08-19 13:51:27 - HelloGalleryTest]
------------------------------
[2011-08-19 13:51:27 - HelloGalleryTest] Android Launch!
[2011-08-19 13:51:27 - HelloGalleryTest] adb is running normally.
[2011-08-19 13:51:27 - HelloGalleryTest] Performing
android.test.InstrumentationTestRunner JUnit launch
[2011-08-19 13:51:27 - HelloGalleryTest] Automatic Target Mode: using
device '428024642BF9457'
[2011-08-19 13:51:27 - HelloGalleryTest] Uploading
HelloGalleryTest.apk onto device '428024642BF9457'
[2011-08-19 13:51:27 - HelloGalleryTest] Installing
HelloGalleryTest.apk...
[2011-08-19 13:51:29 - HelloGalleryTest] Success!
[2011-08-19 13:51:29 - HelloGalleryTest] Project dependency found,
installing: HelloGallery
[2011-08-19 13:51:29 - HelloGallery] Uploading HelloGallery.apk onto
device '428024642BF9457'
[2011-08-19 13:51:29 - HelloGallery] Installing HelloGallery.apk...
[2011-08-19 13:51:31 - HelloGallery] Success!
[2011-08-19 13:51:31 - HelloGalleryTest] Launching instrumentation
android.test.InstrumentationTestRunner on device 428024642BF9457
[2011-08-19 13:51:31 - HelloGalleryTest] Collecting test information
[2011-08-19 13:51:32 - HelloGalleryTest] Sending test information to
Eclipse
[2011-08-19 13:51:32 - HelloGalleryTest] Running tests...

下面是我写的示例项目代码和测试用例 展示了我上面描述的问题。 HelloGallery.getChildStaticTransformation(查看 child ,转换 t) 是调用 invalidate() 的方法。

下面包含的其他文件是为了完整起见,以备不时之需 尝试构建项目并观察我所描述的行为。

START::HELLO_GALLERY_PROJECT-FILES

HelloGallery.java

package com.hello;

import android.content.Context;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Transformation;
import android.widget.Gallery;

public class HelloGallery extends Gallery {

       private Camera mCamera = new Camera();

       /**
        * The position (index) of the centered view in the gallery.
        */
       public int mCenterViewPositionIndex;

       public HelloGallery(Context context, AttributeSet attrs) {
               super(context, attrs);
               this.setStaticTransformationsEnabled(true);
       }

       /**
        * {@inheritDoc}
        *
        * @see #setStaticTransformationsEnabled(boolean)
        */
       protected boolean getChildStaticTransformation(View child,
Transformation t) {
               t.clear();

               mCamera.save();
               final Matrix imageMatrix = t.getMatrix();
               int position = getPositionForView(child);
               t.setTransformationType(Transformation.TYPE_MATRIX);

               if (child == getSelectedView()) {
                       mCenterViewPositionIndex = position;

                       t.setAlpha(1f);
                       mCamera.translate(-20, 20, -200);
               }
               else if(((mCenterViewPositionIndex - 1) == position )) {
                       t.setAlpha(0.5f);
                       // no need to zoom this view.
               }
               else if((mCenterViewPositionIndex + 1) == position ) {
                       t.setAlpha(0.5f);
                       // no need to zoom this view.
               }

               else if(((mCenterViewPositionIndex - 2) == position )) {
                       t.setAlpha(0.35f);
                       mCamera.translate(0, 0, 250);
               }
               else if((mCenterViewPositionIndex + 2) == position ) {
                       t.setAlpha(0.35f);
                       mCamera.translate(0, 0, 250);
               }

               else if(((mCenterViewPositionIndex - 3) == position )) {
                       t.setAlpha(0.1f);
                       mCamera.translate(0, 0, 350);
               }
               else if((mCenterViewPositionIndex + 3) == position ) {
                       t.setAlpha(0.2f);
                       mCamera.translate(0, 0, 350);
               }else {
                       t.setAlpha(0.1f);
                       mCamera.translate(0, 0, 450);
               }

               mCamera.getMatrix(imageMatrix);
               mCamera.restore();
//              invalidate();  //  <----  commenting out this line allows the Test
to run.   Uncommenting this line will not allow the Test to run.

               return true;
       }
}

HelloGalleryActivity.java

package com.hello;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Gallery;

public class HelloGalleryActivity extends Activity implements OnItemClickListener {
    private Gallery mGallery;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mGallery=(Gallery)findViewById(R.id.gallery);

        //String array holding the values
        String [] text=new String[]{"Hello","Hi","Alloha","Bonjour","Hallo","¡Hola"};

        //Circular Array adapter to display our values in the gallery control
        HomeGalleryAdapter adapter = new HomeGalleryAdapter(this, R.layout.gallery_item_layout, text);
        mGallery.setAdapter(adapter);
        mGallery.setSelection(adapter.MIDDLE);
        mGallery.setOnItemClickListener(this);
        mGallery.setOnTouchListener(new OnTouchListener() {

            public boolean onTouch(View arg0, MotionEvent arg1) {
                Log.d("HelloGalleryActivity", " --> onTouch");
                return false;
            }
        });        
    }

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        Log.d("HelloGalleryActivity", " --> onItemClick");  
    }
}

HelloGalleryAdapter.java

package com.hello;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class HomeGalleryAdapter extends ArrayAdapter<String> {
       private LayoutInflater mLayoutInflater;
       private TextView mText;
       private int mLayoutId;

       public static final int HALF_MAX_VALUE = Integer.MAX_VALUE/2;
   public final int MIDDLE;
   private String[] mObjects;

       public HomeGalleryAdapter(Context context, int layoutId, String[]
lables) {
               super(context, 0, lables);

               mLayoutInflater = ((Activity) context).getLayoutInflater();
               mLayoutId = layoutId;

           mObjects = lables;
           MIDDLE = HALF_MAX_VALUE - HALF_MAX_VALUE % lables.length;
       }

       public int getCount() {
               return Integer.MAX_VALUE;
       }

       public String getItem(int position) {
               return mObjects[position % mObjects.length];
       }

       public long getItemId(int position) {
               return position % mObjects.length;
       }

       public View getView(int position, View convertView, ViewGroup group)
{
               if (convertView == null) {
                       convertView = mLayoutInflater.inflate(mLayoutId, group, false);
               }

               mText = (TextView) convertView.findViewById(R.id.gallery_item_text);

               mText.setText((String) getItem(position));
               mText.setTextColor(Color.WHITE);

               convertView.setTag(mText.getText());

               return convertView;
       }
}

res/layout/main.xml

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

       <TextView
               android:id="@+id/textview"
               android:layout_width="fill_parent"
               android:layout_height="wrap_content"
               android:text="@string/hello" />

       <com.hello.HelloGallery
               android:id="@+id/gallery"
               android:layout_gravity="center"
               android:spacing="0dp"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent" />
</LinearLayout>

res/layout/gallery_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/home_gallery_item_layout"
       android:orientation="vertical"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center">

       <RelativeLayout
               android:id="@+id/gallery_item_background"
               android:layout_width="100dip"
               android:layout_height="100dip"
               android:orientation="horizontal"
               android:background="@drawable/gallery_item_selector">

               <ImageView
                       android:src="@drawable/icon"
                       android:id="@+id/gallery_item_icon"
                       android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
                       android:layout_centerInParent="true" />

       </RelativeLayout>

       <TextView
               android:id="@+id/gallery_item_text"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_gravity="center"
               android:textSize="20sp" />
</LinearLayout>

res/drawable/gallery_item_selector.xml

 <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
          android:drawable="@drawable/background_selected" /> <!--
pressed -->
    <item android:drawable="@drawable/background_normal" /> <!--
default -->
 </selector>

res/drawable/background_normal.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
   <gradient
       android:startColor="#80000000"
       android:endColor="#80FFFFFF"
       android:angle="45"/>
   <padding android:left="7dp"
       android:top="7dp"
       android:right="7dp"
       android:bottom="7dp" />
   <corners android:radius="8dp" />
</shape>

res/drawable/background_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
   <gradient
       android:startColor="#80000000"
       android:endColor="#807EB6FF"
       android:angle="45"/>
   <padding android:left="7dp"
       android:top="7dp"
       android:right="7dp"
       android:bottom="7dp" />
   <corners android:radius="8dp" />
</shape>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
       xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.hello"
       android:versionCode="1"
       android:versionName="1.0">
       <uses-sdk
               android:minSdkVersion="7" />

       <application
               android:icon="@drawable/icon"
               android:label="@string/app_name">
               <activity
                       android:name=".HelloGalleryActivity"
                       android:label="@string/app_name">
                       <intent-filter>
                               <action
                                       android:name="android.intent.action.MAIN" />
                               <category
                                       android:name="android.intent.category.LAUNCHER" />
                       </intent-filter>
               </activity>

       </application>
</manifest>

END::HELLO_GALLERY_PROJECT-FILES

.

START::HELLO_GALLERY_TEST_PROJECT-FILES

HelloGalleryActivityTest.java(<----这个文件进入测试项目!!)

package com.hello.test;

import android.test.ActivityInstrumentationTestCase2;
import android.widget.Gallery;
import android.widget.SpinnerAdapter;

import com.hello.HelloGalleryActivity;

public class HelloGalleryActivityTest extends
ActivityInstrumentationTestCase2<HelloGalleryActivity> {
       private HelloGalleryActivity mActivity; // the activity under test
       private Gallery mGallery;
       private String[] mGalleryDataTestArray;
       private SpinnerAdapter mGalleryData;

       public HelloGalleryActivityTest() {
               super("com.hello", HelloGalleryActivity.class);
               mGalleryDataTestArray = new String[] { "Hello", "Hi", "Alloha",
"Bonjour", "Hallo", "¡Hola" };
       }

       @Override
       protected void setUp() throws Exception {
               super.setUp();
               setActivityInitialTouchMode(false);

               mActivity = this.getActivity();
               mGallery = (Gallery) mActivity.findViewById(com.hello.R.id.gallery);
               mGalleryData = (SpinnerAdapter) mGallery.getAdapter();
       }

       public void testPreconditions() {
               assertNotNull(mActivity);
               assertNotNull(mGallery);
               assertNotNull(mGallery.getOnItemClickListener());
               assertNotNull(mGalleryData);
       }

       public void testInitialGalleryPosition() {
               int position = mGallery.getSelectedItemPosition();
               String galleryItemLabel = (String)
mGallery.getItemAtPosition(position);

               assertEquals(mGalleryDataTestArray[0], galleryItemLabel);
       }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.hello.test"
     android:versionCode="1"
     android:versionName="1.0">
   <uses-sdk android:minSdkVersion="12" />
   <instrumentation android:targetPackage="com.hello"
android:name="android.test.InstrumentationTestRunner" />
   <application android:icon="@drawable/icon" android:label="@string/
app_name">

   <uses-library android:name="android.test.runner" />
   </application>
</manifest>

END::HELLO_GALLERY_TEST_PROJECT-FILE

最佳答案

尝试使用 postInvalidate() 而不是 invalidate()。

我不是 100% 确定发生了什么,但我怀疑您的代码中有某些东西阻塞了 UI 线程。使用 postInvalidate() 将立即返回并让您的代码完成,这将解锁 UI 线程。

关于java - ActivityInstrumentationTestCase2 问题 - 由于我正在为其编写测试的代码中的 invalidate() 调用导致测试挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7168527/

相关文章:

android - 无法在 React Native 的图像 slider 中获取和显示图像

testing - 缺陷和问题有什么区别?

database-design - 哪些工具可用于 TDDD(测试驱动数据库开发)?

Java .class 文件与 jar 中的 .java 文件

java - Apache SubnetInfo 用于环回地址

java - 动态创建的 Swing 组件的监听器

android - 事件时区值

Android 在 ListView 中从 URL 加载图像

iphone - 排除 UISpec 中的代码

java - 如何返回延迟实例化的动态网络元素