23

I have an Android project that shows "Hello World". It was created from the "Blank Activity" template from Android Studio.

I then add/create a new java class in my application package (the same package that has my activity). I call it Shape and add a simple constructor

public class Shape {
    public Shape(int i){
        if (i==0){
            throw new IllegalArgumentException("Cant have 0");
        }
    }
}

Great. Now I have a class that isn't touching Android at all, and I want to unit test it. What should I do next?

This is where my question stops. Below I'll go through what I tried.

Please note that I really have never tested before in Android or Java. Excuse me for "rookie" mistakes.

  1. While in the Shape.java I go to "Navigate" > "Test"
  2. Hit enter to select "Create new Test"
  3. Get this popup, and select JUNIT4.

enter image description here

  1. I then hit the fix button to fix the library not being found
  2. I get this popup

enter image description here

  1. I'm not really sure what to select, so I select the default/highlighted.
  2. I write my test

    package com.eghdk.getjunit4towork;
    
    import org.junit.Test;
    
    import static org.junit.Assert.*;
    
    public class ShapeTest {
        @Test(expected = IllegalArgumentException.class)
        public void testShapeWithInvalidArg() {
            new Shape(0);
        }
    }
    
  3. At this point, I'm not really sure how to run my tests, but try to do this: enter image description here

  4. I get these errors when running

    Error:(3, 17) Gradle: error: package org.junit does not exist
    Error:(5, 24) Gradle: error: package org.junit does not exist
    Error:(8, 6) Gradle: error: cannot find symbol class Test

JJD
  • 50,076
  • 60
  • 203
  • 339
EGHDK
  • 17,818
  • 45
  • 129
  • 204

4 Answers4

34

Since Android Studio 1.1, there is (experimental) unit test support. A couple of quotes from that page:

You will have to specify your testing dependencies in the build.gradle file of your android module. For example:

dependencies {
  testCompile 'junit:junit:4.12'
  testCompile "org.mockito:mockito-core:1.9.5"
}

To use unit testing support in AS, you have to do the following steps:

  1. Update build.gradle to use the android gradle plugin version 1.1.0-rc1 or later (either manually in build.gradle file or in the UI in File > Project Structure)

  2. Add necessary testing dependencies to app/build.gradle (see above).

  3. Enable the unit testing feature in Settings > Gradle > Experimental.

  4. Sync your project.

  5. Open the "Build variants" tool window (on the left) and change the test artifact to "Unit tests".

  6. Create a directory for your testing source code, i.e. src/test/java. You can do this from the command line or using the Project view in the Project tool window. The new directory should be highlighted in green at this point. Note: names of the test source directories are determined by the gradle plugin based on a convention.

  7. Create your test. You can do this by opening a class, right-clicking its name and selecting "Go to > Test". Add some test cases.
  8. Right click your new test class or method and select "Run ...".
  9. (Optional) You can decrease the compilation time by using Gradle directly. To do this, go to the Run menu and select "Edit configurations". There, find the default JUnit template, remove the "Make" before-launch step and add a "Gradle aware make" step instead (leave the task name empty).

It is important to know that there are two test types: androidTest and plain test.

  • androidTest is primarily for tests you run on an emulator or device, such as instrumentation tests. From the command line, you use ./gradlew connectedCheck to run these.
  • test is for tests you don't want to run on a device, such as the unit test you wrote. You run ./gradlew test to run these tests.

As stated in the quote, you switch between androidTest and test in Android Studio by changing the test artifact.

