What is the simplest way to create a UI test in Android Studio that can take screenshots when I need it to? - android-studio

I am trying to create a UI test in Android Studio which will navigate through the various screens of my application and take screenshots when I tell it to.
I am new to Android Studio and Android programming in general; I have a decent understanding of XML and Java, but I don't know much about build files and I am not very good at using Android Studio, it seems.
I started this endeavor a couple weeks ago, and the first solution I tried was to use uiautomator. However, the documentation on that page (and seemingly just about everywhere else) is geared towards development with Eclipse, which I would like to avoid using for this project if possible.
The next thing I tried was Espresso. After I overcame some issues with implementing Espresso into my project, I was able to write tests with Espresso which would navigate through the screens of my application. However, unlike uiautomator, Espresso does not have built-in functionality to take screenshots at this time.
I first attempted to solve this problem of being unable to take screenshots with Espresso by writing custom code; as I'm still unfamiliar with Android, I wasn't really sure how to go about that, so I searched for help on the Internet (How to programmatically take a screenshot in Android?). However, I was unable to get the solutions I found to function from inside the test file.
Somebody recommended the usage of this tool: https://github.com/rtyley/android-screenshot-lib but I could not figure out how to import that into my project.
I eventually came back to uiautomator; I was still having a lot of trouble importing it into my project, and some people said that Robotium would help with that. I got Robotium to work, but I still could not import uiautomator.
It has been probably one month since I started using Android Studio, and in that time, I've had nothing but trouble simply getting the software to function properly. For the sake of brevity, I've omitted all the problems I have managed to solve on my own, but, to put it bluntly, I'm at the end of my patience.
TL;DR
If somebody could either:
-explain in the simplest possible way how to import uiautomator into an Android Studio project (I have read a lot of documentation about how to import external libraries into a project, but they all tell me to add a 'libs' folder to my project, but do not specify which type of folder to use [Java Resource Folder? Assets Folder? Module? etc.], and/or they tell me to go into Project Structure, select my app, go to dependencies, and choose "Import as Module," which does not work...)
OR
-explain how best to take a screenshot from inside of an Espresso test, including any instructions on how to import any required libraries
OR
-explain in detail some other way to create a UI test that can take screenshots...
...I would really appreciate it. I've spent days trying to figure out how to do this, and I am so frustrated. Many people have asked similar questions, but the answers are either too vague or the problems aren't close enough to my own.
Thanks!

