I want to verify that a string retrieved from a DB entry is not present anymore after the entry in DB changed, I am using following statement for this:
onView(allOf(withText("oldname"), withId(R.id.title))).check(doesNotExist());
According to the espresso documentation and other posts I saw this should work, but I am getting following error:
android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (with text: is "oldname" and with id: com.myco.myapp:id/apkName)
The problem is that you're looking for a View with the text "oldname" and then trying to assert that it doesn't exist, but this doesn't work because the View doesn't exist (so you can't assert anything on it).
Where you go from here depends on exactly what you're trying to accomplish. If the view should not be there at all:
onView(withId(R.id.title)).check(doesNotExist());
If the view should be there, but without that text:
onView(allOf(not(withText("oldname")),withId(R.id.title))).check(matches(isDisplayed());
Or a variation of that:
onView(withId(R.id.title)).check(matches(not(withText("oldName"))));
The first variation says "make sure that there's a view with that id and not that text". The second variation says "make sure that the view with that id doesn't have that text".
Related
When I add a view to xml (layout) of my activity, it takes an id, so I can use that id in code of activity to recognize it and change my view if I like. Android make an R.class as an intermediate between my activity code an my layout(xml), so I use R.class for example:
findViewById(R.id.textView);
But how does android find it is a TextView? For example, if I write:
Button b = findViewById(R.id.textView);
I get an error. From where does it find I write it wrong?
I mean in R.class it define my id so android know a new id is defined in my xml, and I use it to return an object of View class or class extend View. But how does it find I am writing wrong and it is not a button, before I run the program (in compile time)?
Android Studio runs Android lint checks on your code, and there's the WrongViewCast check to detect such issues and report them as errors:
WrongViewCast
-------------
Summary: Mismatched view type
Priority: 9 / 10
Severity: Error
Category: Correctness
Keeps track of the view types associated with ids and if it finds a usage of
the id in the Java code it ensures that it is treated as the same type.
Source: http://tools.android.com/tips/lint-checks
If your view, that is returned by findViewById(R.id.ID), doesn't cast to the field you're assigning the view to, your code won't even compile! Android Studio checks your assigned variables and tries to cast them in real-time, but if that fails, because you made a mistake, your Activity.java can't compile! This is just a way of how this IDE operates.
Some time ago, you needed to cast the view manually, like this:
(TextView) findViewById(R.id.text_view)
But this is not necessary anymore.
In short, I'm trying to match view with ID like R.id.signCheckbox using Espresso. When I try to match that view I will get NoMatchingView exception when it's clear that view is present.
After some debugging, I've found out that inside my test class when I eval R.id.signCheckbox I'll get ID: -1000984. Inside cause of the NoMatchingViewException you can actually read whole view hierarchy in some format. There I've found that checkbox has different ID 2131362821. I've read the project R.java and it's also assigning 2131362821 to R.id.signCheckbox.
So when I match withId(2131362821) it's actually working. Why it's not working with R.id.signCheckbox and where that -1000984 id comes from?
It looks like the good old Invalidate/Restart/Clean/Rebuild fixed the problem.
The IDs are still negative (like -1000984) not matching the R.java IDs, but Espresso will successfully match the views.
According to this thread I need to use #+id/ for the first time to make resource be created.
But what if I forget that this resource was previously created and create it again with #+id/? I have some input and set nextFocusDown for the element that is still not declared.
<EditText
...
android:nextFocusDown="#+id/myinput2"/>
200 lines below I create this element with #+id because I forgot that it's already declared.
<EditText
...
android:id="#+id/myinput2"/>
It works like this but can it cause an issue?
Some quick definitions:
#+id/foo means "use the id foo, and create it if it doesn't exist"
#id/foo means "use the id foo" (which will be an error if the id foo doesn't exist)
Previously, there were reasons to prefer #id over #+id (the system could tell you if you tried to reference a view via an id that didn't exist), but now the system is smart enough that even writing android:layout_below="#+id/idthatdoesntexistanywhere" will be tagged as an error:
So just always use #+id.
It works like this but can it cause an issue?
No, it can't. Always use #+id/. By now, the Android build environment is smart enought to figure it out.
If you put two elements with the same id in the same layout file, it generates an IDE error (red underline) and you won't be able to compile.
I'm creating my first android app and i have a few layouts so far. In one of them i created a TextView and named it "textViewCurrentUserName". For my surprise, when i created a new layout, inserted a new TextView and try to name it "textViewCurrentUserName" i got a error stating that the name already exists!!! This has got to be a bug right?!? i mean, ok to "no repeat" on the same layout (xml), but these are totally different layouts!!!
Am I doing something wrong here?!? Is there a workaround this??? i dont want to keep a totally idiotic and hard-to-read/understand name such as "activity_UserDetails_TextViewCurrentUserName" and "activity_UserExport_TextViewCurrentUserName"
The Android ID field creates a unique ID for each UI element and stores them in the R file. Since fragments/activities and layouts and fairly decoupled, the app itself won't know which layouts and UI elements are available. Thus, you must explicitly state which element you're looking for. The app will throw an exception if the specified UI element is not currently available (or, perhaps, the element will be null).
The only workaround is to develop a naming convention. One might use [fragment-name]_textViewCurrentUser to allow each text view to have a unique ID. Or perhaps you can put a lowercase "t" in front of each UI element that is a text view: [fragment-name]_tCurrentUser.
until now I couldn't find any answer that suits my problem/question.
In android studio it often shows a notice that e.g. findViewById may produce a NPE, althogh i know the item IS existing in the layout I use.
I also never got a NPE thrown at this locations at runtime, so why the warning/notice?
I just don't know how I have to react/handle to such warnings/infos in the code view? Are there any tips to avoid that messages (because for me it looks like valid and working code)? It's only the warnings in the code view, that makes me uncertain.
Here a snippet where a warning is shown on findViewByID.
//fetch predefined item layout
row = inflater.inflate(R.layout.view_searchresult_item,null);
//get table layout for inserting items
TableLayout itemtablelayout = (TableLayout)row.findViewById(R.id.resultitem_tablelayout);
Warning is not an Error. And the warning which you are talking about says "it may produce", don't say 'it must produce'. So choice is yours. Either add null check or not
So, If you are sure that findViewById in your code will never be cause of NPE, then don't add the null check.