Suche…


Bemerkungen

Local Unit-Tests erstellen

Platzieren Sie Ihre /src/test/<pkg_name>/ hier: /src/test/<pkg_name>/

Beispiel Testklasse

public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        int a=4, b=5, c;
        c = a + b;
        assertEquals(9, c); // This test passes
        assertEquals(10, c); //Test fails
    }
}

Nervenzusammenbruch

public class ExampleUnitTest {
  ...
}

In der Testklasse können Sie mehrere Testklassen erstellen und diese innerhalb des Testpakets platzieren.

@Test
public void addition_isCorrect() {
   ...
}

Mit der Testmethode können mehrere Testmethoden innerhalb einer Testklasse erstellt werden.

Beachten Sie die Anmerkung @Test .

Die Testannotation teilt JUnit mit, dass die öffentliche Void-Methode, an die sie angehängt ist, als Testfall ausgeführt werden kann.

Es gibt einige weitere nützliche Anmerkungen wie @Before , @After usw. Diese Seite wäre ein guter Anfang.

assertEquals(9, c); // This test passes
assertEquals(10, c); //Test fails

Diese Methoden sind Mitglied der Assert Klasse. Einige andere nützliche Methoden sind assertFalse() , assertNotNull() , assertTrue usw. Hier eine ausführliche Erklärung .


Anmerkungsinformationen für JUnit Test:

@Test: Die Test-Annotation teilt JUnit mit, dass die öffentliche Void-Methode, mit der sie verbunden ist, als Testfall ausgeführt werden kann. Um die Methode auszuführen, erstellt JUnit zuerst eine neue Instanz der Klasse und ruft dann die annotierte Methode auf.

@Before: Beim Schreiben von Tests wird häufig festgestellt, dass für mehrere Tests ähnliche Objekte erstellt werden müssen, bevor sie ausgeführt werden können. Wenn Sie eine öffentliche void-Methode mit @Before wird diese Methode vor der Test-Methode ausgeführt.

@After: Wenn Sie externe Ressourcen in einer Before-Methode zuordnen, müssen Sie sie nach dem Testlauf freigeben. Wenn Sie eine öffentliche void-Methode mit @After wird diese Methode nach der Test-Methode ausgeführt. Es wird garantiert, dass alle @After Methoden ausgeführt werden, auch wenn eine @After oder Test-Methode eine Ausnahme @After


Tipp Erstellen Sie schnell Testklassen in Android Studio

  • Setzen Sie den Cursor auf den Klassennamen, für den Sie eine Testklasse erstellen möchten.
  • Drücken Sie Alt + Eingabe (Windows).
  • Wählen Sie Create Test aus und drücken Sie die Eingabetaste.
  • Wählen Sie die Methoden aus, für die Sie Testmethoden erstellen möchten, und klicken Sie auf OK.
  • Wählen Sie das Verzeichnis aus, in dem Sie die Testklasse erstellen möchten.
  • Sie sind fertig, das, was Sie bekommen, ist Ihre erste Prüfung.

Tipp Führen Sie Tests einfach in Android Studio aus

  • Klicken Sie mit der rechten Maustaste, um das Paket zu testen.
  • Wählen Sie Ausführen 'Tests in ...
  • Alle Tests im Paket werden sofort ausgeführt.

Geschäftslogik aus Android-Komponenten herausziehen

Ein großer Teil des Nutzens aus lokalen JVM-Komponententests kommt von der Art und Weise, wie Sie Ihre Anwendung entwerfen. Sie müssen es so gestalten, dass Sie Ihre Geschäftslogik von Ihren Android-Komponenten trennen können. Hier ist ein Beispiel für eine solche Verwendung des Model-View-Presenter-Musters . Lassen Sie uns dies üben, indem Sie einen einfachen Anmeldebildschirm implementieren, der nur einen Benutzernamen und ein Kennwort enthält. Unsere Android-App ist dafür verantwortlich, dass der Benutzername, den der Benutzer bereitstellt, nicht leer ist und dass das Kennwort mindestens acht Zeichen lang ist und mindestens eine Ziffer enthält. Wenn der Benutzername / das Passwort gültig ist, führen wir unseren Anmeldungsaufruf aus, andernfalls wird eine Fehlermeldung angezeigt.

Beispiel, bei dem die Geschäftslogik stark mit der Android-Komponente gekoppelt ist.