Alright, after much trouble, I've found a very simple solution. It took me a very long time to work out, but if anyone else needs to do something similar, I'll put my conclusion here.
First of all, the testing framework that is easiest to use with Android Studio, it seems, is Espresso. Setting up Espresso is fairly simple; most of the instructions can be found here: https://code.google.com/p/android-test-kit/wiki/EspressoSetupInstructions Make sure you read it carefully -- it tells you basically everything you need to know, but I missed some important details and that caused me a lot of trouble.
If you browse around that Espresso site, it tells you just about everything you need to know about how to write Espresso tests. It was a little frustrating for me because, if I wrote a test and the test failed, my device would then have connection issues with my laptop and I would have to disconnect and reconnect the USB cord I was using. I think this had something to do with the fact that I was using a Nexus 7 with a Windows 8 laptop, which has given me some problems in other areas, so you may not encounter this issue yourself.
Now, unlike uiautomator, the documentation of which claims to have support for taking screenshots, Espresso does not have built-in support for taking screenshots. That means you'll have to figure out a different way to take screenshots. My solution was to create a new class (called HelperClass, in my case) inside my androidTest package and add this method to it.
public static void takeScreenshot(String name, Activity activity)
{
//slightly modified version of solution from http://www.ssaurel.com/blog/how-to-programmatically-take-a-screenshot-in-android/
//I added "/Pictures/" to my path because that's the folder where I wanted to store my screenshots -- you might not have that folder on your device, so you might want to replace "/Pictures/" with just "/" until you decide where you want to store the screenshots
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/" + name;
View v = activity.getWindow().getDecorView().getRootView();
v.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false);
OutputStream out = null;
File imageFile = new File(path);
//the following line will help you find where the screen will be stored on your device
Log.v("Screenshot", "The image file path is " + imageFile.getPath());
try {
out = new FileOutputStream(imageFile);
// choose JPEG format
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
} catch (FileNotFoundException e) {
// manage exception
} catch (IOException e) {
// manage exception
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception exc) {
}
}
}
In order for this function to work, you will also have to add the following line to your manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Without that, the function above will throw a FileNotFoundException every time you run it.
Finally, to call the takeScreenshot function from inside your Espresso test code, use this line (assuming you called your class HelperClass... if not, use the name of your class instead.
HelperClass.takeScreenshot("Whatever you want to call the file", getActivity());
Finding where your screenshots are stored can be a little difficult if you don't know where to look. I added a line of code to the takeScreenshot function that would print the filepath to LogCat, but I was using the file explorer on my computer to look for the screenshots on my Nexus (which was, of course, connected to the computer), and I couldn't find that path. However, I got a file explorer application on my tablet which made it very easy to find where the files were located in relation to everything else.
My solution may not be the simplest and it certainly isn't the best -- you'll fill your device up with screenshots before long if you aren't careful to delete the ones you don't need anymore, and I haven't got any idea how one would go about saving the screenshots directly to, say, a computer connected to the tablet via USB. That would certainly be helpful. However, if you really need a simple UI test that takes screenshots, and you're frustrated to no end like I was, this solution should probably help. I certainly found it useful.
I hope this helps somebody else -- it definitely solved my problems, at least for now.
Of course if you don't have all the restrictions that I did when I had to write a UI test that took screenshots, the other posts in this thread probably work much better.

You should give AndroidViewClient/culebra a try. Using culebra GUI, you can automatically generate a test case that interacts with your app and takes screenshot exactly when you indicate so.

Related

Why won't my one simple custom user Python snippet '__init__' appear in IntelliSense?

I've spent the last two hours trying to figure this out, but nothing I've found online helps. Either all search results I've found were severely outdated, not relevant to my problem, or didn't work.
I am a complete beginner to Python, so please try to make your suggestions/solutions/answers understandable enough for me (i.e. draw them in crayon if you must.:)) I want the init method to not autocomplete all of this:
__init__(self, *groups: _Group) -> None:
super().__init__(*groups)
I want it to simply autocomplete as "init()" and that's it, nice and clean for what I'm currently doing.
Searching around, looking at other python snippet extension files, and even using a snippet generator, I've
found that this should be the code that I should use:
"__init__ method":
{
"prefix": "__init__",
"body": ["__init__($0)"],
"description": "New __init__ method"
}
I've created a global.code-snippets file and even a python.json file with Configure User Snippets, both of which are located in C:\Users<myusername>\AppData\Roaming\Code\User\snippets. However, it does not show up when I type out init, instead I still get the default suggestions:
Default init suggestions
What am I missing? I didn't think this would be so difficult.
I've looked at https://code.visualstudio.com/docs/editor/userdefinedsnippets, I've tried https://snippet-generator.app/, I've checked out other Python snippet extensions to see how they were written out.
A bit more digging around and using different keyword searches this morning brought me to IntelliSense in Visual Studio Code, and 3/4 of the way down there was Suggestion selection which said to use the editor.suggestSelection setting. Turns out it was disabled. Once I enabled it, both my python.json and global.code-snippet suggestions showed up.

ADB debugging in Android Studio - some basic issues

Ok, I've squeaked by not needing to use ADB in the Studio, since back
in the 'beta' days of AS. (Just lucky, I guess.) But now, I need to
debug a crashing app.
I've gotten this far:
Learned how to put adb.exe on my Window's 'PATH'
(so that it's invokable from cmd-window):
My path-entry was: C:\Users\David\AppData\Local\Android\sdk\platform-tools
Am assuming that 'logcat' lives on Android device (I was incorrectly guessing it lives on the development machine). I'm assuming this, because when I dis-connect
the USB-cable and enter 'adb logcat' is says waiting for device.
Ok, now my (next) issue: When I fire up the app-being-developed, I'm getting
"Unfortunately has stopped"...which I'm assuming is an app-crash.
And, while I'm looking at 'logcat', I can see a stack-trace flow by. But
as I try to scroll-back to read it, logcat keeps dribbling in more data.
So, how do I tell it to shutup...so that I can look at a static copy
of logcat and see what has happened (without more data dribbling in)?
[If there is other beginner related info, beyond this question, feel free to
to add that info...I'm clearly in need of basic 'adb-related' enlightenment.]
TIA.
Cheers...

Windows Store TriageDump.dmp without debug information

Greetings people,
My Windows Store game has been released for more than three weeks now, and I started getting crash reports. I could download the TriageDump.dmp file and have it opened in Visual Studio 2012, but it did not help much, I am constantly getting "No Debugging Information" error message when I click on "Debug with Native Only":
Also, the tool-tip on my Dashboard shows no information of the crashing function (could "Unknown" here mean inlined function or lambda expressions in concurrent::task?):
I would like to believe that I have done everything the way it should be done, of course I may be wrong. Here are some additional information that might be helpful in finding the issue:
It uses DirectX and written purely in C++ (without C# or XAML)
Project setting: C++\General\Debug Information Format = Program Database (/Zi)
Project setting: Linker\Debugging\Generate Debug Info = Yes (/DEBUG)
The game is made up of two native modules: Labyrinth.App.exe and Labyrinth.Core.dll
The generated APPXUPLOAD contains both APPX and APPXSYM files
The APPXSYM file contains both Labyrinth.App.pdb and Labyrinth.Core.pdb
I'm on x64 development machine, and the triagedump.dmp is for x86
I did click on "Include public symbol files, if any, to enable crash analysis for the app" when generating APPXUPLOAD file:
Please let me know if you spotted the issue or suspected something that's wrong above. Thanks in advance for your help, guys! :)
The very same problem here. MS had that working in the past though.
Actually if you still have the .appxsym around you can easily extract the .pdb out of that. The appxsym is just a .zip file it seems.
You can load these pdbs then as symbols after loading the triagedump.dmp.

Build is producing a .momd in the bundle that is missing the .mom file

I have an app that has been running fine on the iPhone simulator for some time. Recently, I decided I wanted to re-use the data model and related classes in another project - so I dragged them from this project window to the other then told Xcode not to copy, just to make references. At first this didn't work so I jumped through a number of hoops to try to fix it (I may be asking more about that in another post). After all this, I re-compiled and tried to run the original app -- and it's not working any more. On further investigation, I discovered that when I re-compile the original app, I end up with a bundle that contains a .momd package but it contains only a Versioninfo.plist file - no .mom file, no .omo file like I'm expecting to see. I don't recall making any changes to the original app. I don't get any warnings. I just get an incomplete .momd package (and, not surprisingly, my app now crashes).
What's going on here?
BTW, the app now crashes with this message:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Which I get when executing this line of code:
self.productRegistry = [[UIManagedDocument alloc] initWithFileURL:self.productRegistryURL];
I figured this out by looking more closely at the file locations in the project directory using Finder. In the Xcode window, everything looks normal but in the actual project directory I found that the .datamodeld package had ended up at the top level of the project directory -- at the same level as the project package itself. Xcode apparently did not like this but unfortunately it did not complain -- it just created a partial build output. Once I moved the .datamodeld package into the same folder as the rest of the project's code, everything worked just fine.
This would appear to be just a quirk. I would expect that Xcode would either see that all is well and build correctly OR it would see that things weren't quite as they should be and fail. In this case, it did not build correctly but was silent about it.
Hope this answer helps someone else someday.

How to copy a folder, with exclusions, with native groovy?

This is easy enough to implement (will do it now unless someone answers real quick), but I'd always rather reuse than implement.
How can one recursively copy a folder in groovy, while excluding some folders/paths? I know this can be done with ant, but I think a simple native groovy code is nice to have as well.
Posting the code to use AntBuilder (Linked to from my comment above) in case the page disappears at a later date:
new AntBuilder().copy(todir: "dstFolder") {
fileset(dir : "srcFolder") {
include(name:"**/*.java")
exclude(name:"**/*Test.java")
}
}
Not sure if you meant that for some reaon you wanted to avoid using Ant completely however...

Resources