2016-01-26 15 views
6

Ho sviluppato applicazioni Android ma non ho scritto alcun test unitario. Recentemente ho iniziato a conoscerlo e ho provato a usare JUnit per testare le mie applicazioni Android.Test delle unità Android: come rendere una classe più testabile?

Ho scoperto che il più delle volte ricevo bug nelle chiamate API, ma non riesco ancora a capire come scrivere test di unità per loro (& come rendere verificabile il codice originale).

Mi spiego la seguente funzione:

Sto facendo funzionare un setOffenceList chiamata di funzione(). Ci sono più azioni che accadono all'interno della funzione.

i) Caricare il RestClient e passare l'URL.

ii) RestClient parlare con l'api JSON e ottenere la risposta

ii) I afferrare la risposta all'interno del onSuccess (risposta String) funzione

iii) analizzare i dati JSON e conservare all'interno di una matrice

iv) Se il successo vi mostrerò i dati in una vista elenco (altro mostro un messaggio di errore)

Questo è il codice:

public class OffenceFrag extends Fragment { 


    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.frag_offence, container, false); 
     //run API call 
     setOffenceList(); 
     return view; 
    } 

    private void setOffenceList() { 
     String url = Paths.SITE_URL ; 
     RestClient.get(url, null, new AsyncHttpResponseHandler() { 

      @Override 
      public void onStart() { 
       Toast.makeText(getActivity(), "Loading offences...", Toast.LENGTH_SHORT).show(); 
      } 

      @Override 
      public void onSuccess(String response) { 

       //Parse JSON 
       JSONArray jsonArray; 
       try { 

        JSONObject jsonObj = new JSONObject(response); 
        if(jsonObj.getString("status").equalsIgnoreCase("Success")){ 

         jsonArray = new JSONArray(jsonObj.getString("data")); 
         if(jsonArray.length() > 0){ 
          for (int i = 0; i < jsonArray.length(); i++) { 

           JSONObject row = jsonArray.getJSONObject(i); 
           OffenceORM off = new OffenceORM(); 
           off.setOffenceId(row.getString("offence_id")); 
           off.setPhoto(row.getString("photo")); 
           off.setSubmittedBy(row.getString("submitted_by")); 
           offenceList.add(off); 
          } 
         } 

         //Success: Show the list view 
         setOffenceAdapter(); 
         Toast.makeText(getActivity(), "Successfully Loaded", Toast.LENGTH_LONG).show(); 

        } else { 
         //Failed: show error message 
         Toast.makeText(getActivity(), "There are no offences submitted under project", Toast.LENGTH_LONG).show(); 
        } 

       } catch (Exception e) { 
        Log.e("exception", e.getMessage()); 
       } 
      } 

      @Override 
      public void onFailure(Throwable error, String content) { 
       Log.e("failed", error.getMessage()); 
      } 

      @Override 
      public void onFinish() { 

      } 
     }); 
    } 


}//end 

Non riesco davvero a capire come posso scrivere una funzione di test su qualcosa come il codice precedente.

Puoi per favore mostrarmi come suddividere questo codice in parti testabili e scrivere loro funzioni di test di unità?

Grazie mille!

+1

Un approccio sarebbe scrivere un test di integrazione che esegua l'API REST. Vedi http://stackoverflow.com/questions/10752/what-is-the-difference-between-integration-and-unit-tests. In un approccio di unit test tipicamente si prende in giro 'Inflazione LayoutInflater, contenitore ViewGroup, Bundle savedInstanceState', passali a' OffenceFrag. onCreateView() 'e asserisci che OffenceFrag fa quello che ti aspetti da – Kirby

risposta

1

Stai facendo troppe cose in Fragment, è difficile testare e dare manutenzione.

Uso il pattern MVP nei miei progetti, che consente di separare il livello di presentazione dalla logica, evitando di inserire tutto il codice in frammenti/attività.

Controllare questo articolo: http://antonioleiva.com/mvp-android/

E l'esempio di codice relativo a GitHub: https://github.com/antoniolg/androidmvp

4

solo e soltanto un buon design può aiutare a rendere più facile il test dell'unità. Ecco perché Test Driven Development è lì. In modo che tu non possa andare con un design sbagliato.

Durante il test dell'unità, è sufficiente testare il codice scritto da te e utilizzare oggetti fittizi forniti da Android per testare le chiamate Android Api.

Per quanto riguarda gli altri Api hanno problemi rispetto al problema dello sviluppatore Api non vostro. Puoi utilizzare il framework mock come Mockito per testare la funzionalità del tuo codice quando effettua chiamate ad altri codici API. Provare separatamente il codice API se si sta sviluppando la propria API.

Principi di progettazione devono essere seguite per il buon design come

  • S - principio Single-responsiblity
  • O - I Liskov principio di sostituzione
  • - - Interfaccia principio della segregazione aperto-chiuso principio
  • L
  • D - Principio di inversione delle dipendenze

punti importanti:

metodo
  • uno affermare chiamata per ogni caso di test di unità
  • Non modificare le classi solo per i test.
  • Uso di interfacce
  • Non inserire troppe istruzioni o funzionalità in un unico metodo.
  • Non fare lezioni troppo grandi.
  • Usa TDD ....... Molti di più

Unità testare un male progettare codice è completo spreco. Il test si interromperà ogni volta che apporterai alcune modifiche alle classi. In Android questo accadrà ancora di più. Come sei bloccato con i metodi del ciclo di vita di Android.

Funzionalità via attentamente astratte da testare nelle proprie classi.

Ciò renderà il codice dell'applicazione più robusto, semplice e chiaro.

+3

' una chiamata al metodo di asserzione per ogni caso di test '- questo non è sempre possibile. Ad esempio: nessuno controlla null in un test e il valore del risultato in un altro test. – Bevor

1

Il consiglio di Rohit Khatkar di utilizzare TDD è sicuramente da prendere in considerazione per il prossimo codice che sviluppate. Ma, ora che questo codice esiste e stai chiedendo "come suddividere questo codice in parti testabili": potresti dapprima ignorare la testabilità e provare a suddividere questo codice in parti più piccole: definizioni di classi di Exline e metodi di divisione, proprio come per ottimizzare la leggibilità in generale. Troverai già qualche ridondanza (il se attorno al ciclo for).

Come effetto, ciascuno dei metodi risultanti avrà probabilmente meno dipendenze da altre classi. Quindi, puoi concentrarti sulla riduzione di queste dipendenze. Controlla il libro di Michael Feather sulla gestione del codice legacy per un sacco di approcci per rompere le dipendenze. EDIT: Qualcuno ha estratto un elenco di tecniche di interruzione delle dipendenze (però solo descrizioni di alto livello): http://rubyexperiences.blogspot.de/2005/12/dependency-breaking-techniques-from.html