Status Update
Comments
tu...@gmail.com <tu...@gmail.com> #2
My workaround:
source files and data files:
src/test//java/me/ycdev/android/arch/lint/AbstractCheckTest.java
src/test//java/me/ycdev/android/arch/lint/MyToastHelperDetectorTest.java
src/test//java/me/ycdev/android/arch/lint/testdata/src/test/pkg/MyToastHelperTest.java.txt
public class MyToastHelperDetectorTest extends AbstractCheckTest {
...
}
public abstract class AbstractCheckTest extends LintDetectorTest {
@Override
protected InputStream getTestResource(String relativePath, boolean expectExists) {
String path = "testdata" + File.separator + relativePath; //$NON-NLS-1$
InputStream stream = AbstractCheckTest.class.getResourceAsStream(path);
if (stream == null) {
File root = getTestDataRootDir();
assertNotNull(root);
String pkg = AbstractCheckTest.class.getName();
pkg = pkg.substring(0, pkg.lastIndexOf('.'));
File f = new File(root,
"src/test/java/".replace('/', File.separatorChar)
+ pkg.replace('.', File.separatorChar)
+ File.separatorChar + path);
if (f.exists()) {
try {
return new BufferedInputStream(new FileInputStream(f));
} catch (FileNotFoundException e) {
stream = null;
if (expectExists) {
fail("Could not find file " + relativePath);
}
}
}
}
if (!expectExists && stream == null) {
return null;
}
return stream;
}
private File getTestDataRootDir() {
CodeSource source = getClass().getProtectionDomain().getCodeSource();
if (source != null) {
URL location = source.getLocation();
try {
File classesDir = SdkUtils.urlToFile(location);
// "<module root dir>/build/classes/test" --> "<module root dir>"
return classesDir.getParentFile().getAbsoluteFile().getParentFile().getParentFile();
} catch (MalformedURLException e) {
fail(e.getLocalizedMessage());
}
}
return null;
}
}
source files and data files:
src/test//java/me/ycdev/android/arch/lint/AbstractCheckTest.java
src/test//java/me/ycdev/android/arch/lint/MyToastHelperDetectorTest.java
src/test//java/me/ycdev/android/arch/lint/testdata/src/test/pkg/MyToastHelperTest.java.txt
public class MyToastHelperDetectorTest extends AbstractCheckTest {
...
}
public abstract class AbstractCheckTest extends LintDetectorTest {
@Override
protected InputStream getTestResource(String relativePath, boolean expectExists) {
String path = "testdata" + File.separator + relativePath; //$NON-NLS-1$
InputStream stream = AbstractCheckTest.class.getResourceAsStream(path);
if (stream == null) {
File root = getTestDataRootDir();
assertNotNull(root);
String pkg = AbstractCheckTest.class.getName();
pkg = pkg.substring(0, pkg.lastIndexOf('.'));
File f = new File(root,
"src/test/java/".replace('/', File.separatorChar)
+ pkg.replace('.', File.separatorChar)
+ File.separatorChar + path);
if (f.exists()) {
try {
return new BufferedInputStream(new FileInputStream(f));
} catch (FileNotFoundException e) {
stream = null;
if (expectExists) {
fail("Could not find file " + relativePath);
}
}
}
}
if (!expectExists && stream == null) {
return null;
}
return stream;
}
private File getTestDataRootDir() {
CodeSource source = getClass().getProtectionDomain().getCodeSource();
if (source != null) {
URL location = source.getLocation();
try {
File classesDir = SdkUtils.urlToFile(location);
// "<module root dir>/build/classes/test" --> "<module root dir>"
return classesDir.getParentFile().getAbsoluteFile().getParentFile().getParentFile();
} catch (MalformedURLException e) {
fail(e.getLocalizedMessage());
}
}
return null;
}
}
tn...@google.com <tn...@google.com> #4
This for reporting this. I hadn't noticed this earlier because in the other uses of this, each subclass (for example, in the base distribution, AbstractCheckTest) overrides getTestResource() to do its own handling.
Fixed for 1.4.
(FYI for most of the lint unit tests I'm gradually switching over to inlining test cases.
XML example:
https://android-review.googlesource.com/#/c/162737/3/lint/libs/lint-tests/src/test/java/com/android/tools/lint/checks/ManifestDetectorTest.java
Java example:
https://android-review.googlesource.com/#/c/166225/1/lint/cli/src/test/java/com/android/tools/lint/checks/SupportAnnotationDetectorTest.java
Fixed for 1.4.
(FYI for most of the lint unit tests I'm gradually switching over to inlining test cases.
XML example:
Java example:
an...@gmail.com <an...@gmail.com> #5
Hi Tor,
cool, thank you very much for pointing out the inline approach, I was not aware of this!
Btw, recently the Android (UI) testing have moved from the JUnit 3 approach of extending a certain TestCase super class to the JUnit 4 approach of rules [1] (e.g. ActivityTestRule, ServiceTestRule, ...).
I like this idea and I'm wondering if you have plans to switch to JUnit 4 too?
However I've implemented such rule already (also to expose Warnings for more powerful assertions). But it's nothing official of course:https://github.com/a11n/lint-junit-rule
Thank you,
André
[1]https://github.com/junit-team/junit/wiki/Rules
cool, thank you very much for pointing out the inline approach, I was not aware of this!
Btw, recently the Android (UI) testing have moved from the JUnit 3 approach of extending a certain TestCase super class to the JUnit 4 approach of rules [1] (e.g. ActivityTestRule, ServiceTestRule, ...).
I like this idea and I'm wondering if you have plans to switch to JUnit 4 too?
However I've implemented such rule already (also to expose Warnings for more powerful assertions). But it's nothing official of course:
Thank you,
André
[1]
Description
junit.framework.AssertionFailedError: ValidAndroidManifest.xml does not exist
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.Assert.assertTrue(Assert.java:22)
at junit.framework.Assert.assertNotNull(Assert.java:256)
at junit.framework.TestCase.assertNotNull(TestCase.java:426)
at com.android.testutils.SdkTestCase.getTestfile(SdkTestCase.java:447)
at com.android.tools.lint.checks.infrastructure.LintDetectorTest.lintFiles(LintDetectorTest.java:140)
I tracked this down to the following method call (LintDetectorTest, getTestResource(), line 344):
InputStream stream = LintDetectorTest.class.getResourceAsStream(path);
The problem here is the static reference of "LintDetectorTest.class" which, when calling getResourceAsStream(), uses the relative path to this class independent of the current class loader. For me this is something like "file:/<UserDir>/.gradle/caches/modules-2/files-2.1/com.android.tools.lint/lint-tests/24.3.0/7c8cee33fd3e03d8cc08caea030fed8a114f0289/lint-tests-24.3.0.jar!/com/android/tools/lint/checks/infrastructure/".
I came around this by overriding "getTestResource" in my test case and using "this.getClass().getResourceAsStream()". This way the correct test resources are loaded. With the static class reference I had no chance to "inject" my test resources and the tests were failing all the time.
I think it would simplify the usage of this library if you also switch to the ClassLoader approach.
[1]