Проблемы ActivityInstrumentationTestCase2 - тест зависает из-за вызова invalidate () в коде, для которого я пишу тест - PullRequest
3 голосов
/ 24 августа 2011

Я реализую тест для некоторого написанного мною кода, который я перевел в пример проекта, вставленный ниже.Проблема, с которой я сталкиваюсь, заключается в том, что во время выполнения теста не выполняется тестовый прогон, и ни один из тестов в моем тестовом случае не выполняется.

Я отследил проблему до вызова invalidate () в getChildStaticTransformation (View child, Transformation)t) который я переопределяю, чтобы сделать некоторые эффекты масштабирования.

Если я закомментирую вызов invalidate (), то тесты будут запущены.Причина, по которой я вызываю invalidate (), заключается в том, чтобы убедиться, что представление перерисовывается после применения эффекта масштабирования.

Если я не вызываю invalidate (), то представление не будет выглядеть правильно до действия пользователязаставляет экран перерисовываться.

Два вопроса:

  1. Почему invalidate () блокирует запуск теста?
  2. Должен ли яделать масштабирование моего представления иначе, не требуя вызова 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 (View child, Transformation 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 (<---- этот файл входит в тестовый проект !!) </h2> 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

Ответы [ 2 ]

0 голосов
/ 18 февраля 2012

Проблема решена!

Неверный вызов НЕ нужен .. он портит ПЕРИОД!

Хитрость заключалась в том, чтобы добавить метод в HelloGallery.java для установки центральной позиции и вызова setPosition для суперкласса.

HelloGallery.java

public void setSelectionToCenter(int position) {
    mCenterViewPositionIndex = position;
    setSelection(mCenterViewPositionIndex);
}

Затем в HelloGalleryActivity вызывайте метод setSelectionToCenter, а не setSelection.

HelloGalleryActivity

public void onCreate(Bundle savedInstanceState) {
    ...
    ((HelloGallery)mGallery).setSelectionToCenter(adapter.MIDDLE);
    ...
}

Теперь тест проходит как очарование! Woot!
Спасибо Бетси, разработчику загадок, за то, что выследили это для меня!

0 голосов
/ 28 сентября 2011

Попробуйте postInvalidate () вместо invalidate ().

Я не уверен на 100%, что происходит, но я подозреваю, что в вашем коде есть что-то, что блокирует поток пользовательского интерфейса. Использование postInvalidate () вернет вас сразу, и ваш код завершится, что разблокирует поток пользовательского интерфейса.

...