Sie sind auf Seite 1von 63

Tes$ng

 in  Android  
Android  Applica$on  Development  
•  Quality  measures  to  improve  the  development  process:  
–  Coding  standards  and  guidelines  
–  Regular  versioned  builds  
•  CVS,  SVN,  …  
–  Defect  tracking  system  
•  Logging  defects  and  process  for  resolving  defects  
–  Systema$c  applica$on  tes$ng  using  a  test  plan  
•  Good  test  plans  
•  Making  use  of  Android’s  tes$ng  framework  
–  Integrated  tes$ng  framework  that  helps  you  test  all  aspects  of  your  
applica$on  

COMP 355 (Muppala) Testing Embedded Systems 2


Android  Applica$on  Development  
•  Coding  standards:  
–  Common  way  of  handling  excep$ons  and  errors  
–  Moving  process-­‐intensive  opera$ons  off  the  main  UI  thread  
–  Release  objects  and  resources  that  aren’t  ac$vely  being  used  
–  Prudent  memory  management  and  tracking  memory  leaks  
–  Use  resources  appropriately  
•  Don’t  hard-­‐code  data  in  code  or  layout  files  

COMP 355 (Muppala) Testing Embedded Systems 3


Android  Specific  Tes$ng  Strategies  
•  Integra$on  Tes$ng  
–  Test  to  ensure  that  soQware  integrates  well  with  the  other  core  device  
features  
–  Suspend  and  resume  properly  
–  Gracefully  handle  interrupts  from  the  OS  (e.g.,  incoming  messages,  
calls,  power  off)  
•  Upgrade  Tes$ng  
–  Perform  tes$ng  on  device  upgrades  (firmware  and  OS)  
•  Interna$onaliza$on  Tes$ng  
–  Language  support  and  locale  support  
•  Usability  Tes$ng  
–  Naviga$on  and  ease-­‐of-­‐use  
–  Power  consump$on  

COMP 355 (Muppala) Testing Embedded Systems 4


Android  Specific  Tes$ng  Strategies  
•  Performance  Tes$ng  
–  Resource  and  memory  usage,  memory  leaks,  boWlenecks  
•  Conformance  Tes$ng  
–  Policies,  licensing  issues    
•  Edge-­‐case  Tes$ng  
–  Robustness  to  handle  random/unexpected  events  
•  Screen  Orienta$on  Change  Tes$ng  
–  Tes$ng  the  layout  and  proper  redrawing  of  screen  on  orienta$on  
changes  
•  Configura$on  Changes  Tes$ng  
–  Device  configura$on  changes  like  availability  of  keyboard,  system  
language  

COMP 355 (Muppala) Testing Embedded Systems 5


Android  Specific  Tes$ng  Strategies  
•  External  Resources  Dependence  Tes$ng  
–  Availability  of  network  access  (WiFi  or  GPRS/EDGE/3G)  if  required  by  
the  applica$on  
–  Adjus$ng  applica$on  behavior  to  available  network  features  
–  Similarly  SMS,  Bluetooth,  GPS  availability  
–  Graceful  handling  of  changes  in  availability  of  external  resources  

COMP 355 (Muppala) Testing Embedded Systems 6


Android  Tes$ng  Fundamentals  
•  Key  features  of  tes$ng  framework:  
–  Android  test  suites  are  based  on  Junit  
•  use  plain  JUnit  to  test  a  class  that  doesn't  call  the  Android  API  
•  Android's  JUnit  extensions  to  test  Android  components  
–  Provide  component-­‐specific  test  case  classes.  These  classes  provide  helper  
methods  for  crea$ng  mock  objects  and  methods  that  help  you  control  the  
lifecycle  of  a  component.  
–  Test  suites  are  contained  in  test  packages  that  are  similar  to  main  
applica$on  packages  
•  Don't  need  to  learn  a  new  set  of  tools  or  techniques  for  designing  and  
building  tests  
•  Part  of  Eclipse  IDE,  also  available  from  command  line  
–  Monkeyrunner  for  API  tes$ng  with  Python  programs,  UI/App  exerciser  
monkey  

COMP 355 (Muppala) Testing Embedded Systems 7


Android  Tes$ng  Fundamentals  

COMP 355 (Muppala) Testing Embedded Systems 8


JUnit  Tes$ng  
•  Android  tes$ng  is  based  on  Junit:  
–  JUnit  test  is  a  method  whose  statements  test  a  part  of  the  applica$on  
under  test  
–  You  organize  test  methods  into  classes  called  test  cases  (or  test  
suites).  
–  Each  test  is  an  isolated  test  of  an  individual  module  in  the  applica$on  
under  test  
–  Each  class  is  a  container  for  related  test  methods,  although  it  oQen  
provides  helper  methods  as  well.  
•  In  JUnit,  you  build  one  or  more  test  source  files  into  a  class  
file.  
–  Similarly,  in  Android  you  use  the  SDK's  build  tools  to  build  one  or  more  
test  source  files  into  class  files  in  an  Android  test  package  

COMP 355 (Muppala) Testing Embedded Systems 9


JUnit  Tes$ng  
•  In  JUnit,  you  use  a  test  runner  to  execute  test  classes  
–  In  Android,  you  use  test  tools  to  load  the  test  package  and  the  
applica$on  under  test,  and  the  tools  then  execute  an  Android-­‐specific  
test  runner.  
•  Junit  Assert  class  to  display  test  results  
–  The  assert  methods  compare  values  you  expect  from  a  test  to  the  
actual  results  and  throw  an  excep$on  if  the  comparison  fails  
–  Android  also  provides  a  class  of  asser$ons  that  extend  the  possible  
types  of  comparisons,  and  another  class  of  asser$ons  for  tes$ng  the  UI  

COMP 355 (Muppala) Testing Embedded Systems 10