public class LoginActivity extends Activity{
    ...
    private void onSubmitButtonClicked(){
        String username = findViewById(R.id.username).getText().toString();
        String password = findViewById(R.id.password).getText().toString();
        boolean isUsernameValid = username != null && username.trim().length() != 0;
        boolean isPasswordValid = password != null && password.trim().length() >= 8 && password.matches(".*\\d+.*");
        if(isUsernameValid && isPasswordValid){
            performSignUpApiCall(username, password);
        } else {
            displayInvalidCredentialsErrorMessage();
        }
    }
}

Beispiel, bei dem die Geschäftslogik von der Android-Komponente entkoppelt ist.

Hier definieren wir in einer einzigen Klasse, LoginContract, die die verschiedenen Interaktionen zwischen unseren verschiedenen Klassen beherbergen wird.

public interface LoginContract {
    public interface View {
        performSignUpApiCall(String username, String password);
        displayInvalidCredentialsErrorMessage();
    }
    public interface Presenter {
        void validateUserCredentials(String username, String password);
    }
}

Unsere LoginActivity ist größtenteils gleich, mit der Ausnahme, dass wir die Verantwortung für das Validieren des Anmeldeformulars eines Benutzers (unsere Geschäftslogik) aufgehoben haben. Die LoginActivity-Funktion verlässt sich jetzt auf den neuen LoginPresenter, um die Validierung durchzuführen.

public class LoginActivity extends Activity implements LoginContract.View{
    private LoginContract.Presenter presenter;

    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            presenter = new LoginPresenter(this);
            ....
        }
        ...

        private void onSubmitButtonClicked(){
            String username = findViewById(R.id.username).getText().toString();
            String password = findViewById(R.id.password).getText().toString();
            presenter.validateUserCredentials(username, password);
    }
    ...
}

Jetzt befindet sich Ihre Geschäftslogik in Ihrer neuen LoginPresenter-Klasse.

public class LoginPresenter implements LoginContract.Presenter{
    private LoginContract.View view;

    public LoginPresenter(LoginContract.View view){
        this.view = view;
    }

    public void validateUserCredentials(String username, String password){
        boolean isUsernameValid = username != null && username.trim().length() != 0;
        boolean isPasswordValid = password != null && password.trim().length() >= 8 && password.matches(".*\\d+.*");
        if(isUsernameValid && isPasswordValid){
            view.performSignUpApiCall(username, password);
        } else {
            view.displayInvalidCredentialsErrorMessage();
        }
    }
}

Jetzt können wir lokale JVM-Komponententests für Ihre neue LoginPresenter-Klasse erstellen.

public class LoginPresenterTest {

    @Mock
    LoginContract.View view;

    private LoginPresenter presenter;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        presenter = new LoginPresenter(view);
    }

    @Test
    public void test_validateUserCredentials_userDidNotEnterUsername_displayErrorMessage() throws Exception {
        String username = "";
        String password = "kingslayer1";
        presenter.validateUserCredentials(username, password);
        Mockito.verify(view). displayInvalidCredentialsErrorMessage();
    }

    @Test
    public void test_validateUserCredentials_userEnteredFourLettersAndOneDigitPassword_displayErrorMessage() throws Exception {
        String username = "Jaime Lanninster";
        String password = "king1";
        presenter.validateUserCredentials(username, password);
        Mockito.verify(view). displayInvalidCredentialsErrorMessage();
    }

    @Test
    public void test_validateUserCredentials_userEnteredNineLettersButNoDigitsPassword_displayErrorMessage() throws Exception {
        String username = "Jaime Lanninster";
        String password = "kingslayer";
        presenter.validateUserCredentials(username, password);
        Mockito.verify(view). displayInvalidCredentialsErrorMessage();
    }

    @Test
    public void test_validateUserCredentials_userEnteredNineLettersButOneDigitPassword_performApiCallToSignUpUser() throws Exception {
        String username = "Jaime Lanninster";
        String password = "kingslayer1";
        presenter.validateUserCredentials(username, password);
        Mockito.verify(view).performSignUpApiCall(username, password);
    }
}

Wie Sie sehen, haben wir unsere Geschäftslogik aus der LoginActivity extrahiert und in den LoginPresenter POJO gestellt . Wir können jetzt lokale JVM-Komponententests gemäß unserer Geschäftslogik erstellen.

Es sollte beachtet werden, dass unsere Architekturveränderung verschiedene andere Auswirkungen hat, wie zum Beispiel, dass wir uns fast an jeder Klasse mit einer einzigen Verantwortung, an zusätzlichen Klassen usw. halten Entkopplung über den MVP-Style. MVP ist nur eine Möglichkeit, dies zu tun, aber es gibt andere Alternativen, die Sie sich anschauen möchten, wie MVVM . Sie müssen nur das beste System auswählen, das für Sie funktioniert.

Erste Schritte mit JUnit

Konfiguration

Um den Gerätetest Ihres Android-Projekts mit JUnit zu starten, müssen Sie die JUnit-Abhängigkeit zu Ihrem Projekt hinzufügen und einen Testquellensatz erstellen, der den Quellcode für die Komponententests enthält. Projekte, die mit Android Studio erstellt wurden, enthalten häufig bereits die JUnit-Abhängigkeit und den Testquellensatz

Fügen Sie der Modul- build.gradle Datei die folgende Zeile innerhalb der Abhängigkeiten Closure :

testCompile 'junit:junit:4.12'

JUnit-Testklassen befinden sich in einem speziellen Quellsatz mit dem Namen test . Wenn diese Quellgruppe nicht vorhanden ist, müssen Sie selbst einen neuen Ordner erstellen. Die Ordnerstruktur eines Standardprojekts von Android Studio (Gradle-basiert) sieht folgendermaßen aus:

<project-root-folder>
    /app (module root folder)
        /build
        /libs
        /src
            /main (source code)
            /test (unit test source code)
            /androidTest (instrumentation test source code)
        build.gradle (module gradle file)
    /build
    /gradle
    build.gradle (project gradle file)
    gradle.properties
    gradlew
    gradlew.bat
    local.properties
    settings.gradle (gradle settings)

Wenn Ihr Projekt nicht über den Ordner /app/src/test , müssen Sie es selbst erstellen. Im test müssen Sie auch einen java - Ordner (erstellen Sie es , wenn es nicht existiert). Die Java - Ordner in der test Satz sollte enthalten die gleiche Paketstruktur als main

Wenn Sie Ihre Projektstruktur (in der Android-Ansicht in Android Studio) richtig eingerichtet haben, sollte dies folgendermaßen aussehen:

Projektaufbau

Hinweis: Sie müssen nicht unbedingt das androidTest Quellenset haben. Dieses Quellenset wird häufig in Projekten gefunden, die von Android Studio erstellt wurden, und ist hier als Referenz enthalten.


Test schreiben

  1. Erstellen Sie eine neue Klasse innerhalb der test .
    Klicken Sie in der Projektansicht mit der rechten Maustaste auf den Testquellensatz, und wählen Sie New > Java class .
    Das am häufigsten verwendete Benennungsmuster ist die Verwendung des Namens der Klasse, die Sie testen möchten, wobei Test hinzugefügt wird. So wird StringUtilities zu StringUtilitiesTest .

  2. Fügen Sie die Anmerkung @RunWith
    Die Annotation @RunWith ist erforderlich, damit JUnit die Tests @RunWith , die in unserer @RunWith definiert werden. Der Standard-JUnit-Runner (für JUnit 4) ist BlockJUnit4ClassRunner aber anstatt direkt zu laufen, ist es bequemer, den Alias JUnit4 der eine Abkürzung für den Standard-JUnit-Runner ist.

     @RunWith(JUnit4.class)
     public class StringUtilitiesTest {
     
     }
    
  3. Erstellen Sie einen Test
    Ein Komponententest ist im Wesentlichen nur eine Methode, die in den meisten Fällen nicht fehlschlagen sollte, wenn sie ausgeführt wird. Mit anderen Worten, es sollte keine Ausnahme auslösen. In einer Testmethode finden Sie fast immer Assertionen, die prüfen, ob bestimmte Bedingungen erfüllt sind. Wenn eine Assertion fehlschlägt, wird eine Ausnahme ausgelöst, die dazu führt, dass die Methode / der Test fehlschlägt. Eine Testmethode wird immer mit der Annotation @Test . Ohne diese Anmerkung führt JUnit den Test nicht automatisch aus.

     @RunWith(JUnit4.class)
     public class StringUtilitiesTest {
    
         @Test
         public void addition_isCorrect() throws Exception {
             assertEquals("Hello JUnit", "Hello" + " " + "JUnit");
         }
     }
    

    Hinweis: Im Gegensatz zu den Standardmethoden für die Benennung von Java-Methoden enthalten die Namen von Testmethoden oft Unterstriche.