Naturally, it is preferred to not run tests on a device or emulator, since this speeds up the testing process a lot. With the new experimental unit test support, you gain access to stubbed Android API's without using a device. This lets you move more tests from androidTest to test.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
nhaarman
  • 98,571
  • 55
  • 246
  • 278
  • 1
    It seems like you're talking about Android specific unit tests that have to be run on the device. Even before this change in AS and the Android for Gradle plugin 1.1 I thought you could still run basic unit tests on your local machine (no android device). With that being said even though AS 1.1 is out, I feel like I don't have to enable experimental features to get PLAIN java unit tests. My question is for getting those (plain java unit tests) working. Are you aware of how to get that to work? – EGHDK Mar 03 '15 at 23:16
  • Before 1.1, I used the [Android Unit Test](https://github.com/JCAndKSolutions/android-unit-test) and [Android Studio Unit Test](https://github.com/evant/android-studio-unit-test-plugin) plugins, which enable exactly this. Naturally, these plugins have been deprecated in favor of the newly added functionality. – nhaarman Mar 03 '15 at 23:22
  • Hmm... really? My mistake then. I was certain I heard people talking about how you could do plain unit tests with nothing Android specific in the class with Junit and no other configuration. – EGHDK Mar 03 '15 at 23:34
  • Perhaps they were using JUnit3. Since the instrumentation tests use JUnit3, I can imagine those plain tests would get picked up as well. Just speculation though. – nhaarman Mar 03 '15 at 23:36
  • Makes sense. Thanks. Last question I have is why is there a src/main and src/androidTest? Since in your answer it says "Create a directory for your testing source code". Isn't that directory already created for new Android Studio projects? – EGHDK Mar 03 '15 at 23:46
  • If it's already created, you can use it of course. I tend to create projects from scratch, so I'd have to create it myself. The existence of these folders have to do with build types, as explained here: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Types – nhaarman Mar 03 '15 at 23:59
  • Understood. I was just confused because Eclipse never did that and Android Studio does it out of the box. It's the image under #8. You can see that two packages are seemingly created, but one is used for tests. I may ask another SO question just to get complete clarification on it. – EGHDK Mar 04 '15 at 00:04
  • Man I have spent like 3 full days on this! – TechSpellBound Apr 04 '15 at 13:17
  • 1
    The suggestion to decrease execution time of JUnit tests was also awesome! – TechSpellBound Apr 04 '15 at 14:09
  • This solution appears to no longer work for Android Studio 1.2. Also, your statement of "Naturally, it is preferred to not run tests on a device or emulator, since this speeds up the testing process a lot." isn't practical. Testing should be primarily done on a real device where you're going to see the real results. – Johann May 15 '15 at 06:45
  • @AndroidDev running plain Java code on a normal JVM versus a real device makes no practical difference. When making use of Android API's however you will need a real device of course. – nhaarman May 15 '15 at 06:56
  • 1
    Very well done! you did an excellent job differentiating the `InstrumentationTest` and `UnitTest` i.e `androidTest` & `test`. Thanks nhaarman :) – Muhammad Babar May 19 '15 at 08:05
  • Does breakpoints(debugging) works with UnitTest? Also Logs are not printing! – Muhammad Babar May 19 '15 at 10:06
  • 1
    @MuhammadBabar Breakpoints work for me. `android.util.Log` however won't work since there is no Android environment when you simply run the unit tests. For that purpose you can use `System.out.print*` family of methods. – Aleks N. Sep 02 '15 at 13:39
  • +1 For build variants. All these steps has been there apparently as defaults with new studio versions. I only needed to set the build variants (Y) – Mazen Elkashef Mar 02 '16 at 13:40
4

For android studio 1.2 or greater, I include this answer since this is one of the first ranking at google and this is an excelent and VERY easy to follow tutorial on how to set unit tests with Android Studio, this is the link: https://io2015codelabs.appspot.com/codelabs/android-studio-testing#1

After wasting 2 hours trying to run test I finally did it with the above link, hope it is as useful for you as for me.

CommonSenseCode
  • 23,522
  • 33
  • 131
  • 186
  • In Android Studio 2.2.1, under Build Variants, the "Test Artifact:" selection box does not appear, only the table with Model and Build Variant columns. So either it is located somewhere else, or you don't need to select that anymore. – Al Lelopath Oct 13 '16 at 15:05
3

Nowadays Android Studio (current ver. 1.4) has full Unit test support without any workarounds. Just as suggested in the automatically generated ExampleUnitTest:

To work on unit tests, switch the Test Artifact in the Build Variants view.

screen shot

Andrew
  • 36,676
  • 11
  • 141
  • 113
  • 2
    There is no more need to switch test artifacts in Android Studio 2.0. http://stackoverflow.com/questions/35708263/test-artifact-selector-missing-gone-from-build-variants-in-android-studio-2-beta – Noumenon Aug 01 '16 at 20:32
0

Go to settings then build tools then gradle and then experimental. In experimental uncheck enable all test artifacts. Thats it game over

Yash
  • 1
  • 1