Developing mobile applications for the Android platform requires not only writing functional code, but also carefully checking its functionality. The tool Android Studio provides powerful built-in tools to automate this process, allowing you to create tests at various levels. Understanding how to make a test in Android Studio is critical to ensuring the stability of your product before releasing it to the store.

Many beginners encounter difficulties when initially setting up a testing environment, becoming confused about dependencies and types of tests. However, having mastered the basic principles of working with libraries, you can significantly reduce the time spent searching for bugs. This article will examine in detail the process of creating tests, from setting up the project to interpreting the execution results. JUnit And Espresso, you can significantly reduce the time spent searching for bugs. This article will go into detail about the process of creating tests, from setting up the project to interpreting the execution results.

Preparing the environment and project structure

Before you start writing test code, you need to make sure that your project is configured correctly. The standard Android Studio template already provides directories for tests, but sometimes you need to manually add the necessary dependencies to the build file. Open the file build.gradle (Module: app) and check for the presence of blocks testImplementation and androidTestImplementation.

For local tests that run on the JVM of your computer, a library is usually used JUnit. It allows you to check the logic of classes without having to launch an emulator or physical device. This is the fastest way to validate algorithms and process data.

  • ๐Ÿ“‚ Make sure that the folder src/test/java exists and contains packages that match the structure of your main code.
  • ๐Ÿ“ฆ Check the version of the JUnit library, as the annotation syntax in version 4 and 5 may be different.
  • โš™๏ธ Sync your project with Gradle files after making dependency changes to avoid compilation errors.

โš ๏ธ Warning: If you are using older versions of Android Studio or Gradle plugin, some modern testing features may not be available. Always check version compatibility with Google's official documentation, as tools are updated regularly.

๐Ÿ’ก

Use the latest stable version of Android Studio to avoid bugs in the development tool itself that may mask errors in your code.

Creating a local unit test using JUnit

Unit testing focuses on testing individual code modules, such as methods or classes, in isolation from the rest of the application. To create such a test, right-click on the source package and select the option New โ†’ Java/Kotlin Class in the tests directory. Name the file by adding a suffix Test to the name of the class being tested.

Inside the test file, you need to use special annotations that control the test lifecycle. Annotation @Test marks the method as a test script that will be executed by the framework. An annotation is often used to prepare data before each run. @Before.

@Test

public void addition_isCorrect() {

assertEquals(4, 2 + 2);

}

The main task of such a test is to compare the expected result with the actual one. If the values โ€‹โ€‹do not match, the test fails and you will receive a detailed error report. This allows you to instantly find logical inconsistencies in mathematical calculations or string processing.

๐Ÿ“Š What language do you use for tests?
Java
Kotlin
Groovy
I donโ€™t write tests

Writing instrumental tests with Espresso

Unlike local tests, instrumental tests require running on a real device or emulator. The library Espresso is the de facto standard for UI testing in the Android ecosystem. It allows you to simulate user actions, such as pressing buttons, entering text, and scrolling lists.

To work with Espresso, you need to add the appropriate dependencies to the block androidTestImplementation. The syntax of this library is built on call chains, which makes the code readable and similar to natural language. You specify which element to find (onView), what action to perform (perform) and which statement to check (check).

Component Purpose Use example
onView Search for an element interface onView(withId(R.id.button))
perform Executing an action perform(click())
check Checking status check(matches(isDisplayed()))
withText Searching by text withText("Hello")

When writing such tests, it is important to take into account the asynchronous nature of the interface. Espresso automatically waits for the completion of basic operations in the main thread, but when working with network requests or complex animations, additional ones may be required. settings IdlingResource.

โ˜‘๏ธ Preparing for the UI test

Done: 0 / 4

Running tests and analyzing results

After writing the code, you need to run a test. In the Android Studio toolbar, find the "Run" icon next to the name of the class or specific test method. You can also run all tests at once through the menu Run โ†’ Run 'Tests in ...'.

The execution results are displayed in the window Run at the bottom of the screen. Successful tests are highlighted in green, and failed tests are highlighted in red. If it fails, you will see a stack trace, which will indicate the exact line of code where the discrepancy between the expected and actual results occurred.

Log analysis is a key part of the debugging process. Often the error lies not in the statement itself, but in incorrect data preparation or the state of the application before the test. Use system logs and console output for a deep understanding of the reasons for the failure.

โš ๏ธ Attention: Instrumental tests are much slower than local ones, since they require installing an APK on the device. Do not run the entire set of UI tests for every small code change so as not to waste time.

Why does the test fail only on the emulator?

Often the reason lies in differences in Android API versions or missing Google Play services on clean emulator images. Always test tests on a physical device before release.

Parameterized tests to test multiple data

Sometimes you need to test the same logic on different sets of input data. Writing a separate method for each case is inefficient. In such cases, parameterized tests come to the rescue, allowing you to run one script with different arguments.

To implement this approach, JUnit 4 uses an annotation @RunWith(Parameterized.class) and a special method that returns a collection of data. In JUnit 5, the syntax is different and uses annotation @ParameterizedTest together with data sources.

This is especially useful when testing validation functions, math calculations, or string formatting. You can set tolerance limits, edge cases, and known invalid data in one parameter table.

  • โœ… Saves time writing boilerplate code for repeated checks.
  • ๐Ÿ“Š Makes the test report more visual, showing exactly which data failed.
  • ๐Ÿ”„ Allows you to easily expand test coverage by simply adding new rows to the data array.
๐Ÿ’ก

Test parameterization increases the reliability of the code, forcing the developer to think through not only standard scenarios, but also the boundary conditions of the algorithms.

Frequent errors and ways to eliminate them

Even experienced developers encounter problems when setting up testing. One common mistake is trying to use Android Framework classes (for example Context or Activity) in local tests without special preparation. There are mock libraries for this, such as Mockito.

Another problem is โ€œfragileโ€ interface tests that break at the slightest change in layout. To avoid this, use resource IDs (testTag) specifically for tests, rather than relying on button text or the order of items in a list.

If tests are taking too long to run, check to see if they are blocking the thread with waits. Sometimes increasing the timeout or optimizing database queries inside the test script helps.

โš ๏ธ Attention: Never use real servers or production databases in automated tests. This may lead to data corruption or blocking of your account due to suspicious activity. Use stubs and local databases.

FAQ: Frequently Asked Questions

What is the difference between src/test and src/androidTest?

The directory src/test is intended for local unit tests that are executed on the developer's computer and do not require a device. The directory src/androidTest contains instrumented tests that run on an emulator or a real smartphone and have access to the Android API.

How to run only one specific test?

In Android Studio, a green "Play" icon appears next to the method or class name in the code editor. Clicking on it will run only that specific script, which is convenient for quick debugging.

Is it possible to test applications in Kotlin?

Yes, Android Studio fully supports writing tests in Kotlin. The syntax of the JUnit and Espresso libraries is adapted for Kotlin, which makes the code more concise and expressive.

What to do if a test passes locally, but fails on CI?

This is often due to differences in the environment. Check SDK, emulator and dependency versions. Also make sure that the continuous integration server has all the necessary system images and access rights installed.