Stack Overflow
Stack Overflow

Reputation: 2968

Why are there three directories/folders for the java source in Android?

I am new to Android development. When I created a new Android Studio project there are three directories generated inside the java section:

enter image description here

In fact our concern is with the java file that is inside the first directory which is in my case com.example.myapplication -> MainActivity.

Why are there three directories each containing java files and for what purpose are these directories created?

Upvotes: 1

Views: 447

Answers (2)

Nurbol
Nurbol

Reputation: 371

According to wikipedia, development testing is a software development process that involves synchronized application of a broad spectrum of defect prevention and detection strategies in order to reduce software development risks, time, and costs, see.

Folders:
First (com.example.myapplication) for actual source code. For example, java/kotlin files of activities, services, broadcast receivers, content providers, models, utilities etc.

Second (com.example.myapplication(andoridTest)) is for instrumental testing that runs on android OS. As an example, assume that we have MainActivity with a button. Toast with a message is shown when the button is clicked. So we can test whether the button works correctly as following(imports are provided for simplicity):

import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner;
import androidx.test.rule.ActivityTestRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.RootMatchers.withDecorView;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.not;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.matcher.ViewMatchers.withId;

@RunWith(AndroidJUnit4ClassRunner.class)
public class ExampleAndroidTest {

    @Rule
    public ActivityTestRule<Main2Activity> mActivityRule =
            new ActivityTestRule<>(Main2Activity.class);

    @Test
    public void buttonClickShowingToast_isCorrect() {
        onView(withId(R.id.bt_test)).perform(click());
        onView(withText(R.string.toast_test))
            .inRoot(withDecorView(not(
                    mActivityRule.getActivity().getWindow().getDecorView()
            ))).check(matches(isDisplayed()));
}
}

Third (com.example.myapplication(test)) is for Unit tests that can be run on local machine, means doesn't require android OS. For example, we are creating a timer and we have an utility method that converts seconds to HH:MM:SS format. The method is:

public static String getHoursMinutesSeconds(int seconds) {
    int minutes = seconds / 60;
    seconds %= 60;
    int hours = minutes / 60;
    minutes %= 60;

    String strSec = Integer.toString(seconds);
    String strMin = Integer.toString(minutes);
    String strHour = Integer.toString(hours);
    StringBuilder sb = new StringBuilder();
    if (strHour.length() < 2) sb.append(0);
    sb.append(strHour);
    sb.append(':');
    if (strMin.length() < 2) sb.append(0);
    sb.append(strMin);
    sb.append(':');
    if (strSec.length() < 2) sb.append(0);
    sb.append(strSec);

    return sb.toString();
}

As the method doesn't require Android APIs to be tested. It has to be tested on local machine(as it is much faster). So the Unit tests code:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;

import io.jachoteam.taxiapp.views.WaitingIndicatorView;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

@RunWith(BlockJUnit4ClassRunner.class)
public class ExampleUnitTest {

    @Test
    public void getHoursMinutesSeconds_isCorrect1() {
        String actualValue = WaitingIndicatorView.getHoursMinutesSeconds(1);
        assertThat(actualValue, is(equalTo("00:00:01")));
    }

    @Test
    public void getHoursMinutesSeconds_isCorrect2() {
        String actualValue = WaitingIndicatorView.getHoursMinutesSeconds(60);
        assertThat(actualValue, is(equalTo("00:01:00")));
    }
}

Writing tests for each written unit of code is the best practice. Cause it makes developer's life easier when a project gets big to maintain by providing bug detecting in early stages(while fresh=)) and validating the code every time it has been changed.

Upvotes: 2

BlackHatSamurai
BlackHatSamurai

Reputation: 23493

Per the Android docs:

/test: Contains code for local tests that run on your host JVM.

/androidtest Instrumentation tests, run on the OS.

/module-name: This is where the program source code lives

Upvotes: 1

Related Questions