Test durchführen

  1. Methode
    Um eine einzelne Testmethode auszuführen, klicken Sie mit der rechten Maustaste auf die Methode und klicken Sie auf Run 'addition_isCorrect()' oder verwenden Sie die Tastenkombination ctrl+shift+f10 . Führen Sie einen einzelnen Unit-Test durch

    Wenn alles korrekt eingerichtet ist, startet JUnit die Methode und Sie sollten die folgende Schnittstelle in Android Studio sehen:

    Android Studio-Einheitstestschnittstelle

  1. Klasse
    Sie können auch alle in einer einzelnen Klasse definierten Tests ausführen, indem Sie in der Projektansicht mit der rechten Maustaste auf die Klasse klicken und auf Run 'StringUtilitiesTest ' oder die Tastenkombination ctrl+shift+f10 wenn Sie die Klasse in der Projektansicht ausgewählt haben.

  2. Paket (alles)
    Wenn Sie nicht alle im Projekt oder in einem Paket definierten Tests ausführen möchten, können Sie einfach mit der rechten Maustaste auf das Paket klicken und auf Run ... klicken, genauso wie Sie alle in einer einzelnen Klasse definierten Tests ausführen würden.

Ausnahmen

Mit JUnit kann auch getestet werden, ob eine Methode für eine bestimmte Eingabe eine bestimmte Ausnahme auslöst.

In diesem Beispiel testen wir, ob die folgende Methode wirklich eine Ausnahme auslöst, wenn das boolesche Format (Eingabe) nicht erkannt / unbekannt ist:

public static boolean parseBoolean(@NonNull String raw) throws IllegalArgumentException{
    raw = raw.toLowerCase().trim();
    switch (raw) {
        case "t": case "yes": case "1": case "true":
            return true;
        case "f": case "no": case "0": case "false":
            return false;
        default:
            throw new IllegalArgumentException("Unknown boolean format: " + raw);
    }
}

Durch Hinzufügen des expected Parameters zur @Test Annotation kann definiert werden, welche Ausnahme erwartet wird. Der Komponententest schlägt fehl, wenn diese Ausnahme nicht auftritt, und ist erfolgreich, wenn die Ausnahme tatsächlich ausgelöst wird:

@Test(expected = IllegalArgumentException.class)
public void parseBoolean_parsesInvalidFormat_throwsException(){
    StringUtilities.parseBoolean("Hello JUnit");
}

Dies funktioniert gut, beschränkt sich jedoch auf einen einzelnen Testfall innerhalb der Methode. Manchmal möchten Sie möglicherweise mehrere Fälle in einer einzigen Methode testen. Assert.fail() diese Einschränkung zu überwinden, werden häufig try-catch Blöcke und die Assert.fail() -Methode verwendet:

@Test
public void parseBoolean_parsesInvalidFormats_throwsException(){
    try {
        StringUtilities.parseBoolean("Hello!");
        fail("Expected IllegalArgumentException");
    } catch(IllegalArgumentException e){
    }

    try {
        StringUtilities.parseBoolean("JUnit!");
        fail("Expected IllegalArgumentException");
    } catch(IllegalArgumentException e){
    }
}

Hinweis: Einige Leute halten es für eine schlechte Praxis, mehr als einen einzelnen Fall innerhalb eines Komponententests zu testen.

Statischer Import

JUnit definiert einige assertEquals Methoden, von denen mindestens eine für jeden assertEquals und eine für Objekte verfügbar ist. Diese Methoden sind standardmäßig nicht direkt für den Aufruf verfügbar und sollten wie Assert.assertEquals aufgerufen werden: Assert.assertEquals . Da diese Methoden jedoch so häufig verwendet werden, wird fast immer ein statischer Import verwendet, sodass die Methode direkt verwendet werden kann, als wäre sie Teil der Klasse selbst.

Verwenden Sie die folgende Importanweisung, um einen statischen Import für die assertEquals Methode hinzuzufügen:

import static org.junit.Assert.assertEquals;

Sie können auch alle assertArrayEquals Methoden einschließlich der assertArrayEquals , assertNotNull und assertFalse usw. mithilfe des folgenden statischen Imports statisch importieren:

import static org.junit.Assert.*;

Ohne statischen Import:

@Test
public void addition_isCorrect(){
    Assert.assertEquals(4 , 2 + 2);
}

Bei statischem Import:

@Test
public void addition_isCorrect(){
    assertEquals(4 , 2 + 2);
}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow