Question

I'm trying Android Studio 0.5.8 with gradle.

My current root build file:

buildscript {
    repositories {
        mavenCentral()
        maven {
            url 'https://oss.sonatype.org/content/repositories/snapshots'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.9.+'
        classpath 'com.novoda.gradle:robolectric-plugin:0.0.1-SNAPSHOT'
    }
}

allprojects {
    repositories {
        mavenCentral()
        maven {
            url 'https://oss.sonatype.org/content/repositories/snapshots'
        }
    }
}

My app build.gradle:

apply plugin: 'android'
apply plugin: 'robolectric'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    dependencies {
        androidTestCompile 'org.robolectric:robolectric:2.3-SNAPSHOT'
        androidTestCompile 'org.mockito:mockito-all:1.9.5'
        androidTestCompile 'junit:junit:4.+'
    }

    defaultConfig {
        minSdkVersion 9
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:19.1.0'
}

task addTest {
    def src = ['src/test/java']
    def file = file("app.iml")

    doLast {
        try {
            def parsedXml = (new XmlParser()).parse(file)
            def node = parsedXml.component[1].content[0]
            src.each {
                def path = 'file://$MODULE_DIR$/' + "${it}"
                def set = node.find { it.@url == path }
                if (set == null) {
                    new Node(node, 'sourceFolder', ['url': 'file://$MODULE_DIR$/' + "${it}", 'isTestSource': "true"])
                    def writer = new StringWriter()
                    new XmlNodePrinter(new PrintWriter(writer)).print(parsedXml)
                    file.text = writer.toString()
                }
            }
        } catch (FileNotFoundException e) {
            // nop, iml not found
        }
    }
}

gradle.projectsEvaluated {
    preBuild.dependsOn(addTest)
}

tasks.withType(Test) {
    scanForTestClasses = false
    include "**/*Test.class"
}

and this is my test Application class:

public class NSApplicationTest extends NSApplication {

    @Override
    public Context getContext() {
        return mock(Context.class);
    }

    @Override
    public AlarmManager getAlarmManager() {
        return mock(AlarmManager.class);
    }
}

The problem with this configuration is that the task addTest is loading even the NSApplicationTest class as test and it's failing with an:

   com.pack.scheduler.app.NSApplicationTest > initializationError FAILED
        java.lang.Exception  

So I tried to change the name extension to see if this would fix everything but I'm still getting the same error. Then I tried with @Ignore on NSApplicationTest.

Unable to load JUnit4 runner to calculate Ignored test cases
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
        at org.gradle.api.internal.tasks.testing.junit.AllExceptIgnoredTestRunnerBuilder$FallbackJUnit4Builder.runnerForClass(AllExceptIgnoredTestRunnerBuilder.java:52)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
        at org.gradle.api.internal.tasks.testing.junit.IgnoredTestDescriptorProvider.getAllDescriptions(IgnoredTestDescriptorProvider.java:31)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestEventAdapter.processIgnoredClass(JUnitTestEventAdapter.java:104)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestEventAdapter.testIgnored(JUnitTestEventAdapter.java:92)
        at org.junit.runner.notification.RunNotifier$6.notifyListener(RunNotifier.java:175)
        at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:61)
        at org.junit.runner.notification.RunNotifier.fireTestIgnored(RunNotifier.java:172)
        at org.junit.internal.builders.IgnoredClassRunner.run(IgnoredClassRunner.java:16)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:86)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:49)
        at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
        at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at $Proxy2.processTestClass(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:103)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
        at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
        at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)
Caused by: org.junit.internal.runners.InitializationError
        at org.junit.internal.runners.MethodValidator.assertValid(MethodValidator.java:57)
        at org.junit.internal.runners.JUnit4ClassRunner.validate(JUnit4ClassRunner.java:47)
        at org.junit.internal.runners.JUnit4ClassRunner.<init>(JUnit4ClassRunner.java:37)
        ... 39 more           

Any ideas on how to solve this problem?

Was it helpful?

Solution

You don't need write your own TestRunner. Just use the correct naming schema for your test application class: TestNSApplication (instead of NSApplicationTest)

Often I see following pattern:

  • *Test marks test execution classes
  • Test* marks class extensions for make a class testable

I expect you already know that this class must have the same package as your application class.

OTHER TIPS

Ok, apparently I solved it using a custom runner:

public class RobolectricGradleTestRunner extends RobolectricTestRunner {
    public RobolectricGradleTestRunner(Class<?> testClass) throws InitializationError {
        super(testClass);
    }

    @Override
    protected Class<? extends TestLifecycle> getTestLifecycleClass() {
        return MyTestLifecycle.class;
    }

    public static class MyTestLifecycle extends DefaultTestLifecycle {
        @Override
        public Application createApplication(final Method method, final AndroidManifest appManifest) {
            return new TestNSApplication();
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top