Trying to use MonkeyRunner to perform some testing and want to use AndroidViewClient to work with EditText widgets.
I believe I am using AndroidViewClient correctly (relevant stuff below), findViewByIdOrRaise() is always throwing an error. I've tried every variant of specifying an ID that came to mind.
Here is a snippet from my activity's XML:
<EditText
android:id="#+id/someText"
... >
<requestFocus />
</EditText>
<!-- Yes, that is the actual id of my EditText -->
In my MonkeyRunner script I have the following:
device, serialno = ViewClient.connectToDeviceOrExity(serialNo=myDeviceId)
vc = ViewClient(device=device, serialno=serialno)
device.installPackage(apkPath)
device.startActivity(component='com.app.name/com.app.name.ActivityName')
editTextId = 'id/someText'
try:
someText = vc.findViewByIdOrRaise(editTextId)
someText.touch()
someText.type('Derp derp derp')
except ViewNotFoundException, e:
# The comma above is because Jython 2.5.3 does not support the AS keyword
print ' [*] %s' % (e)
Of course, my code is doing a little more (but not much) than what is shown. I stripped out everything that didn't seem relevant. I will gladly put it all up there, but didn't want to start off with code vomited all up in here.
I've looked at everything I could find on the topic:
AndroidViewClient / AndroidViewClient / examples / email-send.py
monkeyrunner: interacting with the Views
How to enter text in text field using monkeyrunner
How to enter values to a text field using monkeyrunner
Any ideas on what I'm doing wrong?
The latest version of ViewClient gives a unique id to each view in the app. The id format is i/no_id/number. You could use a script called dump.py to see the current views. It is located in the examples folder in ViewClient.
Related
I would like to write some UI Test on my Android application in order to take automated screenshots.
My application is written with React-Native.
In order to write my tests in need to know the resource-id of my component but as you can see in this screenshot i can't see any resource-id with ui Automator Viewer in this React-Native example app.
Look this picture.
I would like to know if there is a way to give some IDs to my components so I can write some test or if there is another way to select my components.
Note : I'm trying to write Espresso Test.
The testID only works on iOS, and is not mapped to the resource-id in Android.
You can specify an accessibilityLabel to your component. In uiautomatorviewer it shows up as content-desc
To be cross-platform, you should specify both:
<Text style={styles.welcome} accessibilityLabel="MyId" testID="MyId">
Welcome!
</Text>
You can then search for it using something like webdriver with the tilde selector browser.waitForExist("~MyId")
First of all, ID of each UI Component of Android objects has to be defined in the resource(res) folder as layout XMLs(you need to make sure you have defined it in the right tags) and to obtain the IDs in the Android please follow the steps:
1. Launch Android Studio, Click on "Android Device Monitor" icon next to "SDK Manager"
2. Connect your device and launch the application
3. Select your device name from the list of devices on the left panel
4. Click on Dump "View Hierarchy for UI Automate"
5. Now you can hoover over any view on thde device dump and can see Resource-d in the node details in the right column.
Note: You can also take screenshots
1)First thing first if its your project you can go to the layout and add id to these component and then take screenshot using uiautomator viewer you will find your resource id
2) If option 1 is not possible(that's highly unlikely to happen) you can still test it as from your screenshot i can see only one edittext box so using uiauatomator you can test it on the basis of the class . Here below is the code:
private static UiDevice mDevice;
func(){
mDevice = UiDevice.getInstance(getInstrumentation());
UiObject xyz=new UiObject(new UiSelector().**getClass**(android.widget.EditText));
xyz.click();
xyz.setText("abcdef");
}
// I am not sure its getclass() or getclassName() check both option
//xyz.click() is necessary as in uiautoamtor you won't be able to right text
in a textbox until and unless it is selected
Yes there is! You can pass a testID prop to any component that implements the <View /> props, as documented here.
testID string
Used to locate this view in end-to-end tests.
See also this very informative blogpost about UITesting in React Native. It is about iOS testing, but the javascript part is going to be the same for Android.
When running calabash-android and outputting to HTML format, I am getting intermittent exceptions as per the below (typically within the first step of the app). I am using Xamarin and MVVMCross libraries.
Timeout waiting for elements: * marked:'Terms of Use'
(Calabash::Android::WaitHelpers::WaitError)
./features/step_definitions/calabash_steps.rb:4:in `/^User has accepted the Terms of Use$/'
features\registration.feature:8:in `Given User has accepted the Terms of Use'
2
3Given /^User has accepted the Terms of Use$/ do
4 #current_page=page(TermsOfUse).await
5 #current_page.tap_accept_button
6end
7# gem install syntax to get syntax highlighting
The screenshots generated show the UI element is present on the screen, and the same errors never occur when I exclude the html format option and simply write the detail out to the console. Does anybody else have any experience of this?
Most likely the view's text has some formatting information in it.
It's a good practice to use id instead of text for identifying elements. If you have an id, use that:
query("* id:'terms_of_use_id'")
If you don't have an id try to add one.
If that is not possible try to query the whole UI with:
query("*")
Find the element and see what's in it's text property.
I am using MonkeyTalk to automate some user test cases for my Android app. Everything is working fine except for when I try and detect a button containing this string:
"Connect\n(Code Required)"
I get this error:
FAILURE: Unable to find Button(Connect\n(Code required))
If I change the button to "Connect" and perform a tap on that value MonkeyTalk has no trouble, but something about the line break must be throwing it off.
After some searching I found this thread that confirmed my suspicious about the line break. There was one suggested fix here, to set the default encoding to UTF-8 (Select the Project > File > Properties > Resources)
However this did not work for me.
I have also tried to find the button using a wildcard like so:
"*(Code Required)"
But this does not seem to be supported either.
Maybe there is an alternative line break character I could use?
Thanks in advance for the help!
Maybe there's a carriage return in there? I know in most text editors a new line actually consists of (carriage return)+(newline).
Also take a look at this:
TextView carriage return not working
Also, depending on how flexible your requirements are, you could use the #N MonkeyId replacement to get the Nth button.
IN javascript you can use below command
app.button("buttonname").tap(x, y);
Use android:contentDesxription="your_component_id" in your view xml file definition or view.setContentDescription("your_component_id"); directly on view in code to make it easy to access in MonkeyTalk.
Anyone knows a good tool for crawling the GUI of an android app? I found this but couldn't figure out how to run it...
Personally, I don't think it would be too hard to make a simple GUI crawler using MonkeyRunner and AndroidViewClient.
Also, you may want to look into uiautomator and UI Testing
Good is a relative term. I have not used Robotium, but it is mentioned in these circles a lot.
EDIT - Added example based on comment request.
Using MonkeyRunner and AndroidViewClient you can make a heirarchy of views. I think AndroidViewClient has a built-in mechanism to do this, but I wrote my own. This code tries to produce a layout similar to that used by the Linux tree command. The space and line variables are used to setup the "prefix" prepended on each line. Of course, this code uses a depth-first, recursive traversal.
def printViewListDepth(view, depth=0):
space = '|' * int(not depth == 0)
space += (' ' * 2 * (depth-1)) + '|' * int(not depth-1 <= 0)
line = '_' * int(not depth == 0) * 2
text = view.getText()
text = text[:10] + int(len(text) > 10) * '...'
print " [*] %s%s%s %s %s" % (
space, line, view.getUniqueId(),
view.getClass().replace('android.widget.', ''), text)
for ch in view.children:
printViewListDepth(ch, depth+1)
You call printViewListDepth as follows, using a ViewClient returned by AndroidViewClient:
printViewListDepth(viewClient.root)
Note that in the above implementation, the class of View is truncated, by removing "android.widget." and the the text of a View is truncated at 10 characters. You can change these to suit your needs.
Edit Crawling the GUI
With AndroidViewClient you can query whether a View is clickable, someView.isClickable(). If it is clickable, you can invoke a touch event on it, someView.touch(). Assuming most button clicks open a different Activity, you will need to come up with a mechanism of getting back to where you came from to do the recursion.
I imagine that it can be done with some effort, but you may want to start with something as simple as invoking a BACK button press, device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP). You will probably need to handle application-specific special cases as they arise, but this should get you off to a decent start.
You can take a look at Testdroid App Crawler
This is available in Testdroid Cloud as project type and you can easily run it on 15 free devices.
Clicked on create filter could not figure out from docs how to create a filter for say two or more tags. If I have two tags com.test.TestClassA and com.test.TestClassB how do I create a filter that shows log for both of these classes? I saw how you can start ADB for only certain tags, but how can this be done in eclipse? Please provide details thanks. What exactly do I need to enter on the tag line when creating a new filter in eclipse?
As pointed by Brain Reinhold you can combine tag filters with vertical bar | (which obviously means logical "OR"). You can also use that (as well as other Regex) syntax in the logcat search box (by preceding tags with tag: prefix):
tag:com.test.TestClassA|com.test.TestClassB
More complex filtering is also possible. For example here is the search filter that displays messages from either android.process.media or com.android.camera apps, which have at least one digit (\d) in the message text and are tagged with either dalvikvm or AndroidRuntime tags:
app:android.process.media|com.android.camera tag:dalvikvm|AndroidRuntime text:\d
One short and useful filter is tag:^(?!dalvikvm) which removes all those noisy Dalvik logs.
It's also worth mentioning that you can quickly disable any part of the filter by placing vertical bar at the end of the part you wish to disable (e.g. placing | right after app:android.process.media|com.android.camera in the example above effectively disables filtering by application name while still preserving filtering by tags and text).
In the latest version of the SDK for Eclipse which now shows two versions for logcat (one deprecated); in the undeprecated version one can combine filters using OR bars: |.
For example when clicking on the + and bringing up a dialog to create a new filter, give your filter a name and then in one of the fields (for example TAG) enter com.lampreynetworks|Bluetooth and you will see output for all tags containing com.lampreynetworks and Bluetooth. The '*' is implicit here as if any part of the TAG contains any of that text it will be displayed. Also note, there must be no spaces between the OR bars!
I have not tried combining the 'by TAG' and 'by (some other option)' but somehow I have a feeling that will not work.
On Feb 12, 2:58 am, AndroidDevTime wrote:
If I have two tags
com.test.TestClassA and com.test.TestClassB how do I create a filter
that shows log for both of these classes?
The "Log tag" field accepts Java regular expressions, so do this:
^com.test.TestClassA$|^com.test.TestClassB$
which matches exactly those tags you specified. You could be more economical/efficient/whatever with the regular expression, depending on how much you want to muck around with that.
It is not possible right now.
#see http://groups.google.com/group/android-developers/browse_thread/thread/17356ef7bdf1550f?pli=1
I also wish it were...
I just do it from the command line. Having a different terminal for each adb filter. Then if you line them up side by side you can get a good idea of what is happening.
The only way I have seen is Create a Filter using PID so that evey log message of your application will be displayed in that Filter. I wonder if this is possible through tag names in the current version of the ADT for eclipse.
Use proclogcat: http://devtcg.blogspot.com/2010/04/logcat-improved.html
It lets you filter by your package name instead.