How can I create tests in Android Studio?
Asked Answered
G

12

118

Just downloaded Android Studio which is based off of the Intellij Idea.

How would one create tests?

I notice there is a option for create a Test Module but this doesn't seem to do anything, only create a new project with src

I also tried pressing the hot key CTRL+AlT+T which allows to create unit tests on an existing class but it seems to want to place it in the current project. Of course this doesn't help with TDD

Does anyone have any experience here ?

Goltz answered 16/5, 2013 at 11:38 Comment(1)
I also have tried to create a test project. If you do it with the Android command line tool like you would with an Eclipse project, then you get an error because it can not find the AndroidManifest.xml file. It seems like Google needs to update their Android tool to deal with Grundle projects. However, I'm new to testing in Android so I can't help you =(Cautious
B
64

This answer is for people who are just getting started with Android testing. I will provide two simple examples to help you see how testing works. If you follow along for the next 10 minutes, you will be all set up to start adding your tests to your own app. I think you'll be surprised how easy it is. I certainly was.

Intro to Android Testing

There are two different types of tests that you will do.

  • Local unit tests. These are run locally on the JVM (Java Virtual Machine). Since they are local, they are fast. You can use them to test the parts of your code that just need Java and not the Android APIs. (Sometimes you can make a fake API object to test more things locally. This is called a mocking. A mock Context is an example.)
  • Instrumented tests. These tests are run on a real device or in the emulator. That makes them slower than the local tests. However, they are more flexible because you have the full Android API available to you.

Create a new project and you will see the following default folders.

enter image description here

Everything is already there and waiting for you to create your tests. It's all set up already!

How to create local unit tests

Open the ExampleUnitTest file shown in the image above. it should look something like this:

public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        assertEquals(4, 2 + 2);
    }
}

Press the double green arrow to run all the tests or the single green arrow to run only one. (In this case there is only one test so they both do the same thing.)

enter image description here

It should pass (as long as 2 + 2 is still 4 when you are reading this answer). Congratulations, you just ran your first test!

Making your own test

Let's write our own test. First add this class to your main app project so that we have something to test:

public class MyClass {
    public int add(int a, int b) {
        return a + b;
    }
}

Now change the addition_isCorrect() method in the test class to be like the following code (or just add another method with a different name):

public class ExampleUnitTest {
    @Test
    public void addition_isCorrect() throws Exception {
        MyClass myClass = new MyClass();
        int result = myClass.add(2, 2);
        int expected = 4;
        assertEquals(expected, result);
    }
}

Run it again and you should see it pass. Congratulations, you just created your own first test! (Well, I guess technically it was mine, but, hey, close enough. What's mine is yours.)

How to create instrumented tests

Open the ExampleInstrumentedTest file. it should look something like this:

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.example.myapp", appContext.getPackageName());
    }
}

Press one of those green buttons again.

enter image description here

As long as you have a real device connected or the emulator set up, it should have started it up and run your app. Congratulations, you just ran your first instrumented test!

Making your own test

The instrumented tests use Espresso to run the tests. It is kind of like your own little robot user that you can have test your app. You can tell it to do something like pressing a button or reading the properties of a TextView.

You can write the instructions for how to do the test by hand, but since we are just starting out, let's use the auto-record function. It's super simple.

First add a button to your UI so that we have something to work with. I did this:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.myapp.MainActivity">

    <Button
        android:id="@+id/myButton"
        android:text="Click me"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</android.support.constraint.ConstraintLayout> 

Then press Run > Record Espresso Test in the menu.

enter image description here

After it starts, click the button in the emulator and then to finish choose OK on the Record dialog. It should auto generate the following test code.

@LargeTest
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    @Rule
    public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);

    @Test
    public void mainActivityTest() {
        ViewInteraction appCompatButton = onView(
                allOf(withId(R.id.myButton), withText("Click me"), isDisplayed()));
        appCompatButton.perform(click());
    }
}

Great! You just created you first instrumented test! That was super easy. You should probably add an assertion to make it a real test, but that that is pretty easy to do with the recorder, too. Watch this video to go a little deeper.

Further Study

I'd watch the videos first and then read through the documentation. It is all pretty helpful. The last link is to a series of articles that cover some important things to think about when choosing what to test.

