2010-05-10 40 views
5

Tôi bắt đầu với Hoạt động dựa trên số này ShakeActivity và tôi muốn viết một số xét nghiệm đơn vị cho nó. Tôi đã viết một số bài kiểm tra đơn vị nhỏ cho các hoạt động Android trước đây nhưng tôi không chắc chắn nên bắt đầu từ đâu. Tôi muốn nuôi gia tốc kế một số giá trị khác nhau và kiểm tra cách hoạt động phản ứng với nó. Bây giờ tôi giữ nó đơn giản và chỉ cập nhật một biến truy cập int riêng và một TextView khi một sự kiện "lắc" xảy ra.Tôi làm cách nào để kiểm tra Hoạt động trên Android hoạt động trên Accelerometer?

Vì vậy, câu hỏi của tôi chủ yếu nắm này:

Làm thế nào tôi có thể gửi dữ liệu giả để gia tốc từ một thử nghiệm đơn vị?

Trả lời

5

Giải pháp của tôi cho cách này kết thúc đơn giản hơn tôi mong đợi. Tôi không thực sự thử nghiệm gia tốc quá nhiều như tôi đang thử nghiệm phản ứng của ứng dụng với một sự kiện được gia tốc tăng lên, và tôi chỉ cần kiểm tra tương ứng. Lớp học của tôi thực hiện SensorListener và tôi muốn kiểm tra những gì xảy ra trênSensorChanged. Điều quan trọng sau đó là để nuôi một số giá trị và kiểm tra trạng thái Hoạt động của tôi. Ví dụ:

public void testShake() throws InterruptedException { 
    mShaker.onSensorChanged(SensorManager.SENSOR_ACCELEROMETER, new float[] {0, 0, 0}); 
    //Required because method only allows one shake per 100ms 
    Thread.sleep(500); 
    mShaker.onSensorChanged(SensorManager.SENSOR_ACCELEROMETER, new float[] {300, 300, 300}); 
    Assert.assertTrue("Counter: " + mShaker.shakeCounter, mShaker.shakeCounter > 0); 
} 
4

Tôi làm cách nào để gửi dữ liệu giả tới thiết bị thử nghiệm đơn vị là ?

AFAIK, bạn không thể.

Làm cho logic shaker của bạn chấp nhận nguồn dữ liệu có thể cắm được. Trong thử nghiệm đơn vị, cung cấp một mô hình. Trong sản xuất, cung cấp một wrapper xung quanh gia tốc.

Hoặc, đừng lo lắng về đơn vị kiểm tra bản thân máy lắc, mà là lo lắng về việc kiểm tra đơn vị những thứ sử dụng máy lắc, và tạo ra một máy lắc giả.

+0

Đó chắc chắn có ý nghĩa và có vẻ là một ý tưởng tốt hơn. Bạn có ví dụ về việc sử dụng "nguồn dữ liệu có thể cắm" như thế này không? –

+0

Câu trả lời này vẫn được cập nhật? Hoặc có một cái gì đó mới ra? – TinyTimZamboni

+1

@TinyTimZamboni: Tôi dường như nhớ lại rằng nhóm Android Tools đang nghiên cứu cách sử dụng thiết bị Android làm đầu vào cảm biến cho trình mô phỏng, nhưng tôi không biết vị trí đó ở đâu.Nếu không, tôi không biết bất kỳ cách nào để cung cấp đầu vào cảm biến giả. – CommonsWare

1

Vâng, bạn có thể viết giao diện.

interface IAccelerometerReader { 
    public float[] readAccelerometer(); 
} 

Viết AndroidAccelerometerReaderFakeAccelerometerReader. Mã của bạn sẽ sử dụng IAccelerometerReader nhưng bạn có thể trao đổi trong trình đọc Android hoặc Fake.

0

Không cần phải thử nghiệm gia tốc của hệ điều hành, chỉ cần kiểm tra logic của riêng bạn mà phản ứng với hệ điều hành - nói cách khác SensorListener của bạn. Thật không may SensorEvent là tư nhân và tôi không thể gọi SensorListener.onSensorChanged(SensorEvent event) trực tiếp, vì vậy phải SensorListener lớp con đầu tiên với lớp của riêng tôi, và gọi phương thức của riêng tôi trực tiếp từ các bài kiểm tra:

public class ShakeDetector implements SensorEventListener { 

    @Override 
    public void onSensorChanged(SensorEvent event) { 

     float x = event.values[0]; 
     float y = event.values[1]; 
     float z = event.values[2]; 

     onSensorUpdate(x, y, z); 
    } 

    public void onSensorUpdate(float x, float y, float z) { 
     // do my (testable) logic here 
    } 
} 

Sau đó, tôi có thể gọi onSensorUpdated trực tiếp từ mã thử nghiệm của tôi , mô phỏng việc bắn gia tốc.

private void simulateShake(final float amplitude, int interval, int duration) throws InterruptedException { 
    final SignInFragment.ShakeDetector shaker = getFragment().getShakeSensorForTesting(); 
    long start = System.currentTimeMillis(); 

    do { 
     getInstrumentation().runOnMainSync(new Runnable() { 
      @Override 
      public void run() { 
       shaker.onSensorUpdate(amplitude, amplitude, amplitude); 
      } 
     }); 
     Thread.sleep(interval); 
    } while (System.currentTimeMillis() - start < duration); 
} 
0
public class SensorService implements SensorEventListener { 
/** 
    * Accelerometer values 
    */ 
    private float accValues[] = new float[3]; 
    @Override 
    public void onSensorChanged(SensorEvent event) { 

      if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { 
      accValues[0] = sensorEvent.values[0]; 
      accValues[1] = sensorEvent.values[1]; 
      accValues[2] = sensorEvent.values[2]; 
     } 

    } 
} 

bạn có thể kiểm tra trên đoạn mã bằng cách làm theo cách

@Test 
    public void testOnSensorChangedForAcceleratorMeter() throws Exception { 
     Intent intent=new Intent(); 
     sensorService.onStartCommand(intent,-1,-1); 

     SensorEvent sensorEvent=getEvent(); 
     Sensor sensor=getSensor(Sensor.TYPE_ACCELEROMETER); 
     sensorEvent.sensor=sensor; 
     sensorEvent.values[0]=1.2345f; 
     sensorEvent.values[1]=2.45f; 
     sensorEvent.values[2]=1.6998f; 
     sensorService.onSensorChanged(sensorEvent); 

     Field field=sensorService.getClass().getDeclaredField("accValues"); 
     field.setAccessible(true); 
     float[] result= (float[]) field.get(sensorService); 
     Assert.assertEquals(sensorEvent.values.length,result.length); 
     Assert.assertEquals(sensorEvent.values[0],result[0],0.0f); 
     Assert.assertEquals(sensorEvent.values[1],result[1],0.0f); 
     Assert.assertEquals(sensorEvent.values[2],result[2],0.0f); 
    } 




private Sensor getSensor(int type) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { 
      Constructor<Sensor> constructor = Sensor.class.getDeclaredConstructor(new Class[0]); 
      constructor.setAccessible(true); 
      Sensor sensor= constructor.newInstance(new Object[0]); 

      Field field=sensor.getClass().getDeclaredField("mType"); 
      field.setAccessible(true); 
      field.set(sensor,type); 
      return sensor; 
     } 



private SensorEvent getEvent() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { 
     Constructor<SensorEvent> constructor = SensorEvent.class.getDeclaredConstructor(int.class); 
     constructor.setAccessible(true); 
     return constructor.newInstance(new Object[]{3}); 
    } 
Các vấn đề liên quan