Instrumenta$on  
•  Control  methods  or  "hooks"  in  the  Android  system.    
–  Enable  controlling  an  Android  component  independently  of  its  normal  
lifecycle  
–  Enable  control  how  Android  loads  applica$ons  
–  Enabling  for  tes$ng  code  to  invoke  lifecycle  callback  methods  like  
onCreate(),  onResume  etc.  directly  
•  Allowing  some  components  of  an  applica$on  to  run  in  a  separate  
process  
•  Invoke  callback  methods  in  your  test  code  
–  This  allows  you  to  run  through  the  lifecycle  of  a  component  step  by  step,  
as  if  you  were  debugging  the  component  
•  Instrumenta$on  can  load  both  a  test  package  and  the  applica$on  
under  test  into  the  same  process  
–  Enables  tests  to  invoke  methods  in  the  components,  and  modify  and  
examine  fields  in  the  components  

COMP 355 (Muppala) Testing Embedded Systems 11


Test  Case  Classes  
•  Several  test  case  classes  that  extend  TestCase  and  Assert  classes  of  
Java  with  Android-­‐specific  setup  
–  AndroidTestCase  provides  Junit-­‐standard  setUp()  and  tearDown()  
methods  and  Junit’s  Assert  methods  
–  Methods  for  tes$ng  permissions,  method  that  guards  against  memory  
leaks  
–  Component-­‐specific  test  cases  for  Ac$vity,  content  provider  and  service  
–  Applica$onTestCase  for  applica$on  object  setup  and  teardown  
–  Instrumenta$onTestCase  for  instrumenta$on  methods  usage  in  test  cases  
•  Addi$onal  Assert  classes  like  MoreAsserts  for  power  asser$ons,  and  
ViewAsserts  for  asser$ons  about  views  
•  Mock  object  classes  enables  dependency  injec$on  in  tes$ng  by  
crea$ng  mock  system  objects  such  as  context,  ContentProvider,  
ContentResolver  and  Intent  objects  

COMP 355 (Muppala) Testing Embedded Systems 12


Ac$vity  Tes$ng  

COMP 355 (Muppala) Testing Embedded Systems 13


Ac$vity  Tes$ng  
•  Ac$vi$es  have  complex  lifecycle  based  on  callback  methods:  
onCreate(),  onResume(),  onDestroy()  etc.  
•  Instrumenta$on  framework  enables  calling  these  methods  
directly  to  test:  
–  Ac$vity  tes$ng  dependent  on  the  instrumenta$on  framework  
–  No  other  possible  way  of  calling  methods  directly  
•  Instrumenta$on  enables  sending  UI  events  from  a  program  to  
the  applica$on  

COMP 355 (Muppala) Testing Embedded Systems 14


Ac$vity  Tes$ng  
•  Ac$vity  tes$ng  API  based  around  the  base  class  
Instrumenta$onTestCase  
•  Base  class  provides  these  func$ons:  
–  Lifecycle  control:  With  instrumenta$on,  you  can  start  the  ac$vity  
under  test,  pause  it,  and  destroy  it,  using  methods  provided  by  the  
test  case  classes.  
–  Dependency  injec$on:  Instrumenta$on  allows  you  to  create  mock  
system  objects  such  as  Contexts  or  Applica$ons  and  use  them  to  run  
the  ac$vity  under  test  
•  This  helps  you  control  the  test  environment  and  isolate  it  from  produc$on  
systems  
•  You  can  also  set  up  customized  Intents  and  start  an  ac$vity  with  them.  
–  User  interface  interac$on:  You  use  instrumenta$on  to  send  keystrokes  
or  touch  events  directly  to  the  UI  of  the  ac$vity  under  test.  

COMP 355 (Muppala) Testing Embedded Systems 15


Ac$vity  Tes$ng  
•  Also  provide  the  Junit  framework  by  extending  TestCase  and  
Assert  
•  Two  main  tes$ng  subclasses:  
–  Ac$vityInstrumenta$onTestCase2  
–  Ac$vityUnitTestCase  
–  For  other  than  standard  launches,  you  can  use  
SingleLaunchAc$vityTestCase  

COMP 355 (Muppala) Testing Embedded Systems 16


Ac$vityInstrumenta$onTestCase2  
•  Designed  to  do  func$onal  tes$ng  of  one  or  more  Ac$vi$es  in  
an  applica$on,  using  a  normal  system  infrastructure  
•  It  runs  the  Ac$vi$es  in  a  normal  instance  of  the  applica$on  
under  test,  using  a  standard  system  Context  
•  It  allows  you  to  send  mock  Intents  to  the  ac$vity  under  test,  
so  you  can  use  it  to  test  an  ac$vity  that  responds  to  mul$ple  
types  of  intents,  or  an  ac$vity  that  expects  a  certain  type  of  
data  in  the  intent,  or  both  
•  No$ce,  though,  that  it  does  not  allow  mock  Contexts  or  
Applica$ons,  so  you  can  not  isolate  the  test  from  the  rest  of  a  
produc$on  system.  

COMP 355 (Muppala) Testing Embedded Systems 17


Ac$vityUnitTestCase  
•  Tests  a  single  ac$vity  in  isola$on  
•  Before  you  start  the  ac$vity,  you  can  inject  a  mock  Context  or  
Applica$on,  or  both  
•  You  use  it  to  run  ac$vity  tests  in  isola$on,  and  to  do  unit  
tes$ng  of  methods  that  do  not  interact  with  Android  
•  You  can  not  send  mock  Intents  to  the  ac$vity  under  test,  
although  you  can  call  Ac$vity.startAc$vity(Intent)  and  then  
look  at  the  arguments  that  were  received  

COMP 355 (Muppala) Testing Embedded Systems 18