Beatty answered 26/4, 2017 at 6:51 Comment(3)
Great answer @Suragch. Quick question: where would I put support files for the local unit test case? It's hacky, but I'd be happy to put the full path from the base of the test, but if I run in Android Studio, the tests run from root_/app, however if I run from Gradle command line (or CI) then it is _root. (Ideally I'd like to access specific assets folders when run either way).Infrastructure
@mm2001, I wrote this answer as a way to learn how to do testing myself, so I haven't even gotten as far as you have. If you figure this out before I do, can you leave a comment?Beatty
I found this useful: https://mcmap.net/q/172873/-android-studio-unit-testing-read-data-input-file - it says create a folder test/resources and put files there, e.g. test.txt and access them with getClass().getClassLoader().getResource("test.txt"). I've decided that accessing the APK assets directly is likely a bad idea, so I'll deal with that by either copying the files to test in a build step, or in an external update process. There's some question remaining about different versions of Gradle, but I haven't faced that yet.Infrastructure
G
36

Edit: As of 0.1.8 this is now supported in the IDE. Please follow the instructions in there, instead of using the instructions below.

Following the Android Gradle Plugin User Guide I was able to get tests working on the command line by performing the following steps on a newly created project (I used the default 'com.example.myapplication' package):

  1. Add a src/instrumentTest/java directory for the tests
  2. Add a test class (extending ActivityTestCase) in the package com.example.myapplication.test
  3. Start a virtual device
  4. On the command line (in the MyApplicationProject/MyApplication directory) use the command '../gradlew connectedInstrumentTest'

This ran my tests and placed the test results in MyApplicationProject/MyApplication/build/reports/instrumentTests/connected. I'm new to testing Android apps, but it seem to work fine.

From within the IDE, it's possible to try and run the same test class. You'll need to

  1. Update build.gradle to list Maven Central as a repo
  2. Update build.gradle add JUnit 3.8 as a instrumentTestCompile dependency e.g. instrumentTestCompile 'junit:junit:3.8'
  3. In 'Project Structure' manually move JUnit to be first in the dependency order

However this fails (the classpath used when running the tests is missing the test output directory). However, I'm not sure that this would work regardless as it's my understanding that an Android specific test runner is required.

Guddle answered 2/6, 2013 at 9:22 Comment(0)
A
20

I would suggest to use gradle.build file.

  1. Add a src/androidTest/java directory for the tests (Like Chris starts to explain)

  2. Open gradle.build file and specify there:

    android {
    
        compileSdkVersion rootProject.compileSdkVersion
        buildToolsVersion rootProject.buildToolsVersion
    
        sourceSets {
    
            androidTest {
                java.srcDirs = ['androidTest/java']
            }
        }
    }
    
  3. Press "Sync Project with Gradle file" (at the top panel). You should see now a folder "java" (inside "androidTest") is a green color.

  4. Now You are able to create there any test files and execute they.

Affected answered 3/12, 2013 at 10:43 Comment(5)
Don't forget androidTest.setRoot('instrumentTest')Mayolamayon
In current Android Studio version it is not necessary, more over - replace everything that has a name instrumentTest with androidTestAffected
The names 'instrumentTest' and 'androidTest' are totally arbitrary. They are just directory names for your test project. You can just as well create a 'tests' directory. Besides, the SDK's package name in the testing framework is android.test.InstrumentationTestCase. So canonically I believe 'instrument' or 'instrumentation' still makes sense for naming one's tests. See the following sourcecode: grepcode.com/file/repository.grepcode.com/java/ext/…Mayolamayon
Please, read the documentation here: tools.android.com/tech-docs/new-build-system. Since version 0.9.0 instrumentTest was renamed androidTest.Affected
@Mayolamayon Naming folder as androidTest is NOT arbitrary. It must be done in order for the folder to turn green.Infusionism
T
12

I think this post by Rex St John is very useful for unit testing with android studio.


(source: rexstjohn.com)

Tumefy answered 14/4, 2014 at 14:16 Comment(0)
K
12

Android Studio v.2.3.3

Highlight the code context you want to test, and use the hotkey: CTRL+SHIFT+T

Use the dialog interface to complete your setup.

The testing framework is supposed to mirror your project package layout for best results, but you can manually create custom tests, provided you have the correct directory and build settings.

Koehn answered 1/11, 2017 at 11:45 Comment(0)
C
7

As of now (studio 0.61) maintaining proper project structure is enough. No need to create separate test project as in eclipse (see below).

Tests structure

Couchman answered 22/6, 2014 at 14:29 Comment(0)
M
4

Android Studio keeps evolving so the responses above will eventually be no longer applicable. For the current version of Android Studio 1.2.1.1, there's a nice tutorial on testing at:

http://evgenii.com/blog/testing-activity-in-android-studio-tutorial-part-1/

Mc answered 15/5, 2015 at 12:48 Comment(1)
Yes, AS keeps evolving, so it is rather silly for someone to create an article about cutting edge tech, and never mention the version number it applies to. the only clue is a date at the very bottom.Stichter
C
3

One of the major changes it seems is that with Android Studio the test application is integrated into the application project.

I'm not sure if this helps your specific problem, but I found a guide on making tests with a Gradle project. Android Gradle user Guide

Cautious answered 30/5, 2013 at 2:14 Comment(0)
S
3

The easiest way I found is the streamlined in my following blog post:

  1. Create a folder in which you'll write all your unit tests (preferably com.example.app.tests)
  2. Create a new test class (preferably NameOfClassTestedTests, i.e BankAccountLoginActivityTests)
  3. Extend InstrumentationTestCase
  4. Write a failing unit test to make sure we succeeded configuring unit tests
  5. Note that a unit test method name must start with the word “test” (preferably testTestedMethodNameExpectedResult() i.e testBankAccountValidationFailedShouldLogout())
  6. Configure your project for unit tests:
  7. Open the 'Run...' menu and click 'edit configurations'
  8. Click the + button
  9. Select the Android Tests template
  10. Input a name for your run configuration (preferably 'AppName Tests')
  11. Select your app in the module combobox
  12. Select the “All In Package” radio button (generally you'd want to select this option because it runs all unit tests in all your test classes)
  13. Fill in the test package name from step 1 (i.e com.example.app.tests)
  14. Select the device you wish to run your tests on
  15. Apply and save the configuration
  16. Run unit tests (and expect failure):
  17. Select your newly created Tests configuration from the Run menu
  18. Click Run and read the results in the output console

Good luck making your code more readable, maintainable and well-tested!

Showalter answered 12/6, 2015 at 18:19 Comment(1)
The question was about instrumentation tests! I also have difficulties writing some instrumentation test. See my question at #35427490Massimiliano
S
2

Android Studio has been kind of a moving target, first being a developer preview and now being in beta. The path for the Test classes in the project has changed during time, but no matter what version of AS you are using, the path is declared in your .iml file. Currently, with version 0.8.3, you'll find the following inside the inner iml file:

      <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
  <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
  <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
  <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
  <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
  <sourceFolder url="file://$MODULE_DIR$/src/androidTest/groovy" isTestSource="true" />
  <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
  <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />

The .iml file is telling you where to place your test classes.

Saint answered 24/10, 2014 at 7:33 Comment(0)
P
2

As of Android Studio 1.1, we've got official (experimental) support for writing Unit Tests (Roboelectric works as well).

Source: https://sites.google.com/a/android.com/tools/tech-docs/unit-testing-support

Prickle answered 10/2, 2015 at 15:47 Comment(1)
The support for writing Android tests, just got enhanced, with the new support test library. You can see a nice presentation here :docs.google.com/presentation/d/…Prickle
P
0

Add below lib inside gradle file

 androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

Create class HomeActivityTest inside androidTest directory and before running the test add flurry_api_key and sender_id string inside string resource file and change the value for failure and success case.

@RunWith(AndroidJUnit4.class)
public class HomeActivityTest
{
    private static final String SENDER_ID = "abc";
    private static final String RELEASE_FLURRY_API_KEY = "xyz";

    @Test
    public void gcmRegistrationId_isCorrect() throws Exception
    {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        Assert.assertEquals(SENDER_ID, appContext.getString(R.string.sender_id));
    }

    @Test
    public void flurryApiKey_isCorrect() throws Exception
    {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        Assert.assertEquals(RELEASE_FLURRY_API_KEY, appContext.getString(R.string.flurry_api_key));
    }
}
Persis answered 4/4, 2017 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.