diff options
author | Nick Korostelev <nkorsote@google.com> | 2014-06-20 16:52:19 -0700 |
---|---|---|
committer | Nick Korostelev <nkorsote@google.com> | 2014-08-07 21:52:07 +0000 |
commit | 4771553b614aa042d8456df1dd73aae761c106d8 (patch) | |
tree | 7b97edfdc58984fb2ac35dcac36ddf7761221c0d | |
parent | 976c4234127805d7dc9a1cdbcb42b5d9f4585771 (diff) | |
download | testing-4771553b614aa042d8456df1dd73aae761c106d8.tar.gz |
Adding support for loading classes/methods from file
Added testFile argument to AndroidJunitRunner which allows to run all tests listed in a file:
adb shell am instrument -w -e testFile /sdcard/tmp/testFile.txt com.android.foo/com.android.test.runner.AndroidJUnitRunner
The file should contain a list of line separated test classes and methods.
bug: 16031984
Change-Id: Idf3e5e12f65ed670f31dad54bf3f0e303114c755
(cherry picked from commit da785cf4556f8bfc347c8118b42c74dc0ec59f58)
5 files changed, 111 insertions, 8 deletions
diff --git a/support/src/android/support/test/internal/runner/ClassPathScanner.java b/support/src/android/support/test/internal/runner/ClassPathScanner.java index 300c7de..ac34406 100644 --- a/support/src/android/support/test/internal/runner/ClassPathScanner.java +++ b/support/src/android/support/test/internal/runner/ClassPathScanner.java @@ -44,7 +44,7 @@ class ClassPathScanner { * Tests whether or not the specified abstract pathname should be included in a class path * entry list. * - * @param pathName the relative path of the class path entry + * @param className the relative path of the class path entry */ boolean accept(String className); } diff --git a/support/src/android/support/test/internal/runner/TestRequestBuilder.java b/support/src/android/support/test/internal/runner/TestRequestBuilder.java index 82f007e..4a8383f 100644 --- a/support/src/android/support/test/internal/runner/TestRequestBuilder.java +++ b/support/src/android/support/test/internal/runner/TestRequestBuilder.java @@ -267,7 +267,7 @@ public class TestRequestBuilder { } /** - * Class that filters out tests annotated with {@link RequestDevice} when running on emulator + * Class that filters out tests annotated with {@link RequiresDevice} when running on emulator */ private class RequiresDeviceFilter extends AnnotationExclusionFilter { @@ -518,6 +518,7 @@ public class TestRequestBuilder { * @param instr the {@link Instrumentation} to inject into any tests that require it * @param bundle the {@link Bundle} of command line args to inject into any tests that require * it + * @param skipExecution whether or not to skip actual test execution * @param computer Helps construct Runners from classes * @param classes the classes containing the tests * @return a <code>Request</code> that will cause all tests in the classes to be run diff --git a/support/src/android/support/test/runner/AndroidJUnitRunner.java b/support/src/android/support/test/runner/AndroidJUnitRunner.java index 42cdc73..f07bf0c 100644 --- a/support/src/android/support/test/runner/AndroidJUnitRunner.java +++ b/support/src/android/support/test/runner/AndroidJUnitRunner.java @@ -46,7 +46,12 @@ import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.notification.RunListener; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.List; @@ -88,6 +93,11 @@ import java.util.List; * -e class com.android.foo.FooTest,com.android.foo.TooTest * com.android.foo/android.support.test.runner.AndroidJUnitRunner * <p/> + * <b>Running all tests listed in a file:</b> adb shell am instrument -w + * -e testFile /sdcard/tmp/testFile.txt com.android.foo/com.android.test.runner.AndroidJUnitRunner + * The file should contain a list of line separated test classes and optionally methods (expected + * format: com.android.foo.FooClassName#testMethodName). + * <p/> * <b>Running all tests in a java package:</b> adb shell am instrument -w * -e package com.android.foo.bar * com.android.foo/android.support.test.runner.AndroidJUnitRunner @@ -168,16 +178,22 @@ public class AndroidJUnitRunner extends MonitoringInstrumentation { private static final String ARGUMENT_DEBUG = "debug"; private static final String ARGUMENT_LISTENER = "listener"; private static final String ARGUMENT_TEST_PACKAGE = "package"; + static final String ARGUMENT_TEST_FILE = "testFile"; // TODO: consider supporting 'count' from InstrumentationTestRunner private static final String LOG_TAG = "AndroidJUnitRunner"; + // used to separate multiple fully-qualified test case class names + private static final char CLASS_SEPARATOR = ','; + // used to separate fully-qualified test case class name, and one of its methods + private static final char METHOD_SEPARATOR = '#'; + private Bundle mArguments; @Override public void onCreate(Bundle arguments) { super.onCreate(arguments); - mArguments = arguments; + setArguments(arguments); specifyDexMakerCacheProperty(); start(); @@ -411,11 +427,16 @@ public class AndroidJUnitRunner extends MonitoringInstrumentation { String testClassName = arguments.getString(ARGUMENT_TEST_CLASS); if (testClassName != null) { - for (String className : testClassName.split(",")) { + for (String className : testClassName.split(String.valueOf(CLASS_SEPARATOR))) { parseTestClass(className, builder); } } + String testFilePath = arguments.getString(ARGUMENT_TEST_FILE); + if (testFilePath != null) { + parseTestClassesFromFile(testFilePath, builder); + } + String testPackage = arguments.getString(ARGUMENT_TEST_PACKAGE); if (testPackage != null) { builder.addTestPackageFilter(testPackage); @@ -475,10 +496,10 @@ public class AndroidJUnitRunner extends MonitoringInstrumentation { * * @param testClassName - full package name of test class and optionally method to add. * Expected format: com.android.TestClass#testMethod - * @param testSuiteBuilder - builder to add tests to + * @param testRequestBuilder - builder to add tests to */ private void parseTestClass(String testClassName, TestRequestBuilder testRequestBuilder) { - int methodSeparatorIndex = testClassName.indexOf('#'); + int methodSeparatorIndex = testClassName.indexOf(METHOD_SEPARATOR); if (methodSeparatorIndex > 0) { String testMethodName = testClassName.substring(methodSeparatorIndex + 1); @@ -489,6 +510,38 @@ public class AndroidJUnitRunner extends MonitoringInstrumentation { } } + /** + * Parse and load the content of a test file + * + * @param filePath path to test file contaitnig full package names of test classes and + * optionally methods to add. + * @param testRequestBuilder - builder to add tests to + */ + private void parseTestClassesFromFile(String filePath, TestRequestBuilder testRequestBuilder) { + List<String> classes = new ArrayList<String>(); + BufferedReader br = null; + String line; + try { + br = new BufferedReader(new FileReader(new File(filePath))); + while ((line = br.readLine()) != null) { + classes.add(line); + } + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, String.format("File not found: %s", filePath), e); + } catch (IOException e) { + Log.e(LOG_TAG, + String.format("Something went wrong reading %s, ignoring file", filePath), e); + } finally { + if (br != null) { + try { br.close(); } catch (IOException e) { /* ignore */ } + } + } + + for (String className : classes) { + parseTestClass(className, testRequestBuilder); + } + } + private void setupDexmakerClassloader() { ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); // must set the context classloader for apps that use a shared uid, see diff --git a/support/tests/src/android/support/test/internal/runner/TestRequestBuilderTest.java b/support/tests/src/android/support/test/internal/runner/TestRequestBuilderTest.java index f28c894..f58f39f 100644 --- a/support/tests/src/android/support/test/internal/runner/TestRequestBuilderTest.java +++ b/support/tests/src/android/support/test/internal/runner/TestRequestBuilderTest.java @@ -627,7 +627,7 @@ public class TestRequestBuilderTest { } /** - * Test that {@link RequiresDevuce} filters tests as appropriate + * Test that {@link RequiresDevice} filters tests as appropriate */ @Test public void testRequiresDevice() { diff --git a/support/tests/src/android/support/test/runner/AndroidJUnitRunnerTest.java b/support/tests/src/android/support/test/runner/AndroidJUnitRunnerTest.java index 7952980..245612a 100644 --- a/support/tests/src/android/support/test/runner/AndroidJUnitRunnerTest.java +++ b/support/tests/src/android/support/test/runner/AndroidJUnitRunnerTest.java @@ -18,17 +18,25 @@ package android.support.test.runner; import android.content.Context; import android.os.Bundle; import android.support.test.internal.runner.TestRequestBuilder; -import android.support.test.runner.AndroidJUnitRunner; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; import java.io.PrintStream; +import java.io.Reader; +import java.io.StringReader; /** * Unit tests for {@link AndroidJUnitRunner}. @@ -99,4 +107,45 @@ public class AndroidJUnitRunnerTest { mAndroidJUnitRunner.buildRequest(b, mStubStream); Mockito.verify(mMockBuilder).addTestMethod("ClassName1", "method"); } + + /** + * Test {@link AndroidJUnitRunner#buildRequest(Bundle, PrintStream)} when + * class name and method name is provided along with an additional class name. + */ + @Test + public void testBuildRequest_classAndMethodCombo() { + Bundle b = new Bundle(); + b.putString(AndroidJUnitRunner.ARGUMENT_TEST_CLASS, "ClassName1#method,ClassName2"); + mAndroidJUnitRunner.buildRequest(b, mStubStream); + Mockito.verify(mMockBuilder).addTestMethod("ClassName1", "method"); + Mockito.verify(mMockBuilder).addTestClass("ClassName2"); + } + + /** + * Temp file used for testing + */ + @Rule + public TemporaryFolder mTmpFolder = new TemporaryFolder(); + + /** + * Test {@link AndroidJUnitRunner#buildRequest(Bundle, PrintStream)} when + * multiple class and method names are provided within a test file + */ + @Test + public void testBuildRequest_testFile() throws IOException { + final File file = mTmpFolder.newFile("myTestFile.txt"); + BufferedWriter out = new BufferedWriter(new FileWriter(file)); + out.write("ClassName3\n"); + out.write("ClassName4#method2\n"); + out.close(); + + Bundle b = new Bundle(); + b.putString(AndroidJUnitRunner.ARGUMENT_TEST_FILE, file.getPath()); + b.putString(AndroidJUnitRunner.ARGUMENT_TEST_CLASS, "ClassName1#method1,ClassName2"); + mAndroidJUnitRunner.buildRequest(b, mStubStream); + Mockito.verify(mMockBuilder).addTestMethod("ClassName1", "method1"); + Mockito.verify(mMockBuilder).addTestClass("ClassName2"); + Mockito.verify(mMockBuilder).addTestClass("ClassName3"); + Mockito.verify(mMockBuilder).addTestMethod("ClassName4", "method2"); + } } |