SingleLaunchAc$vityTestCase  
•  Convenience  class  for  tes$ng  a  single  ac$vity  in  an  
environment  that  doesn't  change  from  test  to  test  
•  It  invokes  setUp()  and  tearDown()  only  once,  instead  of  once  
per  method  call  
•  It  does  not  allow  you  to  inject  any  mock  objects.  
•  This  test  case  is  useful  for  tes$ng  an  ac$vity  that  runs  in  a  
mode  other  than  standard  
•  It  ensures  that  the  test  fixture  is  not  reset  between  tests  
•  You  can  then  test  that  the  ac$vity  handles  mul$ple  calls  
correctly.  

COMP 355 (Muppala) Testing Embedded Systems 19


Typical  Tests  on  Ac$vi$es  
•  Input  valida$on:  
–  Test  that  an  ac$vity  responds  correctly  to  input  values  in  an  EditText  
View  
•  Set  up  a  keystroke  sequence,  send  it  to  the  ac$vity,  and  then  use  
findViewById(int)  to  examine  the  state  of  the  View  
–  You  can  verify  that  a  valid  keystroke  sequence  enables  an  OK  buWon,  
while  an  invalid  one  leaves  the  buWon  disabled  
–  You  can  also  verify  that  the  Ac$vity  responds  to  invalid  input  by  
seeng  error  messages  in  the  View  

COMP 355 (Muppala) Testing Embedded Systems 20


Typical  Tests  on  Ac$vi$es  
•  Lifecycle  events:    
–  Test  that  each  of  your  applica$on's  ac$vi$es  handles  lifecycle  events  
correctly  
–  In  general,  lifecycle  events  are  ac$ons,  either  from  the  system  or  from  
the  user,  that  trigger  a  callback  method  such  as  onCreate()  or  onClick()  
–  For  example,  an  ac$vity  should  respond  to  pause  or  destroy  events  by  
saving  its  state  
–  Remember  that  even  a  change  in  screen  orienta$on  causes  the  
current  ac$vity  to  be  destroyed,  so  you  should  test  that  accidental  
device  movements  don't  accidentally  lose  the  applica$on  state.  

COMP 355 (Muppala) Testing Embedded Systems 21


Typical  Tests  on  Ac$vi$es  
•  Intents  
–  Test  that  each  ac$vity  correctly  handles  the  intents  listed  in  the  intent  
filter  specified  in  its  manifest  
–  You  can  use  Ac$vityInstrumenta$onTestcase2  to  send  mock  Intents  to  the  
ac$vity  under  test  
•  Run$me  configura$on  changes  
–  Test  that  each  ac$vity  responds  correctly  to  the  possible  changes  in  the  
device's  configura$on  while  your  applica$on  is  running  
–  These  include  a  change  to  the  device's  orienta$on,  a  change  to  the  
current  language,  and  so  forth.  
•  Screen  sizes  and  resolu$ons  
–  Before  you  publish  your  applica$on,  make  sure  to  test  it  on  all  of  the  
screen  sizes  and  densi$es  on  which  you  want  it  to  run  
–  You  can  test  the  applica$on  on  mul$ple  sizes  and  densi$es  using  AVDs,  or  
you  can  test  your  applica$on  directly  on  the  devices  that  you  are  
targe$ng.  

COMP 355 (Muppala) Testing Embedded Systems 22


Tes$ng  the  UI  
•  An  applica$on's  ac$vi$es  run  on  the  applica$on's  UI  thread  
•  With  instrumenta$on-­‐based  classes,  you  can  invoke  methods  
against  the  UI  of  the  applica$on  under  test  
–  The  other  test  classes  don't  allow  this  
•  To  run  an  en$re  test  method  on  the  UI  thread,  you  can  
annotate  the  thread  with  @UIThreadTest  
–  No$ce  that  this  will  run  all  of  the  method  statements  on  the  UI  thread  
–  Methods  that  do  not  interact  with  the  UI  are  not  allowed  
•  for  example,  you  cannot  invoke  Instrumenta$on.waitForIdleSync()  

COMP 355 (Muppala) Testing Embedded Systems 23


Tes$ng  the  UI  
•  To  run  a  subset  of  a  test  method  on  the  UI  thread  
–  create  an  anonymous  class  of  type  Runnable  
–  put  the  statements  you  want  in  the  run()  method,  and  
–  instan$ate  a  new  instance  of  the  class  as  a  parameter  to  the  method  
appAc&vity.runOnUiThread(),  where  appAc&vity  is  the  instance  of  the  
applica$on  you  are  tes$ng  
•  Example:  
mAc$vity.runOnUiThread(new  Runnable()  {  
                   public  void  run()  {  
                           mSpinner.requestFocus();  
                   }  
   });  

COMP 355 (Muppala) Testing Embedded Systems 24


Tes$ng  for  Key  Events  (Turning  off  Touch  
Mode)  
•  To  control  the  emulator  or  a  device  with  key  events  you  send  
from  your  tests,  you  must  turn  off  touch  mode  
–  If  you  do  not  do  this,  the  key  events  are  ignored.  
•  To  turn  off  touch  mode,  you  invoke  
Ac$vityInstrumenta$onTestCase2.setAc$vityTouchMode(fals
e)  before  you  call  getAc$vity()  to  start  the  ac$vity  
•  You  must  invoke  the  method  in  a  test  method  that  is  not  
running  on  the  UI  thread  
–  For  this  reason,  you  cannot  invoke  the  touch  mode  method  from  a  
test  method  that  is  annotated  with  @UIThread.  Instead,  invoke  the  
touch  mode  method  from  setUp().  

COMP 355 (Muppala) Testing Embedded Systems 25


Unlocking  the  Emulator  or  Device  
•  You  may  find  that  UI  tests  don't  work  if  the  emulator's  or  
device's  home  screen  is  disabled  with  the  keyguard  paWern  
–  This  is  because  the  applica$on  under  test  can't  receive  key  events  sent  
by  sendKeys()  
–  The  best  way  to  avoid  this  is  to  start  your  emulator  or  device  first  and  
then  disable  the  keyguard  for  the  home  screen.  
•  You  can  also  explicitly  disable  the  keyguard  
–  To  do  this,  you  need  to  add  a  permission  in  the  manifest  file  
(AndroidManifest.xml)  and  then  disable  the  keyguard  in  your  
applica$on  under  test  
–  Note,  though,  that  you  either  have  to  remove  this  before  you  publish  
your  applica$on,  or  you  have  to  disable  it  with  code  in  the  published  
applica$on.  

COMP 355 (Muppala) Testing Embedded Systems 26


Unlocking  the  Emulator  or  Device  
•  To  add  the  the  permission,  add  the  element  <uses-­‐permission  
android:name="android.permission.DISABLE_KEYGUARD"/>  
as  a  child  of  the  <manifest>  element  
•  To  disable  the  KeyGuard,  add  the  following  code  to  the  
onCreate()  method  of  ac$vi$es  you  intend  to  test:  
   mKeyGuardManager  =  (KeyguardManager)  
getSystemService(KEYGUARD_SERVICE);  
   mLock  =  mKeyGuardManager.newKeyguardLock("ac$vity_classname");  
   mLock.disableKeyguard();  

COMP 355 (Muppala) Testing Embedded Systems 27


Troubleshoo$ng  UI  Tests  
WrongThreadExcep3on  
•  Problem:  
–  For  a  failed  test,  the  Failure  Trace  contains  the  following  error  message:  
android.view.ViewRoot$CalledFromWrongThreadExcep$on:  Only  the  
original  thread  that  created  a  view  hierarchy  can  touch  its  views.  
•  Probable  Cause:  
–  This  error  is  common  if  you  tried  to  send  UI  events  to  the  UI  thread  from  
outside  the  UI  thread  
–  This  commonly  happens  if  you  send  UI  events  from  the  test  applica$on,  
but  you  don't  use  the  @UIThread  annota$on  or  the  runOnUiThread()  
method  
–  The  test  method  tried  to  interact  with  the  UI  outside  the  UI  thread.  
•  Suggested  Resolu$on:  
–  Run  the  interac$on  on  the  UI  thread.  
–  Use  a  test  class  that  provides  instrumenta$on  

COMP 355 (Muppala) Testing Embedded Systems 28


Troubleshoo$ng  UI  Tests  
java.lang.Run3meExcep3on  
•  Problem:  
–  For  a  failed  test,  the  Failure  Trace  contains  the  following  error  
message:  java.lang.Run$meExcep$on:  This  method  can  not  be  called  
from  the  main  applica$on  thread  
•  Probable  Cause:  
–  This  error  is  common  if  your  test  method  is  annotated  with  
@UiThreadTest  but  then  tries  to  do  something  outside  the  UI  thread  
or  tries  to  invoke  runOnUiThread().  
•  Suggested  Resolu$on:  
–  Remove  the  @UiThreadTest  annota$on,  remove  the  runOnUiThread()  
call,  or  re-­‐factor  your  tests.  

COMP 355 (Muppala) Testing Embedded Systems 29


Service  Tes$ng  

COMP 355 (Muppala) Testing Embedded Systems 30


Service  Tes$ng  
•  Tes$ng  framework  for  Service  objects  that  can  run  them  in  
isola$on  and  provides  mock  objects.  
•  The  test  case  class  for  Service  objects  is  ServiceTestCase  
•  Since  the  Service  class  assumes  that  it  is  separate  from  its  
clients,  you  can  test  a  Service  object  without  using  
instrumenta$on.  

COMP 355 (Muppala) Testing Embedded Systems 31


Service  Tes$ng  
•  When  you  design  a  Service,  you  should  consider  how  your  
tests  can  examine  the  various  states  of  the  Service  lifecycle  
•  If  the  lifecycle  methods  that  start  up  your  Service,  such  as  
onCreate()  or  onStartCommand()  do  not  normally  set  a  global  
variable  to  indicate  that  they  were  successful,  you  may  want  
to  provide  such  a  variable  for  tes$ng  purposes  
•  Most  other  tes$ng  methods  is  facilitated  by  the  methods  in    
the  ServiceTestCase  class  
–  For  example,  the  getService()  method  returns  a  handle  to  the  service  
under  test  
•  Test  to  confirm  that  the  service  is  running  even  at  the  end  of  your  tests  

COMP 355 (Muppala) Testing Embedded Systems 32


ServiceTestCase  
•  Extends  the  Junit  TestCase  class  with  the  methods  for  tes$ng  
applica$on  permissions  and  conrolling  applica$on  and  service  
under  test  
–  Also  provides  mock  applica$on  and  Context  objects  that  isolate  your  
test  from  the  rest  of  the  system  
•  Defers  ini$aliza$on  of  the  test  environment  un$l  you  call  
ServiceTestCase.startService()  or      
ServiceTestCase.bindService()  
–  Allows  you  to  set  up  your  test  environment,  especially  your  mock  
objects  before  the  service  is  started  

COMP 355 (Muppala) Testing Embedded Systems 33


ServiceTestCase  
•  Parameters  to  ServiceTestCase.bindService()are  different  from  
those  for  Service.bindService()  
–  For  the  ServiceTestCase  version,  you  only  provide  an  Intent  
–  Instead  of  returning  a  boolean,  ServiceTestCase.bindService()  returns  an  
object  that  subclasses  Ibinder  
•  setUp()  method  is  called  before  each  test  
–  Sets  up  the  text  fixture  by  making  a  copy  of  the  current  system  Context  
before  any  test  methods  touch  it  
–  Can  retrieve  the  context  by  calling  getSystemContext()  
•  setApplica$on()    and  setContext(Context)  allow  seeng  up  mock  
applica$on  or  mock  Context  
•  By  default,  ServiceTestCase  runs  the  test  method  
testAndroidTestCaseSetupProperly()  
–  Asserts  that  the  base  test  case  class  successfully  set  up  a  Context  before  
running  

COMP 355 (Muppala) Testing Embedded Systems 34


Mock  Object  Classes  
•  ServiceTestCase  assumes  that  you  will  use  a  mock  Context  or  mock  
Applica$on  (or  both)  for  the  test  environment  
–  These  objects  isolate  the  test  environment  from  the  rest  of  the  system  
•  If  you  don't  provide  your  own  instances  of  these  objects  before  you  
start  the  Service,  then  ServiceTestCase  will  create  its  own  internal  
instances  and  inject  them  into  the  Service  
–  You  can  override  this  behavior  by  crea$ng  and  injec$ng  your  own  
instances  before  star$ng  the  Service  
•  To  inject  a  mock  Applica$on  object:  
–  Create  a  subclass  of  MockApplica$on  
–  Inject  into  the  service  with  setApplica$on()  
–  Mock  objecta  llows  you  to  control  the  applica$n  values  that  the  service  
sees,  and  isolates  from  the  real  system  
•  Similarly  inject  mock  Context  using  setContext()  

COMP 355 (Muppala) Testing Embedded Systems 35


Tes$ng  a  Service  
•  Ensure  that  the  onCreate()  is  called  in  response  to  Context.startService()  
or  Context.bindService()  
•  Ensure  that  onDestroy()  is  called  in  response  to  Context.stopService(),  
Context.unbindService(),  stopSelf()  or  stopSelfResult()  
•  Test  that  your  Service  correctly  handles  mul$ple  calls  from  
Context.startService()  
–  Only  the  first  call  triggers  Service.onCreate(),  but  all  calls  trigger  a  call  to  
Service.onStartCommand().  
•  In  addi$on,  remember  that  startService()  calls  don't  nest,  so  a  single  call  to  
Context.stopService()  or  Service.stopSelf()  (but  not  stopSelf(int))  will  stop  
the  Service  
–  You  should  test  that  your  Service  stops  at  the  correct  point.  
•  Test  any  business  logic  that  your  Service  implements.  Business  logic  
includes  checking  for  invalid  values,  financial  and  arithme$c  calcula$ons,  
and  so  forth  

COMP 355 (Muppala) Testing Embedded Systems 36


Tes$ng  Content  
Providers  

COMP 355 (Muppala) Testing Embedded Systems 37


Tes$ng  Content  Providers  
•  In  Android,  content  providers  are  viewed  externally  as  data  APIs  
that  provide  tables  of  data,  with  their  internals  hidden  from  view  
•  A  content  provider  may  have  many  public  constants,  but  it  usually  
has  few  if  any  public  methods  and  no  public  variables.  
–  This  suggests  that  you  should  write  your  tests  based  only  on  the  provider's  
public  members  
–  A  content  provider  that  is  designed  like  this  is  offering  a  contract  between  
itself  and  its  users.  
•  The  base  test  case  class  for  content  providers,  ProviderTestCase2  
allows  you  to  test  your  content  provider  in  an  isolated  environment  
–  Android  mock  objects  such  as  IsolatedContext  and  MockContent  Resolver  
help  provide  an  isolated  test  environment  
–  Test  packages  run  under  the  control  of  the  test  runner  
Instrumenta$onTestRunner  

COMP 355 (Muppala) Testing Embedded Systems 38


Tes$ng  Content  Providers  
•  ProviderTestCase2  
–  Extends  AndroidTestCase,  so  provides  Junit  tes$ng  framework  
–  Ini$aliza$on  done  in  the  constructor  of  ProviderTestCase2  
•  Create  an  IsolatedContext  object  that  allows  file  and  database  opera$ons  
•  Creates  MockContextResolver  to  use  as  the  resolver  for  the  test  
•  Creates  an  instance  of  the  provider  under  test  

COMP 355 (Muppala) Testing Embedded Systems 39


Tes$ng  Content  Providers  
•  Test  with  Resolver  methods:  Always  test  with  a  resolver  object  
using  the  appropriate  URI  
•  Test  a  public  provider  as  a  contract:  
–  Test  with  constants  that  your  provider  publicly  exposes  
–  Test  all  the  URIs  offered  by  your  provider  
–  Test  invalid  URIs  
•  Test  the  standard  provider  interac$ons:  test  access  methods:  
query,  insert,  delete,  update,  getType  and  onCreate()  
•  Tes$ng  Business  logic:  
–  Business  logic  includes  handling  of  invalid  values,  financial  or  arithme$c  
calcula$ons,  elimina$on  or  combining  of  duplicates,  and  so  forth  
–  A  content  provider  does  not  have  to  have  business  logic,  because  it  may  
be  implemented  by  ac$vi$es  that  modify  the  data  
–  If  the  provider  does  implement  business  logic,  you  should  test  it.  

COMP 355 (Muppala) Testing Embedded Systems 40


UI/Applica$on  
Exerciser  Monkey  and  
MonkeyRunner  

COMP 355 (Muppala) Testing Embedded Systems 41


UI/Applica$on  Exerciser  Monkey  
•  Runs  on  your  emulator  or  device  
•  Generates  pseudo-­‐random  streams  of  user  events  such  as  
clicks,  touches,  or  gestures  and  a  number  of  system-­‐level  
events  
–  Stress-­‐test  applica$ons  in  a  random  yet  repeatable  manner  
•  Command-­‐line  tool  
–  Basic  Syntax:  
$  adb  shell  monkey  [op$ons]  <event-­‐count>  
–  Example:  
$  adb  shell  monkey  -­‐p  your.package.name  -­‐v  500  

COMP 355 (Muppala) Testing Embedded Systems 42


UI/Applica$on  Exerciser  Monkey  
•  Four  primary  categories  of  op$ons:  
–  Basic  configura$on  op$ons,  such  as  seeng  the  number  of  events  to  
aWempt.  
–  Opera$onal  constraints,  such  as  restric$ng  the  test  to  a  single  package.  
–  Event  types  and  frequencies.  
–  Debugging  op$ons  
•  It  also  watches  the  system  under  test  and  looks  for  three  
condi$ons,  which  it  treats  specially:  
–  If  you  have  constrained  the  Monkey  to  run  in  one  or  more  specific  
packages,  it  watches  for  aWempts  to  navigate  to  any  other  packages,  and  
blocks  them.  
–  If  your  applica$on  crashes  or  receives  any  sort  of  unhandled  excep$on,  
the  Monkey  will  stop  and  report  the  error.  
–  If  your  applica$on  generates  an  applica&on  not  responding  error,  the  
Monkey  will  stop  and  report  the  error.  

COMP 355 (Muppala) Testing Embedded Systems 43


MonkeyRunner  
•  API  for  wri$ng  programs  to  control  an  Android  device  or  
emulator  from  outside  
–  Unrelated  to  the  monkey  we  saw  earlier  
•  Tool  controls  devices  and  emulators  from  a  worksta$on  by  
sending  specific  commands  and  events  from  an  API  
•  We  can  write  a  Python  program  to  install  an  app  or  test  
package,  run  it,  send  keystrokes  to  it,  and  take  screenshots  of  
its  UI  
•  Test  applica$ons  at  the  func$onal/framework  level  
•  Syntax:  
monkeyrunner  -­‐plugin  <plugin_jar>  <program_filename>  <program_op$ons>  

COMP 355 (Muppala) Testing Embedded Systems 44


MonkeyRunner  
•  Features  for  Android  tes$ng:  
–  Mul$ple  device  control  
•  Can  run  one  or  more  test  suites  across  mul$ple  devices/emulators  
•  Programma$cally  start  up  an  emulator,  run  tests  and  shut  it  down  
–  Func$onal  tes$ng:  Automated  start-­‐to-­‐finish  test  of  an  applica$on  
–  Regression  tes$ng:  Test  applica$on  stability  by  running  an  applica$on  
and  comparing  its  output  screenshots  to  a  set  of  screenshots  that  are  
known  to  be  correct  
–  Extensible  automa$on:  Can  develop  a  Python-­‐based  system  of  
modules  for  controlling  devices  
•  Uses  Jython,  an  implementa$on  of  Python  that  uses  the  Java  
programming  language  

COMP 355 (Muppala) Testing Embedded Systems 45


MonkeyRunner  Example  
#  Imports  the  monkeyrunner  modules  used  by  this  program  
from  com.android.monkeyrunner  import  MonkeyRunner,  MonkeyDevice  
 
#  Connects  to  the  current  device,  returning  a  MonkeyDevice  object  
device  =  MonkeyRunner.waitForConnec$on()  
 
#  Installs  the  Android  package.  No$ce  that  this  method  returns  a  boolean,  so  you  can  test  
#  to  see  if  the  installa$on  worked.  
device.installPackage('myproject/bin/MyApplica$on.apk')  
 
#  sets  a  variable  with  the  package's  internal  name  
package  =  'com.example.android.myapplica$on'  
 
#  sets  a  variable  with  the  name  of  an  Ac$vity  in  the  package  
ac$vity  =  'com.example.android.myapplica$on.MainAc$vity'  

COMP 355 (Muppala) Testing Embedded Systems 46


MonkeyRunner  Example  
 
#  sets  the  name  of  the  component  to  start  
runComponent  =  package  +  '/'  +  ac$vity  
 
#  Runs  the  component  
device.startAc$vity(component=runComponent)  
 
#  Presses  the  Menu  buWon  
device.press('KEYCODE_MENU','DOWN_AND_UP')  
 
#  Takes  a  screenshot  
result  =  device.takeSnapshot()  
 
#  Writes  the  screenshot  to  a  file  
result.writeToFile('myproject/shot1.png','png')  

COMP 355 (Muppala) Testing Embedded Systems 47


MonkeyRunner  API  
•  API  contained  in  three  modules  in  the  package  
com.android.monkeyrunner:  
–  MonkeyRunner:  A  class  of  u$lity  methods  for  monkeyrunner  
programs.  This  class  provides  a  method  for  connec$ng  monkeyrunner  
to  a  device  or  emulator.  It  also  provides  methods  for  crea$ng  UIs  for  a  
monkeyrunner  program  and  for  displaying  the  built-­‐in  help.  
–  MonkeyDevice:  Represents  a  device  or  emulator.  This  class  provides  
methods  for  installing  and  uninstalling  packages,  star$ng  an  Ac$vity,  
and  sending  keyboard  or  touch  events  to  an  applica$on.  You  also  use  
this  class  to  run  test  packages.  
–  MonkeyImage:  Represents  a  screen  capture  image.  This  class  provides  
methods  for  capturing  screens,  conver$ng  bitmap  images  to  various  
formats,  comparing  two  MonkeyImage  objects,  and  wri$ng  an  image  
to  a  file.  

COMP 355 (Muppala) Testing Embedded Systems 48


Debugging  Techniques  
and  Tools  
Debugging  in  Android  
•  Main  components  in  a  typical  Android  debugging  environment:  
–  adb:  
•  acts  as  a  middleman  between  a  device  and  your  development  system  
•  provides  various  device  management  capabili$es,  including  moving  and  
syncing  files  to  the  emulator,  running  a  UNIX  shell  on  the  device  or  emulator,  
and  providing  a  general  means  to  communicate  with  connected  emulators  
and  devices  
–  DDMS    (Dalvik  Debug  Monitor  Server):    
•  Graphical  program  that  communicates  with  your  devices  through  adb  
•  DDMS  can  capture  screenshots,  gather  thread  and  stack  informa$on,  spoof  
incoming  calls  and  SMS  messages,  and  has  many  other  features  
–  Device  or  Android  Virtual  Device  (AVD):  
•  Environment  for  your  applica$on  to  run  and  debugged  
•  An  adb  device  daemon  runs  on  the  device  or  emulator  and  provides  a  means  
for  the  adb  host  daemon  to  communicate  with  the  device  or  emulator  

COMP 355 (Muppala) Debugging 50


Debugging  in  Android  
–  JDWP  Debugger:  
•  JDWP-­‐compliant  debugger  needed  to  be  able  to  do  things  such  as  step  
through  code,  view  variable  values,  and  pause  execu$on  of  an  applica$on  
•  The  Dalvik  VM  supports  the  JDWP  protocol  to  allow  debuggers  to  aWach  
to  a  VM  
•  Each  applica$on  runs  in  a  VM  and  exposes  a  unique  port  that  you  can  
aWach  a  debugger  to  via  DDMS  
•  If  you  want  to  debug  mul$ple  applica$ons,  aWaching  to  each  port  might  
become  tedious,  so  DDMS  provides  a  port  forwarding  feature  that  can  
forward  a  specific  VM's  debugging  port  to  port  8700  
•  You  can  switch  freely  from  applica$on  to  applica$on  by  highligh$ng  it  in  
the  Devices  tab  of  DDMS.  DDMS  forwards  the  appropriate  port  to  port  
8700  
•  You  can  use  a  command  line  debugger  such  as  jdb  
•  Eclipse  already  includes  a  JDWP-­‐compliant  debugger    

COMP 355 (Muppala) Debugging 51


Android  Debugging  Environment  

COMP 355 (Muppala) Debugging 52


Tips  for  Debugging  
•  Dump  the  stack  trace  
–  To  obtain  a  stack  dump  from  emulator,  you  can  log  in  with  adb  shell,  
use  ps  to  find  the  process  you  want,  and  then  kill  -­‐3.  The  stack  trace  
appears  in  the  log  file.  
•  Display  useful  info  on  the  emulator  screen  
–  The  device  can  display  useful  informa$on  such  as  CPU  usage  or  
highlights  around  redrawn  areas.  
•  Get  applica$on  and  system  state  informa$on  from  the  
emulator  
–  You  can  access  dumpstate  informa$on  from  the  adb  shell  commands.  
•  Get  wireless  connec$vity  informa$on  
–  You  can  get  informa$on  about  wireless  connec$vity  using  DDMS.  
From  the  Device  menu,  select  Dump  radio  state.  

COMP 355 (Muppala) Debugging 53


Tips  for  Debugging  
•  Log  trace  data  
–  You  can  log  method  calls  and  other  tracing  data  in  an  ac$vity  by  calling  
startMethodTracing()  
•  Log  radio  data  
–  By  default,  radio  informa$on  is  not  logged  to  the  system  (it  is  a  lot  of  
data).  However,  you  can  enable  radio  logging  using  the  following  
commands:  
adb  shell  
logcat  -­‐b  radio  
•  Capture  screenshots  
–  The  Dalvik  Debug  Monitor  Server  (DDMS)  can  capture  screenshots  from  
the  emulator.  Select  Device  >  Screen  capture.  
•  Use  debugging  helper  classes  
–  Android  provides  debug  helper  classes  such  as  u$l.Log  and  Debug  

COMP 355 (Muppala) Debugging 54


Debugging  from  Eclipse  with  ADT  
•  If  you  are  developing  in  Eclipse  with  the  ADT  plugin,  you  can  
use  the  built-­‐in  Java  Debugger,  along  with  DDMS,  to  debug  
your  applica$ons  
•  To  access  the  debugger  and  DDMS,  Eclipse  displays  the  
debugger  and  DDMS  features  as  perspec$ves,  which  are  
customized  Eclipse  views  that  display  certain  tabs  and  
windows  depending  on  the  perspec$ve  that  you  are  in  
•  Eclipse  also  takes  care  of  star$ng  the  ADB  host  daemon  for  
you,  so  you  do  not  have  to  run  this  manually.  

COMP 355 (Muppala) Debugging 55


The  Debug  Perspec$ve  in  Eclipse  
•  The  Debug  Perspec$ve  in  Eclipse  gives  you  access  to  the  following  
tabs:  
–  Debug  -­‐  Displays  previously  and  currently  debugged  Android  applica$ons  
and  its  currently  running  threads  
–  Variables  -­‐  When  breakpoints  are  set,  displays  variable  values  during  code  
execu$on  
–  Breakpoints  -­‐  Displays  a  list  of  the  set  breakpoints  in  your  applica$on  code  
–  LogCat  -­‐  Allows  you  to  view  system  log  messages  in  real  $me.  The  LogCat  
tab  is  also  available  in  the  DDMS  perspec$ve.  
•  You  can  access  the  Debug  Perspec$ve  by  clicking  Window  >  Open  
Perspec$ve  >  Debug.  Refer  to  the  appropriate  documenta$on  for  
the  Eclipse  debugger  for  more  informa$on.  

COMP 355 (Muppala) Debugging 56


The  DDMS  Perspec$ve  
•  The  DDMS  Perspec$ve  in  Eclipse  lets  you  access  all  of  the  features  
of  DDMS  from  within  the  Eclipse  IDE.  The  following  sec$ons  of  
DDMS  are  available  to  you:  
–  Devices  -­‐  Shows  the  list  of  devices  and  AVDs  that  are  connected  to  ADB.  
–  Emulator  Control  -­‐  Lets  you  carry  out  device  func$ons.  
–  LogCat  -­‐  Lets  you  view  system  log  messages  in  real  $me.  
–  Threads  -­‐  Shows  currently  running  threads  within  a  VM.  
–  Heap  -­‐  Shows  heap  usage  for  a  VM.  
–  Alloca$on  Tracker  -­‐  Shows  the  memory  alloca$on  of  objects.  
–  File  Explorer  -­‐  Lets  you  explore  the  device's  file  system.  
•  To  access  the  DDMS  perspec$ve,  go  to  Window  >  Open  Perspec$ve  
>  DDMS.  If  DDMS  does  not  appear,  go  to  Window  >  Open  
Perspec$ve  >  Other  ...  and  select  DDMS  from  the  Open  Perspec$ve  
window  that  appears.  

COMP 355 (Muppala) Debugging 57


Dalvik  Debug  Monitor  Server  (DDMS)  
•  Provides  port-­‐forwarding  services,  screen  capture  on  the  
device,  thread  and  heap  informa$on  on  the  device,  logcat,  
process,  and  radio  state  informa$on,  incoming  call  and  SMS  
spoofing,  loca$on  data  spoofing,  and  more  
•  Integrated  into  Eclipse  and  is  also  shipped  in  the  tools/  
directory  of  the  SDK  
•  Works  with  both  the  emulator  and  a  connected  device.  If  
both  are  connected  and  running  simultaneously,  DDMS  
defaults  to  the  emulator.  
–  From  Eclipse:  Click  Window  >  Open  Perspec$ve  >  Other...  >  DDMS.  
–  From  the  command  line:  Type  ddms  (or  ./ddms  on  Mac/Linux)  from  
the  tools/  directory.  

COMP 355 (Muppala) Debugging 58


DDMS  and  Debugger  
•  On  Android,  every  applica$on  runs  in  its  own  process,  each  of  
which  runs  in  its  own  virtual  machine  (VM)  
–  Each  VM  exposes  a  unique  port  that  a  debugger  can  aWach  to.  
•  When  DDMS  starts,  it  connects  to  adb  
•  When  a  device  is  connected,  a  VM  monitoring  service  is  
created  between  adb  and  DDMS,  which  no$fies  DDMS  when  
a  VM  on  the  device  is  started  or  terminated  
•  Once  a  VM  is  running,  DDMS  retrieves  the  the  VM's  process  
ID  (pid),  via  adb,  and  opens  a  connec$on  to  the  VM's  
debugger,  through  the  adb  daemon  (adbd)  on  the  device  
•  DDMS  can  now  talk  to  the  VM  using  a  custom  wire  protocol.  

COMP 355 (Muppala) Debugging 59


DDMS  and  Debugger  
•  DDMS  assigns  a  debugging  port  to  each  VM  on  the  device  
–  Typically,  DDMS  assigns  port  8600  for  the  first  debuggable  VM,  the  next  
on  8601,  and  so  on  
–  When  a  debugger  connects  to  one  of  these  ports,  all  traffic  is  forwarded  
to  the  debugger  from  the  associated  VM  
–  You  can  only  aWach  a  single  debugger  to  a  single  port,  but  DDMS  can  
handle  mul$ple,  aWached  debuggers.  
•  By  default,  DDMS  also  listens  on  another  debugging  port,  the  
DDMS  "base  port"  (8700,  by  default)  
–  The  base  port  is  a  port  forwarder,  which  can  accept  VM  traffic  from  any  
debugging  port  and  forward  it  to  the  debugger  on  port  8700  
–  This  allows  you  to  aWach  one  debugger  to  port  8700,  and  debug  all  the  
VMs  on  a  device  
–  The  traffic  that  is  forwarded  is  determined  by  the  currently  selected  
process  in  the  DDMS  Devices  view.  

COMP 355 (Muppala) Debugging 60


Using  DDMS  
•  Viewing  heap  usage  for  a  process  
•  Tracking  memory  alloca$on  of  objects  
•  Working  with  an  emulator  or  device's  file  system  
•  Examining  thread  informa$on  
•  Star$ng  method  profiling  
•  Using  LogCat  
•  Emula$ng  phone  opera$ons  and  loca$on  
–  Changing  network  state,  speed,  and  latency  
–  Spoofing  calls  or  SMS  text  messages  
–  Seeng  the  loca$on  of  the  phone  

COMP 355 (Muppala) Debugging 61


Logging  
•  The  Android  logging  system  provides  a  mechanism  for  
collec$ng  and  viewing  system  debug  output  
•  Logcat  dumps  a  log  of  system  messages,  which  include  things  
such  as  stack  traces  when  the  emulator  throws  an  error  and  
messages  that  you  have  wriWen  from  your  applica$on  by  
using  the  Log  (android.u$l.Log)  class  
•  You  can  run  LogCat  through  ADB  or  from  DDMS,  which  allows  
you  to  read  the  messages  in  real  $me.  

COMP 355 (Muppala) Debugging 62


Log  class  
•  Logging  class  that  you  can  u$lize  in  your  code  to  print  out  messages  
to  the  LogCat  
•  Common  logging  methods  include:  
–  Verbose:  v(String,  String)  
–  Debug:  d(String,  String)  
–  Informa$on:  i(String,  String)  
–  Warning:  w(String,  String)  
–  Error:  e(String,  String)  
•  Usage  Example:  
–  Log.i("MyAc$vity",  "MyClass.getView()  —  get  item  number  "  +  posi$on);  
•  Typical  Output  Example:  
–  I/MyAc$vity(  1557):  MyClass.getView()  —  get  item  number  1  

COMP 355 (Muppala) Debugging 63

Das könnte Ihnen auch gefallen