Sök…


Anmärkningar

Skapa lokala enhetstester

Placera dina testklasser här: /src/test/<pkg_name>/

Exempel testklass

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
    }
}

Bryta ner

public class ExampleUnitTest {
  ...
}

Testklassen, du kan skapa flera testklasser och placera dem i testpaketet.

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

Testmetoden, flera testmetoder kan skapas i en testklass.

Lägg märke till anteckningen @Test .

Testanteckningen berättar för JUnit att den offentliga ogiltiga metoden som den är kopplad till kan köras som ett testfall.

Det finns flera andra användbara kommentarer som @Before , @After etc @After här sidan skulle vara ett bra ställe att börja.

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

Dessa metoder är medlemmar i klassen Assert . Några andra användbara metoder är assertFalse() , assertNotNull() , assertTrue etc. Här är en detaljerad förklaring .


Kommentarinformation för JUnit Test:

@ Test: Testanteckningen berättar för JUnit att metoden för offentlig tomgång till vilken den är kopplad kan köras som ett testfall. För att köra metoden konstruerar JUnit först en ny instans av klassen och åberopar sedan den antecknade metoden.

@Fore: När du skriver tester är det vanligt att upptäcka att flera test behöver liknande objekt skapade innan de kan köras. Annotering av en offentlig @Before med @Before gör att metoden körs före testmetoden.

@ Efter: Om du tilldelar externa resurser i en före-metod måste du släppa dem efter testkörningen. Annotering av en offentlig @After med @After gör att metoden körs efter testmetoden. Alla @After metoder garanteras att köra även om en före eller testmetod kastar ett undantag


Tips Skapa snabbt testklasser i Android Studio

  • Placera markören på det klassnamn som du vill skapa en testklass för.
  • Tryck på Alt + Enter (Windows).
  • Välj Skapa test, tryck på Retur.
  • Välj de metoder du vill skapa testmetoder för, klicka på OK.
  • Välj katalogen där du vill skapa testklassen.
  • Du är klar, det du får är ditt första test.

Tips Utför tester enkelt i Android Studio

  • Högerklicka testa paketet.
  • Välj Run 'Tests in ...
  • Alla tester i paketet kommer att utföras på en gång.

Flytta affärslogik från Android-komponentenheter

Mycket av värdet från lokala JVM-enhetstest kommer från det sätt du utformar din applikation. Du måste utforma det på ett sådant sätt att du kan koppla från din affärslogik från dina Android-komponenter. Här är ett exempel på ett sådant sätt med modell-View-Presenter-mönstret . Låter oss ut genom att implementera en grundläggande registreringsskärm som bara tar ett användarnamn och lösenord. Vår Android-app ansvarar för att bekräfta att användarnamnet som användaren anger inte är tomt och att lösenordet är minst åtta tecken långt och innehåller minst en siffra. Om användarnamnet / lösenordet är giltigt utför vi vårt registrerade api-samtal, annars visar vi ett felmeddelande.

Exempel där affärslogik är mycket kopplad till Android Component.

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();
        }
    }
}

Exempel där affärslogiken är frånkopplad från Android Component.

Här definierar vi i en enda klass, LoginContract, som kommer att hysa de olika interaktionerna mellan våra olika klasser.

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

Vår LoginActivity är till största delen densamma förutom att vi har tagit bort ansvaret för att behöva veta hur man validerar en användares registreringsformulär (vår affärslogik). LoginActivity kommer nu att förlita sig på vår nya LoginPresenter för att utföra validering.

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);
    }
    ...
}

Nu kommer din affärslogik att ligga i din nya klass LoginPresenter.

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();
        }
    }
}

Och nu kan vi skapa lokala JVM-enhetstester mot din nya LoginPresenter-klass.

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);
    }
}

Som ni kan se, när vi extraherade vår affärslogik ur LoginActivity och placerade den i LoginPresenter POJO . Vi kan nu skapa lokala JVM-enhetstester mot vår affärslogik.

Det bör noteras att det finns olika andra konsekvenser av vår förändring i arkitekturen, som att vi är nära att hålla fast vid varje klass med ett enda ansvar, ytterligare klasser, etc. Detta är bara biverkningar av det sätt jag väljer att utföra detta frikoppling via MVP-stil. MVP är bara ett sätt att ta itu med, men det finns andra alternativ som du kanske vill titta på, till exempel MVVM . Du måste bara välja det bästa systemet som fungerar för dig.

Komma igång med JUnit

Uppstart

För att starta enhetstestning av ditt Android-projekt med JUnit måste du lägga till JUnit-beroende till ditt projekt och du måste skapa en testkällsats som kommer att innehålla källkoden för enhetstesterna. Projekt skapade med Android Studio inkluderar ofta redan JUnit-beroende och testkällsats

Lägg till följande rad i din modul build.gradle fil inom beroenden Closure :

testCompile 'junit:junit:4.12'

JUnit-testklasser finns i en speciell källuppsättning med namnet test . Om den här källuppsättningen inte existerar måste du själv skapa en ny mapp. Mappstrukturen för ett standardprojekt för Android Studio (Gradle-baserat) ser ut så här:

<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)

Om ditt projekt inte har mappen /app/src/test måste du skapa den själv. I test mapp du behöver också en java folder (skapa den om den inte existerar). Mappen java i test set bör innehåller samma paket struktur som din main källa-set.

Om installationen korrekt ska din projektstruktur (i Android-vyn i Android Studio) se ut så här:

projektuppsättning

Obs! Du behöver inte nödvändigtvis ha androidTest - androidTest den här androidTest finns ofta i projekt skapade av Android Studio och inkluderas här för referens.


Att skriva ett test

  1. Skapa en ny klass i test .
    Högerklicka på testkällan i projektvyn och välj New > Java class .
    Det mest använda namngivningsmönstret är att använda namnet på klassen du ska testa med Test läggs till i det. Så StringUtilities blir StringUtilitiesTest .

  2. Lägg till @RunWith anteckningen
    @RunWith anteckningen behövs för att få JUnit att köra de tester vi ska definiera i vår testklass. Standard JUnit-löparen (för JUnit 4) är BlockJUnit4ClassRunner men istället för att använda detta körs direkt är det mer bekvämt att använda aliaset JUnit4 som är en kortfattning för standard JUnit-löparen.

     @RunWith(JUnit4.class)
     public class StringUtilitiesTest {
     
     }
    
  3. Skapa ett test
    Ett enhetstest är i huvudsak bara en metod som i de flesta fall inte borde misslyckas om den körs. Med andra ord bör det inte kasta ett undantag. Inuti en testmetod hittar du nästan alltid påståenden som kontrollerar om specifika villkor är uppfyllda. Om ett påstående misslyckas kastar det ett undantag som gör att metoden / testet misslyckas. En testmetod kommenteras alltid med @Test anteckningen. Utan denna kommentar kommer JUnit inte automatiskt att köra testet.

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

    Anmärkning: till skillnad från den vanliga Java-metoden för namngivningskonventionen innehåller testmetodnamn ofta understreck.


Köra ett test

  1. Metod
    För att köra en enda testmetod kan du högerklicka på metoden och klicka på Run 'addition_isCorrect()' eller använda kortkommandot ctrl+shift+f10 . Kör ett enda enhetstest

    Om allt är korrekt inställt börjar JUnit att köra metoden och du bör se följande gränssnitt i Android Studio:

    Testgränssnitt för Android Studio-enhet

  1. Klass
    Du kan också köra alla tester som definierats i en enda klass, genom att högerklicka på klassen i projektvyn och klicka på Run 'StringUtilitiesTest ' eller använda kortkommandot ctrl+shift+f10 om du har valt klassen i projektvyn.

  2. Paket (allt)
    Om du inte vill köra alla tester som definierats i projektet eller i ett paket kan du bara högerklicka på paketet och klicka på Run ... precis som du skulle köra alla tester som definierats i en enda klass.

undantag

JUnit kan också användas för att testa om en metod kastar ett specifikt undantag för en given ingång.

I det här exemplet testar vi om följande metod verkligen kastar ett undantag om det booleska formatet (input) inte känns igen / okänt:

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);
    }
}

Genom att lägga till den expected parametern till @Test anteckningen kan man definiera vilket undantag som förväntas kastas. Enhetstestet misslyckas om detta undantag inte inträffar och lyckas om undantaget verkligen kastas:

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

Detta fungerar bra, men det begränsar dig till bara ett enda testfall inom metoden. Ibland kanske du vill testa flera fall inom en enda metod. En teknik som ofta används för att övervinna denna begränsning använder try-catch block och Assert.fail() -metoden:

@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){
    }
}

Obs: Vissa människor anser att det är dåligt att testa mer än ett enda fall i ett enhetstest.

Statisk import

JUnit definierar en assertEquals del assertEquals minst en för varje primitiv typ och en för objekt är tillgänglig. Dessa metoder är som standard inte direkt tillgängliga att ringa och bör kallas så här: Assert.assertEquals . Men eftersom dessa metoder används så ofta använder människor nästan alltid en statisk import så att metoden kan användas direkt som om den är en del av klassen.

För att lägga till en statisk import för metoden assertEquals använder du följande importmeddelande:

import static org.junit.Assert.assertEquals;

Du kan också statisk importera alla påståndsmetoder inklusive assertArrayEquals , assertNotNull och assertFalse etc. med hjälp av följande statiska import:

import static org.junit.Assert.*;

Utan statisk import:

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

Med statisk import:

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow