Resource files not available when running tests from Android Studio - android

When I run my JUnit (4.12) test in a java Gradle module from within Android Studio, it appears that neither the main/resrouces, nor the test/resources are available on the classpath.
I tested this by creating main/resources/test_dir/foo.txt and test/resources/test_dir/bar.txt. In my test method I check whether either one can be read:
InputStream fooStream =
Thread.currentThread().getContextClassLoader().getResourceAsStream("test_dir/foo.txt");
InputStream barStream =
Thread.currentThread().getContextClassLoader().getResourceAsStream("test_dir/bar.txt");
if (fooStream == null && barStream == null) {
throw new Error("resources unavailable");
}
My Gradle module (a dependency to my android app module) that this test code is contained in is named data. When I execute tests from the command line (./gradlew :data:test --rerun-tasks), the build is successful. When I launch the same tests from Android Studio, the test fails with the above Error being thrown.
How can correctly launch my tests from Android Studio?
Below, You'l find my test run configuration.
I also found this Android Studio bug report. Could that be the cause?

Related

Android: after Gradle update to 6.7.1 ClassLoader in JUnit test no longer lists all resources

I need to iterate over specific classes from main package in my android unit test, to check some of their properties.
For this I use standard approach, using ClassLoader:
val classLoader = Thread.currentThread().contextClassLoader
val resources: Enumeration<URL> = classLoader.getResources("com/models/package")
assert(resources.hasMoreElements()) // Fails from CL, works in AS
Before the Gradle update (had Gradle 5.6.4) that worked. Now the behaviour is as follows: it works when test is run from Android Studio, but fails (returns empty enumeration) when run from command line with gradlew.
I wonder what might be the difference in this respect between the two Gradle versions? And why it still works when run from Studio?
Some considerations and things I have tried:
Referencing these classes in unit test works ok, and also classLoader.findClass("com.models.package.MyModel") and
classLoader.loadClass("com.models.package.MyModel") from unit test is working. But even after that classLoader.getResources("com/models/package") returns empty enumeration.
Using other references to ClassLoader, like MyModel::class.java.classLoader and ClassLoader.getSystemClassLoader() didn't make any difference.
Gradle build from command line contains the warning "OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended", but as far as I can tell it's not connected to my issue.
If I put some of the classes from 'com/models/package' to the unit test /test folder, they are getting returned in enumeration.
This might be connected with some new optimisation setting that makes ClassLoaders omit registering some of the classes, in different root directories, but as it still works in AS there might be some setting to turn this optimisation off in a command line build also?
Thank you for any suggestions on this.
In Gradle 6.7.1 I had to include the directory with the code to the test sourceSets. Afterwards the classloader from junit started to see the classes and return them in Enumeration.
sourceSets {
test {
java.srcDirs += ['src/main']
}
}

How to make Android Studio 1.1 call generateDebugTestSources instead of assembleDebugTest during "Make" instruction?

