So, I'm new to android unit testing. I'm trying to write a unit test for the Phone application:
package com.android.phone;
import android.content.Intent;
import android.net.Uri;
import android.test.ApplicationTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import com.android.phone.PhoneApp;
import dalvik.annotation.TestTargetClass;
#TestTargetClass(PhoneApp.class)
public class TestPhone extends ApplicationTestCase<PhoneApp> {
public TestPhone() {
super(PhoneApp.class);
}
private PhoneApp phone;
#Override
protected void setUp() throws Exception {
super.setUp();
phone = getApplication();
}
#MediumTest
public void testDialerIsUp() {
assertNotNull("Phone app does not exist", phone);
// TODO add tests
}
}
Then I start an emulator, wait till it boots up, and run those tests:
adb shell am instrument -e class com.android.phone.TestPhone -r -w com.android.phone.tests/android.test.InstrumentationTestRunner
And now I'm getting a junit.framework.AssertionFailedError: PhoneApp does not exist. What is wrong here, why isn't PhoneApp up?
Actually, I'd recommend calling createApplication() in your setUp() method before calling phone = getApplication().
You don't show the code for your PhoneApp. Did you derive a PhoneApp class from the android.app.Application class? Or are you expecting that there is just something called PhoneApp out there that you can test?
You will need to write an android.app.Application class as part of your project, if you expect to test something.
Or, perhaps, you are talking about something that I do not understand. That is always possible.
How does this even compile with "PhoneApp.class" in it if you just stick to the SDK?
I know you can use Robotium to test existing apps though.
Elaborating on Karim's answer (it does work), this is the setup method:
MyApplication application;
#Override
protected void setUp() throws Exception {
super.setUp();
createApplication();
application = getApplication();
}
Related
I have written a class to manage logging within an android application project.
The LogManager is basically a wrapper for android.util.log
It handles logging to a file, if the application crashes, and standard debug logging.
I would like to unit test the class using JUnit.
I have tried the following but it does not seem to produce the results I would expect after reading the examples:
LogManager.class (This is a simplified version of the class I have used, for demonstration purposes)
public class LogManager implements ILogManager
{
public void log(String tag, String message)
{
Log.e(tag, message);
}
}
And here is my test class
#RunWith(RobolectricGradleTestRunner.class)
#Config(constants = BuildConfig.class, sdk = 21)
#PrepareForTest({Log.class, LogManager.class})
public class LogManagerUnitTest
{
#Test
public void testLogConsoleInfo()
{
PowerMockito.mockStatic(Log.class);
LogManager.getInstance().log(LogLevel.INFO, "test", "test");
PowerMockito.verifyStatic(Mockito.times(1));
Log.e(anyString(), anyString());
}
}
My problem is that this passes no matter what I put.
E.g: if I instead replace the last call with Log.wtf(...) it still passes. I would have assumed that it should fail since Log.wtf was not called in the static class Log?
So my question is, why isn't this approach working as expected and what would be the correct way to do it?
I started a fresh project and was able to get it to fail tests and succeed appropriately using the following, so I'm assuming the runwith was the culprit:
#RunWith(PowerMockRunner.class)
#PrepareForTest(android.util.Log.class)
public class LoggerUnitTest {
#Test
public void testLog() throws Exception
{
PowerMockito.mockStatic(Log.class); // when(Log.e(anyString(), anyString())).thenReturn(1);
Logger.log("test", "test");
PowerMockito.verifyStatic(times(1));
Log.e(anyString(), anyString());
} }
For the RobolectricGradleTestRunner, the following incantation would have exposed your logging:
ShadowLog.stream = System.out
Robolectric does not print the Android system logging by default.
It's also worth noting that the RobolectricGradleTestRunner has been deprecated in favor of the fully operational RobolectricTestRunner (The above assignment is still effective)
I am developing a test for an Android app using cucumber-jvm. I wrote a feature and the corresponding steps. The console says that there is any test.
Did you have already this problem?
I don't know exactly what I'm doing wrong.
Running tests Test running startedTest running failed: No test results
Empty test suite.
"StepsDefinitions.java"
#CucumberOptions(features = "features")
public class StepsDefinitions extends ActivityInstrumentationTestCase2<LoginActivity> {
public StepsDefinitions() {
super(LoginActivity.class);
assertNotNull(getActivity());
Log.i("That","It is running.");
}
#Given("^I have a UserBox$")
public void I_am_on_the_Login_Screen() {
EditText etLoginUser = (EditText) getActivity().findViewById(R.id.User);
assertNotNull(etLoginUser);
}
#Then("^I should see on the display$")
public void I_should_see_s_on_the_display() {
EditText display = (EditText) getActivity().findViewById(R.id.Pass);
} }
Do you have the Runner class? You just need a small 'marker' class to tell JUnit to invoke the Cucumber test suite (put it in the same package as your StepDefinitions).
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
public class RunCukesTest {
// No further code needed
}
I am trying to run following Android JUnit3 test with robotium:
import android.test.ActivityInstrumentationTestCase2;
import com.package.sample.MyActivityClass;
import com.jayway.android.robotium.solo.Solo;
public class TestSample extends ActivityInstrumentationTestCase2<MyActivityClass> {
private Solo solo;
public TestSample() {
super("com.package.sample", MyActivityClass.class);
}
protected void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
}
public void clickbutton1() throws Exception{
solo.clickOnButton("abc");
solo.setActivityOrientation(Solo.LANDSCAPE);
assertTrue(solo.searchText("load"));
}
#Override
protected void tearDown() throws Exception{
solo.finishOpenedActivities();
}
}
The JUnit explores shows 0/0 tests runs. The debugger does not hit any code path mentioned here and Console outputs "test run finished"??:
Uploading MyAppTest.apk onto device 'emulator-5554'
Installing MyAppTest.apk...
Success!
Project dependency found, installing: MyApp
Uploading MyApp.apk onto device 'emulator-5554'
Installing MyApp.apk...
Success!
Launching instrumentation android.test.InstrumentationTestRunner on device emulator-5554
Collecting test information
Sending test information to Eclipse
Running tests...
Test run finished
Does anyone has an idea what is wrong? I have followed all steps in robotium tutorials religiously. I know there have been many questions around this but I have take care of all answers.
Also Robotium has similar problem with JUnit4 here.
Yes, I know what is wrong.
In order to run your tests, you need to begin them with test. So your code should be like this:
import android.test.ActivityInstrumentationTestCase2;
import com.package.sample.MyActivityClass;
import com.jayway.android.robotium.solo.Solo;
public class TestSample extends ActivityInstrumentationTestCase2<MyActivityClass> {
private Solo solo;
public TestSample() {
super("com.package.sample", MyActivityClass.class);
}
protected void setUp() throws Exception {
super.setUp();
solo = new Solo(getInstrumentation(), getActivity());
}
//the test methods MUST begin with test...
public void testClickbutton1() throws Exception{
solo.clickOnButton("abc");
solo.setActivityOrientation(Solo.LANDSCAPE);
assertTrue(solo.searchText("load"));
}
#Override
protected void tearDown() throws Exception{
solo.finishOpenedActivities();
}
}
I had a similar issue awhile ago, and Robotium doesn't have the greatest documentation. I hope this helps you out :)
I did everything what you said, but I still got error with 0/0 test.I had found the solution, which is related to constructors:
// I DELETED THIS CONSTRUCTOR
public TestHomeScreenTest(String pkg, Class<ScreenSlidePagerActivity> activityClass) {
super(pkg, activityClass);
}
//GOOD SOLUTION:
public TestHomeScreenTest() {
super("com.dolphin.homescreen", ScreenSlidePagerActivity.class);
}
and it now WOOORKS ! :)
I've got the basic scenario: a test project, in it - one test class, nothing less, nothing more. The code of the test class is this:
public class SManagerTest extends AndroidTestCase {
private SManager sm;
public SManagerTest(){
sm = SManager.getInstance(getContext());
}
#Test
public void trainTest(){
sm.go();
}
}
What's wrong? because I get this:
Test run failed: Test run incomplete. Expected 1 tests, received 0
Thanks!
As pointed out earlier use "test" with a small t and don't forget to run it as an "Android JUnit Test"
Agree with Christopher - start the method name with 'test' even though you're adding the #Test decorator. Also, add this class in the same folder as your tests and it will run all your tests:
public class AllTests extends TestSuite
{
public static Test suite()
{
return new TestSuiteBuilder(AllTests.class).includeAllPackagesUnderHere().build();
}
}
I've been trying to make a test case extending intstrumentationtestcase, and whenever I call getinstrumentation() it returns a null instance of Instrumentation instead of an Instrumentation, rendering any of the automation I'm wanting to do useless. I have the permission set in the manifest as well even though I'm only testing the automation on the same app this case is going to run on...any ideas?
You need inject the instrumentation programmatically by calling injectInstrumentation(InstrumentationRegistry.getInstrumentation()); using InstrumentationRegistry from the official Android testing-support-lib:0.1
I had a similar problem and it seems that the getInstrumentation() method returns a valid instrumentation only after the base class (InstrumentationTestCase) setUp method is called. Please look at the code below and check the LogCat debug messages:
import android.app.Instrumentation;
import android.test.InstrumentationTestCase;
import android.util.Log;
public class TestInstrumentation extends InstrumentationTestCase {
private static final String LOG_TAG = BrowseLocationsTest.class.getSimpleName();
private Instrumentation instr;
public TestInstrumentation() {
instr = getInstrumentation();
Log.d(LOG_TAG, "TestInstrumentation instrumentation: " + instr);
}
#Override
protected void setUp() throws Exception {
instr = getInstrumentation();
Log.d(LOG_TAG, "setUp instrumentation: " + instr);
super.setUp();
instr = getInstrumentation();
Log.d(LOG_TAG, "setUp instrumentation: " + instr);
}
public void testInstrumentation() {
Log.d(LOG_TAG, "testInstrumentation instrumentation: " + instr);
}
}
The instrumentation is right in place as expected right after the super.setUp() call.
Had the same problem while using the Testing Support Library with the '#RunWith(AndroidJUnit4.class)' annotation, even though I made sure to inject my instrumentation in the setUp() method as indicated by #Gallal and #Dariusz Gadomski, only it continued to throw NullPointerExceptions.
Turns out, I forgot to include the #Before annotation on my setup method so jUnit4 didn't run it, whereas before with the jUnit3 based Instrumentation tests, it would've run. Since I implemented the instrumentation injection in setUp(), it never got injected even though the code looked like it should have been injecting it.
So instead of
#Override
protected void setUp() throws Exception {
...
Be sure to use
#Before
public void setUp() throws Exception {
super.setUp();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
}
instead.
I think what you really need is Context, in JUnit4, we can get context by InstrumentationRegistry.getContext();