I have a project with 1,000+ tests running fine with Robolectric. After switching to Android Studio 1.1 when I go to "Run" -> "All Tests" during the "Make" instruction Android Studio calls Gradle's assembleDebugTest instead of generateDebugTestSources .. In my case this makes the build system to start dexing and packaging the test APK which is useless for me since all the tests are JVM tests.
I found this change that might be causing it:
- if (testCompileType == TestCompileType.ANDROID_TESTS) {
+ if (testCompileType != TestCompileType.NONE) {
String gradleTaskName = properties.ASSEMBLE_TEST_TASK_NAME;
if (StringUtil.isNotEmpty(gradleTaskName)) {
tasks.add(createBuildTask(gradlePath, gradleTaskName));
Is there a way to make it configurable on Android Studio? Version 1.0 was working fine.
Thanks!
If someone is interested in the solution according to the new Unit Testing guide:
http://tools.android.com/tech-docs/unit-testing-support
you need to change the test artifacts to "Unit Testing" as describe on step 5. That way when you run all the tests AS will call the new assembleDebugUnitTest task instead of assembleDebugTest.

Xamarin.UITests Android Device Not Detected or Not Working

I can't run Xamarin.UITests on any Android simulator/emulator. Any suggestions? I get the following errors when I try:
Google Emulator:
SetUp: System.Exception: Unable to run on a physical device without activation.
The full version is available for Xamarin Test Cloud customers, for more information contact sales#xamarin.com
If you are already a Xamarin Test Cloud customer, you can provide your api in one of the following ways:
* Adding it ConfigureApp using the ApiKey method
* Setting the XTC_API_KEY environment variable
* Adding the following attribute to your Properties/AssemblyInfo.cs file: [assembly: Xamarin.UITest.TestCloudApiKey(YOUR_API_KEY)]
* Place an xtc_api-key file containing your api key in an upstream directory from the test assembly
Xamarin Android Player:
SetUp: System.Exception: No devices connected
GenyMotion:
SetUp : System.Exception : Failed to execute: /users/erikandersen/Library/Developer/Xamarin/android-sdk-macosx/platform-tools/adb devices - exit code: 1
cannot bind 'tcp:5037'
ADB server didn't ACK
* failed to start daemon *
error:
adb server is out of date. Killing…
After updated GenyMotion to 2.3.1, I now get the following error:
SetUp: System.Exception: App Installation failed with output: 12050 KB/s (11199602 bytes in 0.907s)
pkg: /data/local/tmp/final-xxxxxx.apk
Failure [INSTALL_FAILED_CPU_ABI_INCOMPATIBLE]
NUnit Code
AndroidApp _app;
public string PathToAPK { get; set; }
[TestFixtureSetUp]
public void BeforeAll ()
{
var path = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
var info = new FileInfo(path);
var directory = info.Directory.Parent.Parent.Parent.FullName;
PathToAPK = Path.Combine(directory, "Android", "bin", "Debug", "Demo.Android.apk");
}
[SetUp]
public void BeforeEach ()
{
_app = ConfigureApp.Android.ApkFile (PathToAPK).StartApp ();
}
[Test]
public void TestInvalidEmail ()
{
_app.EnterText (c => c.Class ("UITextField"), "");
}
TestInvalidEmail() is never called because NUnit fails on
_app = ConfigureApp.Android.ApkFile (PathToAPK).StartApp ();
Background:
I'm using Xamarin.UITests for an iOS/Android application I'm developing and we're having issues with the Android side of things. iOS works fine. I've written each test twice, once in C# and once in Ruby using calabash, in order to isolate the issue. Calabash works fine, but any C# NUnit Test Project fails to connect to any emulator I try launching.
What I've tried:
Making sure an emulator is already running before I run the tests
Making sure only 1 emulator is running
Restarting the adb server
Trying multiple types of emulators (i.e. Xamarin Android Player, Gennymotion, and the Google Emulator)
So, after several hours of working on this, this fixed it:
Upgrade GennyMotion to 2.3.1
Delete my old GenyMotion Simulator (Nexus 4) and create a new one
Add support for all ABIs in my Android Build settings
Android Project > Options > Android Build > Advanced Tab > Supported ABIs > Check "armeabi, armeabi-v7a, x86" > OK
Generate a new .apk file via the terminal (while inside the Android project directory)
/usr/bin/xbuild /t:Package /p:Configuration=Release .csproj
Resigned the .apk via calabash-android
calabash-android resign ./bin/Release/.apk
In Xamarin Studio, set my Startup Project as the my UITest project
Launch GenyMotion simulator
Ran the tests under the Debug configuration with only the GenyMotion simulator active
And it worked! I still can't run UI tests with the Google Emulator or the Xamarin Android Player. Funny thing is, I also can't debug my Android project using GenyMotion. It's only good for UITests. SO here's my current setup:
Xamarin Android Player - Normal debug
GenyMotion - UITests
I had the same problem and fixed by setting the ApiKey when setting ConfigureApp.
[SetUp]
public void SetUp()
{
_app = ConfigureApp.iOS.AppBundle(PathToIPA).ApiKey("YOUR_API_KEY_HERE").StartApp();
}
As in here. Just put your ApiKey there.
Note: I didn't have this problem with Xamarin Android Player. I didn't have this problem with AVD running an Android 5.0 emulator. I only had this problem with AVD running an Android 4.0.3 emulator.

Testing an android app generating specific xml junit file

I'm using Android Studio and the gradle plugin to build apps from the command line.
Now, suppose I want to run tests on my connected devices, I run:
./gradlew app:connectedCheck
and it will output a junit report XML file on:
./app/build/outputs/androidTest-results/connected/flavors/latest/TEST-Galaxy Nexus - 4.3-app-Latest.xml
This is almost what I want. Just that I would like to specify for example this test output file. For example, I would like to output it to $HOME/junit.xml. And I would like to specify this $HOME/junit.xml from the command line.
How do I do this?
You can specify the output directory for test reports using
android {
testOptions {
reportDir = "$project.buildDir/foo/report"
}
}
http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Test-reports

Android Unit Test Not Reporting Failing with fail()

I've written a unit test that simply extends TestCase and I have the following:
public class MetricParserTests extends TestCase {
#Override
protected void setUp() throws Exception {
super.setUp();
}
#Override
protected void tearDown() throws Exception {
super.tearDown();
}
public void testFailure() {
fail("This needs to fail");
}
}
When I run my tests using ant test or adb shell am instrument I get the following results:
... [exec] OK (1 tests) ...
I'd expect to see a failure on the command line.
I believe I know what the issue is. I was able to reproduce the issue and solve it. The command you use does not rebuild and re-install your test project onto a device. When you call ant test it will just execute the tests which are already installed on that device.
What you need to call is the three commands in your test project's directory:
ant debug
ant installd
ant test
Then all tests will be rebuild and re-installed and latest tests will be executed. If you don't call debug and installd, the changes you did to the tests do not get applied.
I haven't had recent experience in Android testing, but here is what I have found...
You can use normal JUnit tests if your code is totally decoupled from Android (see here
for an example). This would run on your JVM using the JUnit runner.
However, if you are trying to run these tests on an Android device (either via ant, or the command line tools) then you need to create a full android test project (See here).
To test "on device" your test cases need to extend one of the Android test classes like ActivityInstrumentationTestCase2<T>
and are run using the InstrumentationTestRunner in the Dalvik VM on the Android device.
Using an IDE or the command-line tools to create a test project should create a sample test for you to work from.
This blog post linked from the comments of the post above is a good source of information, as is the Android Testing Fundamentals doc.
The method testFailure() does not have a #Test annotation. Is that correct?

Categories

Resources